Webhooks expliqués : signatures et réessais

Backend2026-11-03TryQuickToolBox

Vous venez d'intégrer un fournisseur de paiement tiers. L'utilisateur effectue un achat, mais votre base de données n'est jamais mise à jour. Pourquoi ? Parce que le webhook censé notifier votre application a échoué silencieusement. Sans vérification de signature et logique de réessai appropriées, les webhooks peuvent devenir une source de bugs mystérieux et de failles de sécurité.

Dans cet article, nous expliquons comment fonctionnent les webhooks, pourquoi vous devez vérifier les payloads signés et comment concevoir un mécanisme de réessai robuste. Nous vous montrons également comment tester et déboguer efficacement les webhooks.

Que sont les webhooks ?

Les webhooks sont des callbacks HTTP définis par l'utilisateur. Ils permettent à un système d'envoyer des données en temps réel à un autre lorsqu'un événement se produit. Par exemple, lorsqu'un paiement est traité, le fournisseur de paiement envoie une requête HTTP POST à une URL que vous spécifiez, contenant les détails de l'événement.

Contrairement au polling, où votre application demande régulièrement des mises à jour, les webhooks vous poussent les données dès qu'elles sont disponibles. Cela les rend efficaces et quasi temps réel.

Le problème de sécurité : pourquoi vérifier les signatures ?

Les points de terminaison de webhook sont des URL accessibles publiquement. N'importe qui peut leur envoyer une requête POST. Sans vérification, un attaquant pourrait forger une requête pour, par exemple, marquer une commande comme payée sans paiement réel. Pour éviter cela, les fournisseurs signent chaque payload avec une clé secrète.

Comment fonctionnent les signatures HMAC

La plupart des fournisseurs utilisent HMAC (Hash-based Message Authentication Code) avec SHA-256. Ils calculent un hash du corps de la requête à l'aide d'un secret partagé et l'incluent dans un en-tête, comme X-Signature. Votre serveur recalcule le hash et le compare à l'en-tête. S'ils correspondent, la requête est authentique.

Voici un exemple simple en Python :

import hmac
import hashlib

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

Utilisez toujours une fonction de comparaison à temps constant comme hmac.compare_digest pour éviter les attaques temporelles.

Erreurs courantes à éviter

Concevoir des réessais fiables

Les webhooks sont envoyés sur Internet, les échecs sont donc inévitables. Les réseaux tombent, les serveurs redémarrent et les points de terminaison expirent. Un bon système de webhook réessaie les livraisons échouées avec un backoff exponentiel.

Comment fonctionnent généralement les réessais

Les fournisseurs réessaient généralement avec des délais croissants : après 1 minute, 5 minutes, 30 minutes, etc., jusqu'à un nombre maximum de tentatives (par exemple 5-10). Si tous les réessais échouent, l'événement est marqué comme échoué et peut être disponible pour un rejeu manuel.

Votre point de terminaison doit répondre rapidement avec un code de statut 2xx pour accuser réception. Si vous renvoyez un code non-2xx ou si vous expirez, le fournisseur réessaiera.

Implémenter l'idempotence

Parce que les réessais peuvent provoquer des livraisons en double, votre point de terminaison doit être idempotent. Utilisez l'ID d'événement (inclus dans le payload ou les en-têtes) pour suivre les événements traités. Avant de traiter, vérifiez si vous avez déjà géré cet ID. Stockez les ID traités dans une base de données avec une TTL.

Exemple de vérification d'idempotence :

def process_event(event_id, data):
    if db.exists(f"processed:{event_id}"):
        return  # déjà traité
    # traiter les données
    db.setex(f"processed:{event_id}", 86400, "1")  # expire après 24h

Construire un récepteur de webhook : étape par étape

  1. Exposez un point de terminaison HTTPS : Utilisez TLS pour protéger les données en transit.
  2. Vérifiez la signature : Rejetez les requêtes avec des signatures invalides avec un 401.
  3. Vérifiez l'horodatage : S'il est fourni, assurez-vous qu'il est dans une fenêtre acceptable (par exemple 5 minutes).
  4. Analysez le payload : Validez la structure JSON et les champs requis.
  5. Vérifiez l'idempotence : Utilisez l'ID d'événement pour éviter les doublons.
  6. Traitez de manière asynchrone : Répondez immédiatement avec 200, puis traitez dans une tâche en arrière-plan pour éviter les expirations.
  7. Journalisez et surveillez : Enregistrez les échecs et configurez des alertes.

Tester les webhooks localement

Pendant le développement, vous avez besoin d'un moyen de recevoir des webhooks sur votre machine locale. Des outils comme ngrok ou localtunnel créent une URL publique qui redirige vers votre localhost. Alternativement, de nombreux fournisseurs offrent une CLI pour déclencher des événements de test.

Testez toujours la vérification de signature avec des signatures valides et invalides. Simulez des réessais en renvoyant des codes d'erreur et en observant le comportement de réessai du fournisseur.

Comparaison : Webhooks vs Polling

AspectWebhooksPolling
Temps réelQuasi temps réelRetardé par l'intervalle
EfficacitéEnvoie des données uniquement lors d'un événementRequêtes fréquentes même sans données
ComplexitéNécessite un point de terminaison, vérification de signature, réessaisPlus simple à implémenter
FiabilitéDépend du mécanisme de réessaiVous contrôlez la planification

FAQ

Qu'est-ce qu'un payload de webhook signé ?

Un payload signé inclut une signature cryptographique (généralement HMAC) qui permet au récepteur de vérifier que la requête provient de l'expéditeur attendu et n'a pas été altérée.

Combien de fois un webhook doit-il être réessayé ?

La plupart des fournisseurs réessaient 5 à 10 fois avec un backoff exponentiel. Le nombre exact dépend de la politique du fournisseur. Votre point de terminaison doit être idempotent pour gérer les doublons.

Quel code de statut HTTP mon webhook doit-il renvoyer ?

Renvoyez un code de statut 2xx (par exemple 200 OK) pour accuser réception avec succès. Tout autre code (4xx ou 5xx) signale un échec et déclenche des réessais.

Prêt à tester vos payloads de webhook ? Utilisez notre JSON Formatter pour valider et embellir rapidement les payloads JSON.