Webhooks · Guides de recettes
Recevoir et vérifier un webhook
Recevoir est facile. Vérifier la signature et rester idempotent est ce qui fait la différence en production.
1. Déclarer l'endpoint
La réponse 201 porte le secret. Il n'est visible qu'ici : ni la lecture ni la liste ne le renvoient. Conservez-le au même endroit que vos autres secrets d'application.
{
"url": "https://example.com/webhooks/mobupay",
"events": ["payment.captured", "payment.failed", "payment.refunded"]
}2. Vérifier la signature
Chaque livraison porte X-Mobupay-Signature (HMAC-SHA256 du corps brut avec votre secret), X-Mobupay-Event et X-Mobupay-Delivery-Id.
La signature se calcule sur le corps brut, avant tout analyseur JSON. Un cadriciel qui reformate le corps avant votre code invalide toutes les signatures, et le symptôme est un rejet systématique inexplicable.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifie(rawBody, signature, secret) {
const attendu = createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(attendu);
const b = Buffer.from(signature ?? "");
return a.length === b.length && timingSafeEqual(a, b);
}Comparez en temps constant. Une comparaison de chaînes ordinaire s'arrête au premier caractère différent, ce qui laisse mesurer la signature attendue octet par octet.
3. Traiter une seule fois
Mobupay retente cinq fois avec un délai croissant tant que votre serveur ne répond pas 2xx. Une réponse lente comptée comme un échec produit donc un doublon.
X-Mobupay-Delivery-Id identifie la livraison, l'id de l'événement identifie l'événement. Retenez l'un des deux et ignorez ce que vous avez déjà traité.
4. Répondre vite, travailler après
Accusez réception en 2xx immédiatement, puis traitez en tâche de fond. Un traitement long dans la requête finit par dépasser le délai et déclenche des relances que rien ne justifie.