Vérifier les signatures, enregistrer durablement les événements et maîtriser leur traitement.
Contenu relu:
Les webhooks Stripe informent votre application des changements liés aux abonnements, factures et paiements. Les livraisons peuvent se répéter ou arriver dans le désordre, et votre traitement peut échouer après réception. Prévoyez explicitement chacun de ces cas.
Avant de commencer
Un environnement de test Stripe et une CLI installée, authentifiée avec des identifiants de test uniquement.
Une route HTTP POST sous votre contrôle ; les exemples locaux utilisent localhost:4242/webhook.
Une base ou une file durable et un processus de traitement pour la production.
Périmètre
Conception d'une intégration avec événements snapshot et tests locaux élémentaires. Le modèle officiel est une base de gestionnaire, pas une file durable de production. Ajoutez persistance, réservation atomique, reprise et effets idempotents avant le déploiement.
Étape 1
Ce qu'est vraiment un webhook
Stripe → verify → durable acceptance → retryable worker → idempotent effects. Acknowledge only after persistence.
Stripe envoie une requête HTTP POST décrivant un événement à l'URL configurée. Dans Workbench → Webhooks → Create event destination, choisissez des événements snapshot si votre intégration lit event.data.object. Votre serveur vérifie l'événement et l'enregistre durablement ; un processus applique ensuite les changements métier.
Étape 2
Vérifier la signature à chaque requête
Vérifiez chaque signature avec le SDK officiel : stripe.webhooks.constructEvent(rawBody, signature, secret). Sans cette vérification, un tiers pourrait envoyer de faux événements. Si elle lève une exception, renvoyez 400 et ne traitez pas la requête.
La signature doit être vérifiée sur le corps brut de la requête, avant toute transformation JSON. Configurez cette route pour conserver les octets reçus et l'en-tête de signature.
Étape 3
S'abonner uniquement aux événements utiles
Sélectionnez les événements que votre intégration sait traiter, par exemple customer.subscription.created, customer.subscription.updated, customer.subscription.deleted, invoice.paid, invoice.payment_failed et customer.updated. Documentez le rôle de chaque traitement. Évitez tous les événements sans politique de gestion définie.
Tests uniquement : vérifiez le compte CLI et les identifiants de test ; n'ajoutez jamais --live. Lancez votre serveur à cette adresse ou adaptez-la. Utilisez le secret de signature de l'écoute dans l'environnement serveur, pas celui d'une destination du Dashboard. Gardez ce secret privé et laissez ce terminal ouvert.
Étape 4
Enregistrer avant d'acquitter, puis traiter en arrière-plan
Vérifiez la signature, enregistrez durablement l'événement dans une file persistante ou une transaction validée, puis répondez rapidement avec 2xx après cet enregistrement. Si la persistance échoue, ne confirmez pas la réception. Le processus doit réserver atomiquement le travail en attente, appliquer les changements et réessayer les échecs. Une tâche en mémoire lancée avant la réponse 200 ne constitue pas un enregistrement durable.
Astuce
Une table d'événements en attente peut remplacer une file si elle gère les réservations atomiques, leur expiration, les nouvelles tentatives et la surveillance des erreurs. Distinguez received_at de processed_at.
Étape 5
Gérer l'idempotence
Unique event id prevents duplicate storage, not unfinished processing. Retry the pending record; mark success only after processing.
Un event_id unique évite les doublons dans la table de réception, mais une insertion réussie ne signifie PAS un traitement réussi. En cas de nouvelle livraison, réutilisez l'enregistrement en attente plutôt que d'abandonner un travail inachevé. Réservez-le atomiquement et rendez les effets métier idempotents, y compris les appels externes avec des clés adaptées. Renseignez processed_at uniquement après un traitement réussi ; un échec reste à réessayer. Coordonnez les écritures en base et les effets externes pour qu'un arrêt entre les deux ne répète ni prélèvement ni notification.
Étape 6
Prévoir le désordre et les accès concurrents
Les événements peuvent arriver dans le désordre et plusieurs traitements se concurrencer. Relisez l'état actuel via l'API Stripe pour synchroniser une vue courante, mais conservez l'événement immuable pour les effets historiques ou comptables. L'état actuel ne remplace pas ce qui s'est passé à la date de l'événement. Sérialisez les traitements par objet et appliquez des règles de version ou de rapprochement adaptées ; l'ordre de réception n'est pas l'ordre causal.
Attention
Testez l'ordre de livraison inversé et les traitements concurrents d'un même objet, pas seulement les identifiants d'événements dupliqués.
Étape 7
Prévoir une reprise contrôlée
Construisez une reprise à partir des événements enregistrés durablement. Une nouvelle livraison doit réutiliser l'enregistrement en attente et reprendre le travail inachevé, sans être écartée par la déduplication sur l'identifiant. Réservez cette opération aux personnes autorisées, journalisez-la et préservez l'idempotence des effets métier. Toute réexécution volontaire d'un événement déjà traité doit être une opération distincte et vérifiée.
Étape 8
Surveiller la livraison et le traitement séparément
Suivez les réponses hors 2xx, l'ancienneté du travail en attente, les réservations expirées, les erreurs de traitement et les écarts de rapprochement. Une réponse 200 prouve seulement la réception, pas l'achèvement. Enregistrez un statut structuré, le nombre de tentatives, la prochaine échéance et la dernière erreur ; alertez sur les tâches bloquées et prévoyez une correction autorisée. Définissez des règles de conservation, d'accès et de masquage des données personnelles et des secrets.
Générer un échec de test
stripe trigger invoice.payment_failed
Dans un second terminal du même environnement de test, lancez cette commande pendant l'écoute. Elle crée des objets de test, sans prélèvement réel ni reprise d'un événement existant. Vérifiez la réponse HTTP et l'achèvement du traitement durable. Testez séparément les doublons, l'ordre et la reprise après incident.
Vérifiez les signatures, enregistrez durablement les événements et rendez les effets idempotents. Distinguez synchronisation courante et effets historiques, surveillez le travail inachevé et testez la reprise après échec. Ces contrôles réduisent les risques sans supprimer tous les incidents.
Connectez Stripe à FlowMRR pour synchroniser les données de facturation et suivre le revenu récurrent. Vérifiez l'état de connexion et la dernière synchronisation : la configuration seule ne prouve pas le traitement.
Faut-il gérer chaque événement envoyé par Stripe ?+
Non. Sélectionnez uniquement les événements nécessaires à votre application et documentez leur traitement. Les types non sélectionnés ne sont pas livrés à cette destination.
Quelle architecture de base pour les webhooks ?+
Prévoyez une table de réception durable avec event_id unique, type, données de l'événement, received_at, processed_at, statut, expiration de réservation, nombre de tentatives, prochaine échéance et dernière erreur. La réservation atomique évite les traitements concurrents ; l'identifiant unique évite les doublons de stockage, pas les effets métier répétés. Renseignez processed_at uniquement après réussite et contrôlez conservation et accès.
Exposer les webhooks derrière un CDN ou directement ?+
Les deux conviennent si la route conserve le corps brut et l'en-tête de signature, accepte les requêtes Stripe sans contrôle interactif et ne met pas les réponses en cache. Testez la signature derrière le CDN ou le mandataire réellement déployé. Aucun réglage spécial Cloudflare universel n'est requis pour les webhooks Stripe.