Webhooklar
A-ZPay, operatör bir işlemi onayladığında veya reddettiğinde webhook gönderir.
Header’lar
X-AZPay-Event: deposit.approved
X-AZPay-Event-Id: evt_...
X-AZPay-Timestamp: 1778940000
X-AZPay-Signature: <hmac sha256>
Webhook imzası partner API istekleriyle aynı canonical string’i kullanır:
<timestamp>.POST.<webhook_path>.<raw_json_body>.<hashSecret>
HMAC anahtarı olarak casino apiSecret değerini kullanın ve casino hashSecret değerini canonical string’in son segmenti olarak ekleyin. JSON parse etmeden önce ham body üzerinde doğrulama yapın.
import crypto from 'node:crypto';
function verifyWebhook(req, rawBody) {
const timestamp = req.header('x-azpay-timestamp');
const signature = req.header('x-azpay-signature');
const path = '/azpay/webhook';
const canonical = [timestamp, 'POST', path, rawBody, process.env.AZPAY_HASH_SECRET].join('.');
const expected = crypto.createHmac('sha256', process.env.AZPAY_API_SECRET).update(canonical).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(expected, 'hex'));
}
app.post('/azpay/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const rawBody = req.body.toString('utf8');
if (!verifyWebhook(req, rawBody)) return res.sendStatus(401);
const payload = JSON.parse(rawBody);
if (payload.status === 'approved') await applySettlement(payload);
res.sendStatus(200);
});<?php
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_AZPAY_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_AZPAY_SIGNATURE'] ?? '';
$path = '/azpay/webhook';
$canonical = implode('.', [$timestamp, 'POST', $path, $rawBody, getenv('AZPAY_HASH_SECRET')]);
$expected = hash_hmac('sha256', $canonical, getenv('AZPAY_API_SECRET'));
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
$payload = json_decode($rawBody, true);
if ($payload['status'] === 'approved') {
applySettlement($payload);
}
http_response_code(200);Payload
{
"transactionId": "txn_...",
"externalReference": "casino-deposit-1001",
"type": "deposit",
"status": "approved",
"amountCents": 10000,
"requestedAmountCents": 10000,
"actualAmountCents": 9900,
"amountDifferenceCents": -100,
"commissionCents": 990,
"netAmountCents": 8910,
"playerAmountCents": 8910,
"balanceImpactCents": 8910,
"currency": "TRY",
"referenceCode": "BP-A1B2C3D4"
}
deposit.approved için amountCents ve requestedAmountCents casino tarafından talep edilen tutardır. actualAmountCents, A-ZPay operatörünün doğruladığı brüt gerçek tutardır ve daha düşük veya yüksek olabilir. İmzayı doğruladıktan sonra oyuncuya playerAmountCents kadar bakiye ekleyin.
Idempotency
X-AZPay-Event-Id değerini saklayın ve yalnızca bir kez işleyin. Sadece kendi veritabanı transaction’ınız commit olduktan sonra 2xx dönün. A-ZPay teslim denemelerini saklar ve başarısız eventleri tekrar deneyebilir.