Aller au contenu principal
Tous les articles
Technique4 min de lecture

Réussir son intégration des webhooks

Cinq erreurs qui reviennent dans presque toutes les intégrations, et le traitement en quinze lignes qui les évite toutes.

Un paiement n'aboutit pas au moment où vous l'appelez. L'acheteur passe par sa banque, valide une authentification, revient — ou ne revient pas. Le résultat vous parvient par webhook, et c'est cette notification qui fait foi.

Autant dire que la qualité de votre traitement de webhooks décide de la fiabilité de tout votre encaissement. Voici les cinq erreurs que nous voyons le plus souvent.

1. Vérifier la signature après avoir parsé le JSON

C'est l'erreur la plus fréquente et la plus silencieuse. La signature est calculée sur le corps brut de la requête. Si votre framework parse le JSON avant que vous n'y touchiez, puis que vous re-sérialisez l'objet pour vérifier, vous obtenez des octets différents — un espace, un ordre de clés, un nombre reformaté — et la signature ne correspond plus.

Configurez votre route pour conserver le corps brut, vérifiez la signature dessus, et ne parsez qu'après.

2. S'abonner à tout

L'API vous laisse déclarer une liste explicite d'événements. La tentation est de tout cocher « au cas où ».

Chaque événement auquel vous vous abonnez est un événement que votre code doit savoir ignorer proprement. Un switch sans branche par défaut, un log qui grossit, une alerte qui se déclenche pour rien : la liste courte est la liste sûre. Abonnez-vous à ce que vous traitez, et rien de plus.

3. Ne pas dédupliquer

Une même notification peut arriver deux fois. Ce n'est pas un défaut, c'est une garantie : nous préférons livrer deux fois que perdre une fois.

Chaque livraison porte un identifiant d'événement. Stockez-le — une table avec une contrainte d'unicité suffit — et sortez immédiatement si vous l'avez déjà vu. Sans cela, un accusé de réception perdu vous fait expédier deux fois la même commande.

4. Faire le travail lourd dans la requête

Envoyer un e-mail, générer une facture PDF, appeler trois services internes : si tout cela se fait avant votre réponse, votre traitement prend des secondes. Nous considérons alors la livraison en échec et nous rejouons. Vous refaites le travail. Le cycle s'emballe, et l'endpoint finit suspendu.

Accusez réception avec un 200 dès que vous avez écrit l'événement quelque part, et faites le reste en tâche de fond.

5. Croire la redirection plutôt que le webhook

Ce n'est pas un problème de webhook, c'est le problème que le webhook résout. Un acheteur qui ferme son onglet après le paiement ne verra jamais votre page de retour. Si votre commande n'est validée que là, elle ne le sera jamais — alors que l'argent, lui, est bien arrivé.

Le traitement, en quinze lignes

javascript
export async function POST(request) {
  const raw = await request.text();               // le corps brut, d'abord
  if (!verifySignature(raw, request.headers)) {
    return new Response('bad signature', { status: 401 });
  }

  const event = JSON.parse(raw);
  const known = await db.events.findByEventId(event.id);
  if (known) return new Response('ok');           // déjà traité

  await db.events.insert({ eventId: event.id, payload: event });
  await queue.push('handle-payment-event', event.id);

  return new Response('ok');                      // accusé, le reste suit
}

Vérifier, dédupliquer, accuser, déléguer. Le reste de votre logique métier vit dans la tâche de fond, où elle peut échouer et être rejouée sans conséquence sur la livraison.

Rejouer une livraison échouée

Votre serveur était en maintenance, une livraison a échoué : rien n'est perdu. Le journal des livraisons du portail montre chaque livraison — son nombre de tentatives, la dernière réponse de votre serveur (code HTTP compris) et le corps exact de l'événement. Le rejeu se fait en un clic — ou par l'API, si vous voulez l'intégrer à votre supervision.

Deux réflexes rendent ce rejeu sans danger. D'abord, la déduplication du point 3 : un événement rejoué porte le même identifiant, votre traitement le reconnaît et sort. Ensuite, ne corrigez jamais un incident en modifiant votre base à la main *puis* en rejouant l'événement — vous appliqueriez le même effet deux fois. Rejouez d'abord, vérifiez ensuite.

Un endpoint qui échoue en continu finit suspendu, pour vous protéger comme pour nous. La reprise après suspension suit le même chemin : corrigez, testez avec un événement de test, réactivez, puis rejouez les livraisons manquées dans l'ordre chronologique.

Sécuriser l'endpoint au-delà de la signature

La signature HMAC authentifie le contenu ; elle ne dispense pas des règles d'hygiène autour.

  • HTTPS uniquement — l'API refuse de toute façon de déclarer un endpoint en HTTP clair.
  • Horodatage vérifié : chaque livraison est datée. Rejetez ce qui est plus vieux que quelques minutes, et vous fermez la porte au rejeu d'une requête capturée.
  • Réponse minimale : votre endpoint n'a rien à raconter. Un 200 vide suffit ; un corps d'erreur détaillé renseigne surtout un attaquant.
  • Secret par environnement : le secret de signature sandbox et celui de production sont distincts. Un événement de test signé avec la clé sandbox ne doit jamais être accepté par votre endpoint de production.

Aucune de ces règles ne coûte plus de quelques lignes. Ensemble, elles font d'un endpoint de webhook exposé sur Internet un composant aussi sûr que le reste de votre intégration.

Un dernier conseil

Envoyez-vous un événement de test avant d'ouvrir la production. L'API le propose sur chaque endpoint déclaré, et le journal des livraisons vous dit ce que votre serveur a répondu. Découvrir un problème de signature à ce moment-là coûte cinq minutes ; le découvrir en production coûte une journée d'enquête.

Écrit par Équipe ChariPay.

À lire ensuite

Une question sur votre intégration ?

Notre équipe répond aux commerçants comme aux développeurs, du premier test jusqu'à la mise en production.