Le verdict en trois phrases
Un webhook de paiement fiable repose sur trois piliers : vérifier la signature (HMAC ou hash du provider), dédupliquer par référence avec une clé d'idempotence, et rejouer les événements via une file de retry à backoff exponentiel. Sans ces trois garde-fous, vous validez des commandes fantômes ou vous débitez un client deux fois. En 2026, tout provider sérieux — Wave, Paystack, Flutterwave, CinetPay, MTN MoMo — signe ses webhooks : votre travail est de ne jamais faire confiance à un callback non vérifié.
Pourquoi les webhooks se perdent (et se dupliquent)
Un webhook est un simple POST HTTP du provider vers votre serveur. Tout ce qui casse une requête HTTP casse un webhook : timeout, déploiement en cours, code 500, DNS lent. Les providers réagissent en rejouant l'événement — c'est la source numéro un des doublons. Votre endpoint doit donc être idempotent : recevoir deux fois le même événement ne doit produire qu'un seul effet.
| Provider | Retry automatique | Délai entre tentatives | Signature | Perte estimée 2026 |
|---|---|---|---|---|
| Paystack | Oui, jusqu'à 72 h | Exponentiel (min -> h) | En-tête x-paystack-signature (HMAC SHA512) | ~1 % |
| Flutterwave | Oui, plusieurs essais | Progressif | Hash verif-hash (secret configuré) | ~1-2 % |
| CinetPay | Oui | ~15 min à plusieurs h | Token / vérification API status | ~2 % |
| Wave | Oui | Progressif | Signature HMAC (webhook secret) | ~1 % |
| MTN MoMo | Callback + polling conseillé | Variable | Clé API + vérification transaction | ~2-3 % |
| Orange Money | Callback + vérification statut | Variable | Token de notification | ~2-3 % |
Règle d'or : ne jamais considérer un paiement comme final sur la seule foi du webhook. Toujours reconfirmer via l'API verify/status du provider avant de livrer.
Les trois garde-fous techniques
1. Vérifier la signature
Chaque provider signé le corps brut de la requête avec votre secret. Vous recalculez le HMAC côté serveur et comparez. Exemple Paystack : HMAC-SHA512(secret, raw_body) doit égaler l'en-tête x-paystack-signature. Si ça ne correspond pas, répondez 401 et jetez l'événement. Utilisez le corps brut, pas le JSON re-sérialisé — un espace de différence casse la signature.
2. Clé d'idempotence et déduplication
Stockez chaque reference de transaction dans une table avec contrainte d'unicité. À la réception :
| Étape | Action | Résultat |
|---|---|---|
| Réception webhook | Extraire reference | Clé unique de la transaction |
| INSERT en base | Contrainte UNIQUE sur reference | Doublon rejeté au niveau SQL |
| Déjà traité ? | Renvoyer 200 sans rien faire | Pas de double livraison |
| Nouveau ? | Traiter puis marquer processed | Effet unique garanti |
La contrainte d'unicité en base est votre filet de sécurité ultime : même sous forte concurrence, deux INSERT identiques échouent, un seul passé.
3. File de retry à backoff exponentiel
Si votre traitement échoue (base indisponible, service tiers KO), ne perdez pas l'événement : poussez-le dans une file (queue) et rejouez avec un délai croissant : 1 min, 2 min, 4 min, 8 min... jusqu'à 24 h. Répondez 200 au provider seulement quand l'événement est acquitté en file, pas quand tout le métier est fini.
Besoin d'un site web professionnel ?
Kolonell crée des sites web qui attirent des clients, optimisés pour le marché sénégalais. Devis gratuit en 2 minutes.
Mini cas pratique
Awa gère une boutique de cosmétiques à Dakar, environ 900 commandes/mois à 15 000 FCFA en moyenne. Avant refonte, son site validait la commande directement sur le webhook, sans déduplication. Résultat : environ 1,5 % de doublons, soit ~13 commandes/mois livrées ou comptées deux fois, dont 4 remboursements manuels à 15 000 FCFA = 60 000 FCFA/mois de pertes sèches, plus 3 h de réconciliation.
Après ajout de la contrainte d'unicité sur reference + reverification via l'API status : doublons tombés à ~0, 3 h/mois économisées. Coût du correctif : une demi-journée de dev. Retour sur investissement en moins d'un mois.
FAQ
Dois-je livrer la commande directement dans le webhook ?
Non. Le webhook doit seulement enregistrer l'événement et déclencher un traitement idempotent. Livrez après revérification du statut via l'API provider, car un webhook peut arriver pour un paiement encore pending ou finalement échoué.
Que faire si je reçois le même webhook trois fois ?
Rien de plus qu'à la première fois. Grâce à la contrainte UNIQUE sur la référence, les 2e et 3e réceptions sont détectées comme déjà traitées et vous renvoyez 200 immédiatement. C'est le comportement attendu, pas un bug.
Comment tester la signature sans casser la production ?
Utilisez le sandbox du provider (clés de test) et un tunnel local type ngrok. Envoyez un événement de test, vérifiez que votre HMAC recalculé correspond, puis simulez un mauvais secret pour confirmer que vous rejetez bien en 401.
Combien de webhooks se perdent vraiment ?
Ordre de grandeur 2026 : 1 à 3 % selon le provider et la disponibilité de votre endpoint. C'est pourquoi le polling de secours (vérifier les transactions pending toutes les X minutes) reste indispensable pour un e-commerce sérieux.
Faut-il un provider par pays ou un agrégateur ?
Un agrégateur (Paystack, Flutterwave, CinetPay) simplifie l'intégration webhook multi-opérateurs, mais chaque provider a sa propre logique de signature et de retry. Standardisez votre couche de réception pour absorber ces différences.
Discutons de votre projet. Nous intégrons des webhooks mobile money idempotents et testés pour votre boutique. WhatsApp +221 77 596 93 33.
Mohamed Bah
Fondateur, Kolonell
Passionné par le digital et l'entrepreneuriat en Afrique, Mohamed accompagne les entreprises sénégalaises dans leur transformation digitale depuis 2020. Fondateur de Kolonell, il croit que chaque PME mérite une présence en ligne professionnelle et accessible.

