Webhooks expliqués : charges signées et tentatives

Backend2026-10-17TryQuickToolBox

Vous venez d'intégrer une passerelle de paiement. La documentation indique : « Nous enverrons un webhook à votre point de terminaison lorsqu'un paiement réussit. » Vous configurez une route simple, la testez localement et déployez. Puis, en production, vous remarquez des événements en double, des notifications manquées et de mystérieuses erreurs 500. Les webhooks semblent simples—jusqu'à ce qu'ils ne le soient plus.

Ce guide explique comment les webhooks fonctionnent réellement, pourquoi les charges signées sont importantes et comment construire une logique de réessai qui maintient votre système synchronisé même lorsque les choses tournent mal.

Qu'est-ce qu'un webhook ?

Un webhook est un rappel HTTP : un système envoie une requête HTTP POST à une URL que vous fournissez lorsqu'un événement spécifique se produit. Contrairement au polling, où vous demandez répétitivement « Est-ce que quelque chose s'est passé ? », les webhooks vous poussent les événements en quasi temps réel.

Utilisations courantes :

L'expéditeur (par exemple, Stripe, GitHub) est le fournisseur de webhook ; votre serveur est le consommateur de webhook.

Pourquoi les charges signées sont essentielles

Votre point de terminaison de webhook est accessible publiquement. Quiconque connaît l'URL peut envoyer de faux événements. Sans vérification, un attaquant pourrait usurper un événement « paiement réussi » et vous pourriez expédier des marchandises gratuitement.

Les charges signées résolvent ce problème en incluant une signature cryptographique dans les en-têtes de la requête, générée avec un secret partagé connu uniquement de vous et du fournisseur. Lorsque vous recevez un webhook, vous recalculez la signature et comparez. Si elles correspondent, la charge est authentique.

Comment fonctionnent les signatures HMAC

La plupart des fournisseurs utilisent HMAC-SHA256. Le fournisseur calcule :

signature = HMAC-SHA256(secret, payload)

et l'envoie dans un en-tête comme X-Signature. Votre serveur effectue le même calcul et vérifie l'égalité. Comme le secret est secret, seul le fournisseur peut générer une signature valide.

Vérifier une signature en pratique

Voici un exemple minimal en Node.js avec Express :

const crypto = require('crypto');
const express = require('express');
const app = express();

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  const payload = req.body; // Buffer brut

  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  if (signature !== expected) {
    return res.status(401).send('Signature invalide');
  }

  // Traiter l'événement
  const event = JSON.parse(payload);
  console.log('Événement reçu :', event.type);
  res.status(200).send('OK');
});

app.listen(3000);

Important : Utilisez toujours le corps brut de la requête pour la vérification de signature. Si vous analysez d'abord le JSON, la chaîne sérialisée peut différer (espaces, ordre des clés) et la vérification de signature échouera.

Pièges courants

Réessais : gérer les échecs avec élégance

Les réseaux échouent, les serveurs redémarrent et les déploiements ont lieu. Les fournisseurs de webhooks s'attendent à ce que votre point de terminaison soit temporairement indisponible, ils réessaient donc les livraisons échouées. Mais les réessais introduisent de nouveaux défis : événements en double, livraison dans le désordre et boucles infinies si vous ne faites pas attention.

Comment les fournisseurs réessaient

La plupart des fournisseurs utilisent un backoff exponentiel : ils attendent un court laps de temps après le premier échec, puis des intervalles progressivement plus longs. Par exemple, Stripe réessaie jusqu'à 3 jours avec des délais croissants. GitHub réessaie jusqu'à 8 fois. Le calendrier exact varie, mais le modèle est cohérent.

Votre point de terminaison doit retourner un code de statut 2xx rapidement pour accuser réception. Tout autre statut (4xx, 5xx) signale un échec et déclenche un réessai.

Construire des gestionnaires idempotents

Parce que les réessais peuvent livrer le même événement plusieurs fois, votre gestionnaire doit être idempotent : traiter le même événement deux fois doit avoir le même effet que le traiter une fois.

Stratégies courantes :

Exemple utilisant un simple ensemble en mémoire (à titre d'illustration ; utilisez un stockage persistant en production) :

const processedEvents = new Set();

app.post('/webhook', (req, res) => {
  const event = req.body;
  if (processedEvents.has(event.id)) {
    return res.status(200).send('Déjà traité');
  }
  // Traiter l'événement...
  processedEvents.add(event.id);
  res.status(200).send('OK');
});

Répondre rapidement

Les fournisseurs ont souvent un délai d'attente (par exemple, 5 secondes). Si votre gestionnaire effectue un traitement lourd, accusez réception immédiatement et traitez de manière asynchrone. Par exemple, poussez l'événement dans une file d'attente et retournez 200.

Meilleures pratiques pour des webhooks fiables

  1. Vérifiez toujours les signatures en utilisant le corps brut et une comparaison à temps constant.
  2. Utilisez HTTPS pour votre point de terminaison afin de prévenir l'écoute clandestine et la falsification.
  3. Implémentez l'idempotence pour gérer les livraisons en double.
  4. Journalisez tout — charges utiles entrantes, signatures et vos réponses — pour le débogage.
  5. Surveillez les échecs et configurez des alertes pour les erreurs répétées.
  6. Testez avec des événements réels en utilisant les tableaux de bord des fournisseurs ou des outils CLI.
  7. Gérez les événements dans le désordre en incluant des horodatages ou des numéros de séquence dans votre logique.

Comparaison : Polling vs. Webhooks

AspectPollingWebhooks
LatenceDépend de l'intervalleQuasi temps réel
Charge serveurÉlevée (requêtes constantes)Faible (uniquement sur événements)
ComplexitéSimple à implémenterNécessite un point de terminaison, sécurité, réessais
FiabilitéVous contrôlez les réessaisLe fournisseur contrôle les réessais

FAQ

Qu'est-ce qu'une signature de webhook ?

Une signature de webhook est un hachage cryptographique (généralement HMAC-SHA256) de la charge utile, généré avec un secret partagé. Il permet au récepteur de vérifier que la requête provient de l'expéditeur attendu et n'a pas été falsifiée.

Comment gérer les événements de webhook en double ?

Rendez votre gestionnaire idempotent en suivant les ID d'événement ou en utilisant des opérations de base de données naturellement idempotentes. Vérifiez si un événement a déjà été traité avant d'appliquer des modifications.

Que doit retourner mon point de terminaison de webhook ?

Retournez un code de statut 2xx (par exemple, 200 OK) dès que vous avez reçu et validé l'événement. Si vous devez effectuer un traitement lourd, accusez réception immédiatement et gérez le travail de manière asynchrone.

Prêt à tester vos charges utiles de webhook ? Utilisez notre JSON Formatter pour inspecter et valider la structure JSON des événements entrants.