Pourquoi le webhook est le maillon critique
Un webhook de paiement est l appel serveur a serveur que le prestataire (Orange Money, Wave, Stripe) envoie a votre backend quand un paiement change de statut. C est lui, et non la redirection du navigateur, qui fait foi. Un webhook mal securise ouvre la porte aux fausses confirmations de paiement et aux doubles traitements.
Ce guide couvre les quatre piliers d un webhook robuste : verification de signature, idempotence, reponse HTTP correcte, et gestion des retries.
Anatomie d un payload de webhook
Un webhook arrive par une requete POST vers votre endpoint, avec un corps JSON et des en-tetes de signature.
| Champ | Type | Description |
|---|---|---|
| event_id | chaine | Identifiant unique de l evenement, cle d idempotence |
| event_type | chaine | Type, par exemple payment.succeeded |
| order_id | chaine | Reference de la commande cote marchand |
| amount | entier | Montant en FCFA |
| status | chaine | SUCCESS, FAILED, PENDING |
| created_at | timestamp | Horodatage de l evenement |
| signature | chaine | HMAC du corps, dans l en-tete |
En-tetes a lire
La signature voyage dans un en-tete dedie, souvent accompagne d un horodatage pour bloquer les attaques par rejeu.
| En-tete | Role |
|---|---|
| X-Signature | HMAC SHA-256 du corps brut |
| X-Timestamp | Horodatage d envoi, pour fenetre anti-rejeu |
| Content-Type | application/json |
Verification de signature HMAC
La signature prouve que le webhook vient bien du prestataire et que le corps n a pas ete modifie. Le calcul se fait sur le corps brut, jamais sur le JSON re-serialise.
- Recuperer le corps brut de la requete, octet pour octet.
- Recuperer l en-tete X-Signature et X-Timestamp.
- Calculer HMAC SHA-256 du corps avec votre secret de webhook.
- Comparer en temps constant la signature calculee a celle recue.
- Rejeter si l horodatage est plus vieux que 5 minutes (anti-rejeu).
Erreur classique
Beaucoup de bugs viennent d un framework qui parse le JSON avant que vous lisiez le corps brut. Re-serialiser change les espaces et casse le HMAC. Lisez toujours le raw body avant tout parsing.
Idempotence : ne traiter qu une seule fois
Les prestataires renvoient le meme webhook plusieurs fois (retries). Votre logique doit etre idempotente : traiter event_id deux fois ne doit jamais debiter deux fois ni livrer deux fois.
| Strategie | Mecanisme | Avantage |
|---|---|---|
| Cle unique en base | Index unique sur event_id | Rejet immediat des doublons |
| Verrou par commande | Lock sur order_id pendant traitement | Evite les conditions de course |
| Statut transactionnel | Transition PENDING vers PAID atomique | Pas de double passage |
Le plus simple et robuste : un index unique sur event_id. Si l insertion echoue pour doublon, renvoyez 200 sans retraiter.
Reponse HTTP et codes de statut
Ce que vous renvoyez decide si le prestataire reessaie ou non. Une mauvaise reponse provoque des retries inutiles ou, pire, la perte de l evenement.
| Code renvoye | Interpretation prestataire | Quand l utiliser |
|---|---|---|
| 200 | Recu et traite | Succes, ou doublon deja traite |
| 400 | Requete invalide | Signature invalide, payload corrompu |
| 401 | Non authentifie | Signature absente ou fausse |
| 409 | Conflit | Traitement deja en cours (optionnel) |
| 500 | Erreur serveur | Bug interne, declenche un retry |
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.
Renvoyez 200 le plus vite possible, puis traitez en arriere-plan si le travail est long. Un webhook qui repond en plus de quelques secondes risque un timeout cote prestataire.
Strategie de retries
Si vous repondez par une erreur 5xx ou ne repondez pas, le prestataire reessaie selon un backoff exponentiel.
| Tentative | Delai indicatif | Action backend |
|---|---|---|
| 1 | immediat | Traiter ou logger l echec |
| 2 | environ 1 minute | Verifier idempotence |
| 3 | environ 5 minutes | Verifier idempotence |
| 4 | environ 30 minutes | Alerter le support si toujours en echec |
| 5 et plus | jusqu a 24 h | Reconciliation manuelle |
Exemple concret
Un client paie une commande de 40 000 FCFA. Le prestataire envoie payment.succeeded. Votre serveur lit le raw body, verifie le HMAC, controle que event_id n existe pas en base, insere l evenement, passe la commande de PENDING a PAID dans une transaction, puis renvoie 200. Une minute plus tard, un retial duplique arrive avec le meme event_id : l insertion echoue sur l index unique, vous renvoyez 200 immediatement, aucune double livraison. Total : un seul traitement effectif, zero double debit.
Checklist securite webhook
| Controle | Statut attendu |
|---|---|
| Verification HMAC sur raw body | obligatoire |
| Comparaison de signature en temps constant | obligatoire |
| Fenetre anti-rejeu sur l horodatage | obligatoire |
| Index unique sur event_id | obligatoire |
| Endpoint en HTTPS uniquement | obligatoire |
| Reponse 200 rapide, traitement async | recommande |
| Journalisation de chaque evenement | recommande |
FAQ
Pourquoi ne pas se fier a la redirection du navigateur ?
Parce que le client peut fermer l onglet ou perdre sa connexion avant le retour. Seul le webhook serveur a serveur garantit que vous etes notifie du statut reel.
Sur quel contenu calculer le HMAC ?
Sur le corps brut de la requete, octet pour octet, avant tout parsing JSON. Re-serialiser le JSON change les espaces et invalide la signature.
Comment eviter le double traitement ?
Un index unique sur event_id en base. Si l evenement existe deja, renvoyez 200 sans retraiter. C est la methode la plus simple et la plus fiable.
Que renvoyer si la signature est invalide ?
Un code 401 ou 400, sans traiter l evenement. Ne renvoyez jamais 200 pour un webhook dont la signature ne correspond pas.
Combien de temps un prestataire reessaie-t-il ?
Generalement jusqu a 24 heures avec un backoff exponentiel. Apres echec total, prevoyez une reconciliation manuelle ou un endpoint de rejeu.
Discutons de votre projet. Kolonell construit des backends de paiement securises avec verification de signature et idempotence par defaut. 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.

