Le verdict en trois phrases
Un webhook de paiement fiable repose sur trois piliers : verifier la signature (HMAC ou hash du provider), dedupliquer par reference avec une cle d'idempotence, et rejouer les evenements via une file de retry a backoff exponentiel. Sans ces trois garde-fous, vous validez des commandes fantomes ou vous debitez un client deux fois. En 2026, tout provider serieux — Wave, Paystack, Flutterwave, CinetPay, MTN MoMo — signe ses webhooks : votre travail est de ne jamais faire confiance a un callback non verifie.
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 requete HTTP casse un webhook : timeout, deploiement en cours, code 500, DNS lent. Les providers reagissent en rejouant l'evenement — c'est la source numero un des doublons. Votre endpoint doit donc etre idempotent : recevoir deux fois le meme evenement ne doit produire qu'un seul effet.
| Provider | Retry automatique | Delai entre tentatives | Signature | Perte estimee 2026 |
|---|---|---|---|---|
| Paystack | Oui, jusqu'a 72 h | Exponentiel (min -> h) | En-tete x-paystack-signature (HMAC SHA512) | ~1 % |
| Flutterwave | Oui, plusieurs essais | Progressif | Hash verif-hash (secret configure) | ~1-2 % |
| CinetPay | Oui | ~15 min a plusieurs h | Token / verification API status | ~2 % |
| Wave | Oui | Progressif | Signature HMAC (webhook secret) | ~1 % |
| MTN MoMo | Callback + polling conseille | Variable | Cle API + verification transaction | ~2-3 % |
| Orange Money | Callback + verification statut | Variable | Token de notification | ~2-3 % |
Regle d'or : ne jamais considerer 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. Verifier la signature
Chaque provider signe le corps brut de la requete avec votre secret. Vous recalculez le HMAC cote serveur et comparez. Exemple Paystack : HMAC-SHA512(secret, raw_body) doit egaler l'en-tete x-paystack-signature. Si ca ne correspond pas, repondez 401 et jetez l'evenement. Utilisez le corps brut, pas le JSON re-serialise — un espace de difference casse la signature.
2. Cle d'idempotence et deduplication
Stockez chaque reference de transaction dans une table avec contrainte d'unicite. A la reception :
| Etape | Action | Resultat |
|---|---|---|
| Reception webhook | Extraire reference | Cle unique de la transaction |
| INSERT en base | Contrainte UNIQUE sur reference | Doublon rejete au niveau SQL |
| Deja traite ? | Renvoyer 200 sans rien faire | Pas de double livraison |
| Nouveau ? | Traiter puis marquer processed | Effet unique garanti |
La contrainte d'unicite en base est votre filet de securite ultime : meme sous forte concurrence, deux INSERT identiques echouent, un seul passe.
3. File de retry a backoff exponentiel
Si votre traitement echoue (base indisponible, service tiers KO), ne perdez pas l'evenement : poussez-le dans une file (queue) et rejouez avec un delai croissant : 1 min, 2 min, 4 min, 8 min... jusqu'a 24 h. Repondez 200 au provider seulement quand l'evenement est acquitte en file, pas quand tout le metier 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 gere une boutique de cosmetiques a Dakar, environ 900 commandes/mois a 15 000 FCFA en moyenne. Avant refonte, son site validait la commande directement sur le webhook, sans deduplication. Resultat : environ 1,5 % de doublons, soit ~13 commandes/mois livrees ou comptees deux fois, dont 4 remboursements manuels a 15 000 FCFA = 60 000 FCFA/mois de pertes seches, plus 3 h de reconciliation.
Apres ajout de la contrainte d'unicite sur reference + reverification via l'API status : doublons tombes a ~0, 3 h/mois economisees. Cout du correctif : une demi-journee 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'evenement et declencher un traitement idempotent. Livrez apres reverification du statut via l'API provider, car un webhook peut arriver pour un paiement encore pending ou finalement echoue.
Que faire si je recois le meme webhook trois fois ?
Rien de plus qu'a la premiere fois. Grace a la contrainte UNIQUE sur la reference, les 2e et 3e receptions sont detectees comme deja traitees et vous renvoyez 200 immediatement. C'est le comportement attendu, pas un bug.
Comment tester la signature sans casser la production ?
Utilisez le sandbox du provider (cles de test) et un tunnel local type ngrok. Envoyez un evenement de test, verifiez que votre HMAC recalcule 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 a 3 % selon le provider et la disponibilite de votre endpoint. C'est pourquoi le polling de secours (verifier les transactions pending toutes les X minutes) reste indispensable pour un e-commerce serieux.
Faut-il un provider par pays ou un agregateur ?
Un agregateur (Paystack, Flutterwave, CinetPay) simplifie l'integration webhook multi-operateurs, mais chaque provider a sa propre logique de signature et de retry. Standardisez votre couche de reception pour absorber ces differences.
Discutons de votre projet. Nous integrons des webhooks mobile money idempotents et testes 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.

