🔔 Webhook İşlemleri
Endpoint
POST /api/return/webhook/complete-cardstorage/{type}/{id}
Açıklama
Kart saklama işlemi tamamlandığında çağrılan webhook endpoint'i. Bu endpoint, 3D Secure doğrulaması veya kart kayıt işlemi tamamlandıktan sonra sistem tarafından otomatik olarak çağrılır ve kart bilgilerinin başarıyla kaydedildiğini bildirir.
Path Parametreleri
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| type | string | ✅ | Webhook tipi (örn: "recurring", "paymentOrder") |
| id | uuid | ✅ | İşlem UUID'si |
Headers
Content-Type: application/json
X-Webhook-Signature: {hash}Request: CompleteCardStorageWebhookRequest
{
"ownerId": "OWN-123456",
"cardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"tenantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"hash": "a1b2c3d4e5f6...",
"hashFields": "ownerId,cardId,tenantId,timestamp",
"timestamp": 1708084800000
}Parametreler
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| ownerId | string | ❌ | Kart sahibi ID'si |
| cardId | uuid | ✅ | Kaydedilen kart UUID'si |
| tenantId | uuid | ✅ | Kiracı (tenant) UUID'si |
| hash | string | ❌ | Güvenlik hash'i (HMAC-SHA256) |
| hashFields | string | ❌ | Hash hesaplamasında kullanılan alanlar |
| timestamp | integer | ✅ | Unix timestamp (milisaniye) |
Response
Başarılı İstek (200 OK)
{
"success": true,
"message": "Card storage completed successfully"
}Hash Doğrulama
Webhook güvenliğini sağlamak için gelen isteklerin hash değeri doğrulanmalıdır.
Hash Hesaplama Algoritması
// JavaScript örneği
const crypto = require('crypto');
function calculateHash(data, secret) {
const fields = data.hashFields.split(',');
const values = fields.map(field => data[field]).join('|');
const hmac = crypto.createHmac('sha256', secret);
hmac.update(values);
return hmac.digest('hex');
}
// Doğrulama
const receivedHash = request.body.hash;
const calculatedHash = calculateHash(request.body, YOUR_WEBHOOK_SECRET);
if (receivedHash === calculatedHash) {
// Hash geçerli, işleme devam et
} else {
// Hash geçersiz, isteği reddet
}C# Örneği
using System.Security.Cryptography;
using System.Text;
public string CalculateHash(CompleteCardStorageWebhookRequest data, string secret)
{
var fields = data.HashFields.Split(',');
var values = string.Join("|", fields.Select(f =>
typeof(CompleteCardStorageWebhookRequest)
.GetProperty(f)
.GetValue(data)
.ToString()
));
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)))
{
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(values));
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
// Doğrulama
var receivedHash = request.Hash;
var calculatedHash = CalculateHash(request, YOUR_WEBHOOK_SECRET);
if (receivedHash == calculatedHash)
{
// Hash geçerli
}Webhook Endpoint Kurulumu
Sistemden webhook almak için kendi endpoint'inizi yapılandırmanız gerekir.
Örnek Webhook Handler (Node.js/Express)
const express = require('express');
const app = express();
app.post('/webhooks/card-storage/:type/:id', express.json(), (req, res) => {
const { type, id } = req.params;
const webhookData = req.body;
// Hash doğrulama
const calculatedHash = calculateHash(webhookData, process.env.WEBHOOK_SECRET);
if (webhookData.hash !== calculatedHash) {
return res.status(401).json({ error: 'Invalid hash' });
}
// Timestamp kontrolü (5 dakikadan eski istekleri reddet)
const now = Date.now();
const difference = now - webhookData.timestamp;
if (difference > 5 * 60 * 1000) {
return res.status(401).json({ error: 'Request expired' });
}
// İşlemi veritabanına kaydet
console.log(`Card storage completed for ${type}:${id}`);
console.log(`Owner: ${webhookData.ownerId}, Card: ${webhookData.cardId}`);
// Başarılı yanıt
res.json({ success: true });
});Örnek Webhook Handler (C# / ASP.NET Core)
[ApiController]
[Route("webhooks")]
public class WebhookController : ControllerBase
{
private readonly string _webhookSecret;
public WebhookController(IConfiguration configuration)
{
_webhookSecret = configuration["WebhookSecret"];
}
[HttpPost("card-storage/{type}/{id}")]
public IActionResult CompleteCardStorage(
string type,
Guid id,
[FromBody] CompleteCardStorageWebhookRequest request)
{
// Hash doğrulama
var calculatedHash = CalculateHash(request, _webhookSecret);
if (request.Hash != calculatedHash)
{
return Unauthorized(new { error = "Invalid hash" });
}
// Timestamp kontrolü
var now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var difference = now - request.Timestamp;
if (difference > 5 * 60 * 1000) // 5 dakika
{
return Unauthorized(new { error = "Request expired" });
}
// İşlemi kaydet
_logger.LogInformation(
"Card storage completed for {Type}:{Id}, Owner: {OwnerId}, Card: {CardId}",
type, id, request.OwnerId, request.CardId
);
return Ok(new { success = true });
}
}Webhook URL Yapılandırması
Webhook URL'inizi Klogs yönetim panelinden yapılandırabilirsiniz:
- Klogs Dashboard'a giriş yapın
- Ayarlar > Webhook Yapılandırması bölümüne gidin
- Kart Saklama Webhook URL alanına endpoint'inizi girin
- Webhook Secret anahtarını not alın
- Test webhook'unu göndererek doğrulayın
Webhook URL Formatı
https://yourdomain.com/webhooks/card-storage/{type}/{id}Güvenlik Önerileri
- ✅ Her zaman hash doğrulaması yapın
- ✅ Timestamp kontrolü ile replay attack'leri önleyin
- ✅ HTTPS kullanın
- ✅ Webhook secret'ı güvenli saklayın (environment variables)
- ✅ Rate limiting uygulayın
- ✅ IP whitelist kullanmayı düşünün
- ❌ Hash doğrulamasını atlayarak işlem yapmayın
- ❌ Webhook secret'ı kodda sabit olarak tanımlamayın
Hata Durumları
| Durum | Açıklama | Çözüm |
|---|---|---|
| 401 Unauthorized | Hash doğrulaması başarısız | Secret anahtarını kontrol edin |
| 401 Unauthorized | Timestamp süresi dolmuş | Sunucu saatini kontrol edin |
| 404 Not Found | Webhook endpoint bulunamadı | URL yapılandırmasını kontrol edin |
| 500 Server Error | Webhook işleme hatası | Log'ları kontrol edin |
Retry Mekanizması
Webhook başarısız olursa (2xx dışında bir HTTP kodu dönerse), sistem otomatik olarak tekrar deneme yapar:
- deneme: Hemen
- deneme: 5 dakika sonra
- deneme: 15 dakika sonra
- deneme: 1 saat sonra
- deneme: 6 saat sonra
⚠️ Not: 5 denemeden sonra webhook başarısız olarak işaretlenir ve manuel müdahale gerekir.
Webhook Loglama
Webhook isteklerini loglamanız önerilir:
// Loglama örneği
console.log({
timestamp: new Date().toISOString(),
type: type,
id: id,
ownerId: webhookData.ownerId,
cardId: webhookData.cardId,
success: true
});Test Etme
Webhook'unuzu test etmek için Klogs Dashboard'dan test webhook'u gönderebilirsiniz:
# Manuel test için cURL
curl -X POST https://yourdomain.com/webhooks/card-storage/recurring/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
-H "Content-Type: application/json" \
-d '{
"ownerId": "OWN-TEST",
"cardId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"tenantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"hash": "test-hash-value",
"hashFields": "ownerId,cardId,tenantId,timestamp",
"timestamp": 1708084800000
}'
