Le verdict en trois phrases
Un webhook de paiement est l'appel que l'opérateur envoie à votre serveur pour dire "ce paiement est réussi" ; s'il n'est pas vérifié, un attaquant peut le falsifier et déclencher une livraison sans jamais payer. La parade tient en trois couches : vérification de signature HMAC, clé d'idempotence contre le rejeu, et re-vérification du statut directement auprès de l'API de l'opérateur. Sans ces couches, la fraude est 100 % gratuite ; avec elles, elle devient quasi impossible.
La faille : simuler un paiement réussi
Le scénario est banal. Votre code écoute une URL de webhook et, en recevant un message "status=success", il marque la commande payée et déclenche la livraison. Si vous ne vérifiez pas que le message vient bien de l'opérateur, un attaquant envoie lui-même ce message avec le bon numéro de commande et repart avec la marchandise. La signature HMAC résout ça : l'opérateur signe chaque message avec un secret partagé, et vous recalculez la signature pour confirmer l'origine.
| Mécanisme par opérateur | En-tête de signature | Méthode | Risque sans vérif |
|---|---|---|---|
| Wave | Signature HMAC dans l'en-tête | HMAC-SHA256 | Paiement fictif accepté |
| Paystack | x-paystack-signature | HMAC-SHA512 | Paiement fictif accepté |
| Flutterwave | vérif-hash | Hash secret partagé | Paiement fictif accepté |
| Stripe | Stripe-Signature | HMAC-SHA256 + timestamp | Paiement fictif accepté |
| Orange Money | Token / signature selon intégration | Variable | Paiement fictif accepté |
La règle d'or : ne jamais faire confiance au corps du webhook seul. La signature prouve l'origine, pas le contenu métier.
Les trois couches de défense
Chaque couche bloque une attaque différente. Ensemble, elles couvrent la falsification, le rejeu et le mensonge sur le montant.
| Couche | Ce qu'elle bloque | Comment |
|---|---|---|
| Vérification signature HMAC | Message falsifié | Recalculer le hash avec le secret |
| Clé d'idempotence | Rejeu du même message | Stocker l'ID d'événement, ignorer les doublons |
| Re-check statut via API | Faux montant / faux statut | Interroger l'API avec l'ID de transaction |
| IP allowlist | Source inconnue | N'accepter que les IP de l'opérateur |
| Timestamp / fenêtre | Rejeu différé | Rejeter les messages trop anciens |
Le re-check du statut est le filet de sécurité ultime : même si tout le reste échoue, interroger l'API de l'opérateur avec l'ID de transaction confirme le vrai montant et le vrai statut avant de livrer.
L'idempotence, pourquoi c'est vital
Les opérateurs renvoient parfois le même webhook plusieurs fois (réseau instable, retry automatique). Sans idempotence, vous risquez de créditer deux fois une commande, d'envoyer deux fois la marchandise ou de compter le CA en double. La solution : stocker l'identifiant unique de chaque événement reçu et ignorer tout doublon. C'est aussi une protection contre le rejeu volontaire par un attaquant.
Mini cas pratique
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.
Moussa lance une boutique de recharge et vente de crédits à Accra. Au début, son webhook accepte tout message "success". En une semaine, un attaquant simule 40 paiements et repart avec 600 000 FCFA de crédits. Moussa fait ajouter les trois couches : vérification HMAC (Paystack via x-paystack-signature), idempotence sur l'ID d'événement, et re-check du statut via l'API avant chaque livraison. Coût du correctif : environ 300 000 FCFA, une seule fois. La fraude tombe à zéro. Le correctif s'est remboursé en une demi-attaque évitée.
FAQ
La vérification de signature suffit-elle seule ?
Non. Elle prouve que le message vient de l'opérateur, mais un rejeu du même message reste possible sans idempotence, et un bug de montant peut passer. La combinaison signature + idempotence + re-check statut est le standard.
Où trouver le secret de signature ?
Dans le tableau de bord de l'opérateur (Wave, Paystack, Flutterwave, Stripe), section webhooks ou clés API. Ce secret doit rester côté serveur, jamais dans le code client ni dans un dépôt public.
Faut-il vraiment re-vérifier le statut via l'API ?
C'est la meilleure pratique pour les montants sensibles. Même avec une signature valide, interroger l'API avec l'ID de transaction garantit le vrai statut et le vrai montant avant de livrer. C'est un appel rapide et peu coûteux.
L'IP allowlist est-elle obligatoire ?
Non, mais c'est une couche gratuite : n'accepter que les plages d'IP publiées par l'opérateur réduit la surface d'attaque. Attention aux opérateurs qui changent leurs IP sans préavis.
Combien coûte la sécurisation d'un webhook ?
Un ordre de grandeur 2026 : 200 000 à 400 000 FCFA pour implémenter les trois couches proprement sur une intégration existante. C'est négligeable face au risque d'une seule attaque réussie.
Discutons de votre projet. Nous sécurisons vos webhooks Wave, Paystack, Flutterwave et Stripe avec signature HMAC, idempotence et re-check statut. 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.

