AZA-ZPayA-ZPay banka transferi API’si

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.

Webhook doğrula ve işle
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.