Signatures de webhooks
Chaque webhook est signé avec HMAC-SHA256 sur le corps brut de la requête en utilisant votre secret de webhook. La signature est envoyée dans l'en-tête X-ZyndPay-Signature. Comparez en temps constant. Relance : backoff exponentiel sur 24h.
Choisissez votre langage :
Verify X-ZyndPay-Signature
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const SECRET = process.env.ZYNDPAY_WEBHOOK_SECRET!;
// Mount raw-body parser so we can hash the exact bytes ZyndPay signed.
app.post('/webhooks/zyndpay', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.header('x-zyndpay-signature') ?? '';
const expected = crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
const a = Buffer.from(signature);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).send('invalid signature');
}
const event = JSON.parse(req.body.toString('utf8'));
// handle event.type (e.g. 'payin.succeeded') ...
res.status(200).send('ok');
});Catalogue d'événements
Chaque événement porte un id unique, un type (ex. payin.succeeded), un compteur de tentatives, et un timestamp ISO. Les relances sont idempotentes — le même id est redélivré en cas d'échec.
| event.type | description |
|---|---|
| payin.succeeded | Customer paid. Amount and tx hash are in the payload. |
| payin.failed | Underlying transfer failed or the paylink expired. |
| payin.expired | Paylink expired before the customer completed payment. |
| payout.succeeded | Payout confirmed on-chain. |
| payout.failed | Payout rejected (insufficient balance, bad address, compliance). |
| withdrawal.succeeded | Merchant-initiated withdrawal confirmed on-chain. |
| withdrawal.failed | Withdrawal rejected by the gateway or compliance. |
| refund.succeeded | Refund sent back to the original payer. |
| subscription.renewed | Recurring subscription charge succeeded. |
| dispute.opened | A customer or chain flagged a payment. See issue #200 workflow. |