Webhooks expliqués : payloads signés et retries

Backend2026-10-08TryQuickToolBox

Vous venez d'intégrer une passerelle de paiement à l'aide de webhooks. Tout fonctionne en test, mais en production, des événements disparaissent parfois, ou vous recevez des notifications en double qui provoquent des doubles débits. La cause racine réside souvent dans la façon dont vous gérez les payloads signés et les retries. Cet article explique la mécanique des webhooks et fournit des étapes pratiques pour construire une intégration robuste et sécurisée.

Que sont les webhooks ?

Les webhooks sont des callbacks HTTP définis par l'utilisateur. Lorsqu'un événement se produit dans un système source (par exemple, un paiement est traité), il envoie une requête HTTP POST vers une URL que vous spécifiez, contenant les données de l'événement. Contrairement au polling, les webhooks poussent les données en quasi temps réel, réduisant la latence et la charge serveur.

Cependant, les webhooks introduisent des défis : vérifier l'authenticité, gérer les échecs et garantir un traitement exactement-une-fois. Abordons chacun d'eux.

Payloads signés : vérifier l'authenticité

Comme les endpoints de webhook sont accessibles publiquement, n'importe qui pourrait envoyer de fausses requêtes. Pour éviter cela, les fournisseurs signent le payload avec une clé secrète. Vous vérifiez la signature pour vous assurer que la requête est authentique.

Comment fonctionnent les signatures HMAC

La plupart des fournisseurs utilisent HMAC (Hash-based Message Authentication Code) avec SHA-256. Le fournisseur calcule une signature à partir du corps de la requête et d'un secret partagé, puis l'inclut dans un en-tête (par exemple, X-Signature). Vous recalculez la signature de votre côté et comparez.

Exemple en Python :

import hmac
import hashlib

def verify_signature(payload, secret, received_signature):
    expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, received_signature)

Important : Utilisez le corps brut de la requête, pas le JSON parsé, car le parsing peut modifier les espaces et casser la signature.

Pièges courants

Retries : gérer les échecs avec grâce

Votre endpoint peut être temporairement indisponible, ou des problèmes réseau peuvent causer des échecs. Les systèmes de webhooks fiables réessaient les livraisons échouées avec un backoff exponentiel.

Stratégies de retry

Les fournisseurs réessaient généralement sur des réponses non-2xx ou des timeouts. Modèles courants :

StratégieDescriptionExemple
Intervalle fixeRéessayer toutes les N secondesToutes les 30s, jusqu'à 5 fois
Backoff exponentielDoubler le délai à chaque tentative1s, 2s, 4s, 8s...
Exponentiel avec jitterAjouter de l'aléatoire pour éviter l'effet de troupeau1s ± 0,5s, 2s ± 1s...

En tant que récepteur, vous ne pouvez pas contrôler la politique de retry de l'émetteur, mais vous pouvez concevoir votre endpoint pour être résilient.

Bonnes pratiques pour les récepteurs

  1. Répondez rapidement : Retournez un 2xx en quelques secondes. Déchargez le traitement vers une tâche en arrière-plan.
  2. Soyez idempotent : Utilisez une clé d'idempotence du payload pour éviter le traitement en double.
  3. Journalisez tout : Stockez les webhooks entrants pour le débogage et le rejeu.
  4. Surveillez les échecs : Configurez des alertes pour les échecs répétés.

Implémenter l'idempotence

Les doublons arrivent : l'émetteur peut réessayer parce que votre réponse était lente, ou vous pourriez traiter accidentellement le même événement deux fois. L'idempotence garantit que traiter un événement plusieurs fois a le même effet qu'une seule fois.

Utilisez un ID d'événement unique (souvent fourni dans le payload ou les en-têtes) et stockez-le dans une base de données avec une contrainte unique. Avant de traiter, vérifiez si l'ID existe ; si oui, passez.

def process_event(event_id, data):
    if EventLog.exists(event_id):
        return  # déjà traité
    EventLog.create(event_id)
    # traiter les données...

Pour les systèmes à haut débit, utilisez un verrou distribué ou une transaction de base de données pour éviter les conditions de course.

Considérations de sécurité

Au-delà de la vérification de signature, considérez :

Tester les webhooks localement

Pendant le développement, vous avez besoin d'une URL publique pour recevoir les webhooks. Des outils comme ngrok ou localtunnel exposent votre serveur local. Alternativement, de nombreux fournisseurs proposent une CLI pour transférer les événements vers votre localhost.

Simulez des échecs pour tester la gestion des retries : retournez intentionnellement des erreurs 500 et observez le modèle de retry du fournisseur.

FAQ

Comment vérifier une signature de webhook ?

Utilisez HMAC avec le secret partagé. Calculez le hash du corps brut de la requête et comparez-le à l'en-tête de signature à l'aide d'une fonction de comparaison à temps constant.

Que faire si je reçois des webhooks en double ?

Implémentez l'idempotence en stockant les ID d'événements. Vérifiez si l'événement a déjà été traité avant d'exécuter la logique métier.

Puis-je me fier uniquement aux retries de webhooks pour la fiabilité ?

Non. Les retries aident mais ne peuvent pas garantir la livraison. Pour les événements critiques, combinez les webhooks avec un fallback de polling ou une file de messages qui persiste les événements.

Lors du débogage des payloads de webhooks, vous pourriez avoir besoin d'inspecter des données JSON. Utilisez notre JSON Formatter pour joliment imprimer et valider les payloads rapidement.