Integration
Webhooks
Recevez chaque changement d’etat sur votre serveur, signe et rejoue automatiquement en cas d’echec.
Endpoints
GET
/v1/webhooksLister vos endpointscle secretePOST
/v1/webhooksCreer un endpointcle secretePOST
/v1/webhooks/:idModifier un endpointcle secreteDELETE
/v1/webhooks/:idSupprimer un endpointcle secretePOST
/v1/webhooks/testEnvoyer un evenement de testcle secreteGET
/v1/webhooks/deliveriesHistorique des livraisonscle secreteFormat d’un evenement
{
"id": "evt_2p8zk3m1x9",
"type": "payment.succeeded",
"created": "2024-03-01T12: 00: 06.000Z",
"environment": "sandbox",
"livemode": false,
"data": {
"object": {
"id": "pay_8f2k39dmz0qw",
"object": "payment",
"status": "succeeded",
"amount": 10000,
"currency": "XOF",
"fee_amount": 180,
"net_amount": 9820,
"payment_method": "mobile_money",
"network": "tmoney",
"reference": "ORDER-12345"
}
}
}Evenements disponibles
- payment.created
- payment.processing
- payment.succeeded
- payment.failed
- payment.cancelled
- payment.expired
- payment.refunded
- payment.partially_refunded
- payout.created
- payout.processing
- payout.succeeded
- payout.failed
- refund.created
- refund.succeeded
- refund.failed
- payment_link.created
- payment_link.paid
Un endpoint abonne a * recoit tous les evenements, y compris ceux ajoutes ulterieurement.
Verifier la signature
La signature est un HMAC-SHA256 calcule sur timestamp.payload avec le secret de l’endpoint. Verifiez-la systematiquement et rejetez toute requete non signee.
import crypto from 'node:crypto';
const TOLERANCE_SECONDS = 300;
export function verifyWanePaySignature(header, rawBody, secret) {
const parts = Object.fromEntries(
header.split(',').map((kv) => kv.split('=')),
);
const timestamp = Number(parts.t);
const age = Math.abs(Math.floor(Date.now() / 1000) - timestamp);
if (!Number.isFinite(timestamp) || age > TOLERANCE_SECONDS) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(parts.v1 ?? ''),
);
}Utilisez le corps brut
La signature porte sur le corps exact recu. Ne re-serialisez pas le JSON avant verification : le moindre espace change le resultat.Rejeu et fiabilite
Politique de rejeu
| Parametre | Type | Description |
|---|---|---|
Tentative 1 | immediate | Des l’emission de l’evenement. |
Tentative 2 | +5 s | Si la reponse n’est pas 2xx. |
Tentative 3 | +30 s | |
Tentative 4 | +5 min | |
Tentative 5 | +30 min | |
Tentative 6 | +2 h | Puis abandon et statut failed. |
- Repondez 2xx en moins de 8 secondes ; traitez ensuite de maniere asynchrone.
- Le meme evenement peut etre livre plusieurs fois : rendez votre traitement idempotent en vous appuyant sur
event.id. - L’ordre de livraison n’est pas garanti : fiez-vous au statut porte par l’objet.
- L’historique complet (statut HTTP, duree, erreur) est consultable dans le dashboard.