Accéder directement au contenu
Créez un compte ou connecter-vous
Logo de la documentation Stripe
/
Demander à l'assistant IA
Créez un compteConnectez-vous
Démarrer
Paiements
Revenus
Plateformes et marketplaces
Gestion de fonds
Ressources pour les développeurs
API et SDKAide
Aperçu
Gestion des versions
Journal des modifications
Mettre à niveau votre version de l'API
Actualiser votre version du SDK
Essentials
SDK
API
Tests
CLI Stripe
Exemples de projets
Outils
Dashboard Stripe
Workbench
Dashboard des développeurs
Stripe pour Visual Studio Code
Terraform
Fonctionnalités
Workflows
Destinations d'événements
    Intégrer avec les événements
    Amazon EventBridge
    Endpoint de webhook
      Outil de création de webhook
      Gérer les événements de paiement
      Contrôle des versions de webhook
      Migration vers des événements légers
      Corriger les erreurs de vérification de la signature du webhook
      Traiter les événements non envoyés
      Gérer les événements de webhook non récupérables
      Gérez les webhooks à l’aide de gestionnaires de notifications d’événements
Alertes d'intégrité de StripeChargements de fichiers
Solutions d'IA
Boîte à outils des agents
Modèle de protocole contextuelCréer des flux de facturation SaaS avec l’IA agentique
Sécurité et confidentialité
Sécurité
Robot d'exploration Web Stripebot
Extensions Stripe
Créer des applications Stripe
Utiliser les applications de Stripe
Partenaires
Partner ecosystem
Certification des partenaires
États-Unis
Français (France)
AccueilRessources pour les développeursEvent destinationsWebhook endpoint

Migrer des événements instantanés vers des événements légers

Découvrez comment migrer vers des événements légers sans perturber la production.

Version bêta privée

Les événements légers pour les ressources API v1 sont disponibles en version bêta privée. Auparavant, les événements légers prenaient uniquement en charge les ressources API v2. En savoir plus et demander l’accès.

Les événements légers offrent une alternative légère et stable entre les versions aux événements instantanés. Au lieu de recevoir des objets ressource complets dans les charges utiles webhook, vous recevez des notifications compactes et récupérez les détails dont vous avez besoin. Cela élimine la nécessité de mettre à jour les gestionnaires webhook lors de la mise à niveau des versions d’API.

Utilisez ce guide pour migrer des événements instantanés vers les événements légers sans perturber la production. La migration utilise une stratégie à double destination où les deux gestionnaires s’exécutent en parallèle pendant la transition. Pour un aperçu complet des événements légers, y compris les avantages et les cas d’usage, consultez Événements légers.

Versions légères des événements instantanés

Pour faciliter la migration, Stripe crée des versions d’événement léger de vos événements instantanés existants. Par exemple, customer.created a une version légère v1.customer.created. Lors de la migration, lorsqu’une seule action déclenche les deux événements, la version légère inclut un champ snapshot_event contenant l’ID d’événement instantané d’origine. Utilisez-le comme clé d’idempotence pour éviter les doublons de traitement lorsque vous exécutez les deux gestionnaires simultanément.

Avant de commencer

Assurez-vous d’avoir :

  • Accès au code de votre endpoint webhook pour ajouter un nouvel acheminement
  • Autorisation de créer des destinations événements dans votre Dashboard Stripe ou avec l’API
  • Accès à un environnement de test ou à un mode test pour valider la migration avant la mise en service
  • Surveillance et enregistrement pour comparer le comportement des gestionnaires

Avertissement

Effectuez tout ce processus de migration dans un environnement de test ou en mode test avant d’essayer de le déployer en mode production.

Stratégie de migration progressive

La migration comprend les phases suivantes :

  1. Ajoutez un nouvel acheminement de webhook léger à votre formulaire d’inscription.
  2. Créez une destination d’événement léger qui reflète vos abonnements existants.
  3. Exécutez en shadow mode pour valider le comportement sans apporter de modifications.
  4. Transférez avec idempotence pour gérer les deux destinations simultanément.
  5. Retirez la destination 'instantanée après avoir confirmé sa stabilité.

Cette stratégie garantit que vous n’avez pas de temps d’indisponibilité et vous donne de multiples opportunités de valider et d’annuler si nécessaire.

Ajouter un acheminement webhook léger

Créez un nouvel endpoint dans votre formulaire d’inscription spécifiquement pour les événements légers. Commencez par une implémentation minimale qui vérifie uniquement les signatures et renvoie un code d’état 200.

Remarque

Pour accéder au champ snapshot_event, configurez votre SDK Stripe afin d’utiliser une version bêta de l’API :

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY, { apiVersion: '2025-11-17.preview' });

Les versions API stables (.clover) n’incluent pas de fonctionnalités de version bêta privée comme snapshot_event.

const express = require('express'); const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY, { apiVersion: '2025-11-17.preview' }); const app = express(); // New thin event endpoint app.post( '/webhook/thin', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const thinWebhookSecret = process.env.THIN_WEBHOOK_SECRET; try { // Verify the signature using the same method as snapshot events const thinNotification = stripe.webhooks.constructEvent( req.body, sig, thinWebhookSecret ); console.log(`Verified thin event: ${thinNotification.id}`); // For now, just acknowledge receipt res.sendStatus(200); } catch (err) { console.log(`Webhook Error: ${err.message}`); res.status(400).send(`Webhook Error: ${err.message}`); } } ); app.listen(3000, () => console.log('Running on port 3000'));

Déployez cette modification et vérifiez que l’endpoint est accessible.

Créer une destination d’événement léger

Dans le Dashboard ou l’API de Stripe, créez une nouvelle destination d’événements configurée pour les événements légers.

Utiliser le Dashboard

  1. Accédez à Développeurs > Webhooks.
  2. Cliquez sur Ajouter destination.
  3. Sous Paramètres avancés, activez Utiliser les événements légers.
  4. Abonnez-vous aux mêmes types d’événements que ceux utilisés par votre destination instantanée, mais avec le préfixe v1. :
    • customer.created → v1.customer.created
    • payment_intent.succeeded → v1.payment_intent.succeeded
    • invoice.paid → v1.invoice.paid
  5. Saisissez l’URL de votre nouvel endpoint (par exemple, https://yourdomain.com/webhook/thin)

Utiliser l’API

Command Line
curl https://api.stripe.com/v2/core/event_destinations \ -H "Authorization: Bearer sk_test_..." \ -H "Stripe-Version: 2025-11-17.preview" \ -d "name"="Thin Events Destination" \ -d "type"="webhook_endpoint" \ -d "event_payload"="thin" \ -d "webhook_endpoint[url]"="https://yourdomain.com/webhook/thin" \ -d "enabled_events[]"="v1.customer.created" \ -d "enabled_events[]"="v1.payment_intent.succeeded" \ -d "enabled_events[]"="v1.invoice.paid"

Remarque

Stockez la nouvelle clé secrète de signature webhook séparément de votre clé secrète webhook instantanée. Libellez-les clairement (par exemple, SNAPSHOT_WEBHOOK_SECRET et THIN_WEBHOOK_SECRET) pour éviter de les mélanger.

À ce stade, les deux destinations sont actives et envoient des événements à votre application.

Exécuter en shadow mode

Mettez à jour votre gestionnaire de webhook léger pour récupérer les détails de l’événement et les objets associés, mais n’écrivez pas encore dans votre base de données. Enregistrez plutôt les actions que vous feriez pour pouvoir surveiller que votre gestionnaire léger se comporte de la même manière que votre gestionnaire instantané.

Ajoutez ces composants à votre gestionnaire à l’étape 1 :

  1. Activez un flag en shadow mode (ajoutez-le en haut de votre fichier) :
// Enable shadow mode via environment variable const SHADOW_MODE = process.env.SHADOW_MODE !== 'false';
  1. Récupérer les détails complets de l’événement (ajouter après la vérification de la signature) :
// Fetch the full event details const event = await stripe.v2.core.events.retrieve(thinNotification.id); console.log(`Processing ${event.type} (thin ID: ${event.id})`); // For interop events, log the original snapshot event ID if (event.snapshot_event) { console.log(`Correlated snapshot event: ${event.snapshot_event}`); }
  1. Récupérer l’objet associé et le shadow log (ajouter une logique de gestion des événements) :
// Fetch the related object if needed if (event.type === 'v1.customer.created') { const customer = await stripe.customers.retrieve(event.related_object.id); if (SHADOW_MODE) { // SHADOW MODE: Log what you would do, but don't do it yet console.log(`[SHADOW] Would create customer record: ${customer.id}`); // recordMetric('customer.created.thin', 1); } else { // Production mode: Actually write to database await createCustomerInDatabase(customer); } }
  1. Finalisez le gestionnaire avec le shadow mode :
const SHADOW_MODE = process.env.SHADOW_MODE !== 'false'; // ← NEW app.post( '/webhook/thin', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const thinWebhookSecret = process.env.THIN_WEBHOOK_SECRET; try { const thinNotification = stripe.webhooks.constructEvent( req.body, sig, thinWebhookSecret ); // ← NEW: Fetch full event details const event = await stripe.v2.core.events.retrieve(thinNotification.id); console.log(`Processing ${event.type} (thin ID: ${event.id})`); // ← NEW: Log snapshot event ID for correlation if (event.snapshot_event) { console.log(`Correlated snapshot event: ${event.snapshot_event}`); } // ← NEW: Fetch related object and handle in shadow mode if (event.type === 'v1.customer.created') { const customer = await stripe.customers.retrieve(event.related_object.id); if (SHADOW_MODE) { console.log(`[SHADOW] Would create customer record: ${customer.id}`); } else { await createCustomerInDatabase(customer); } } res.sendStatus(200); } catch (err) { console.log(`Webhook Error: ${err.message}`); res.status(400).send(`Webhook Error: ${err.message}`); } } );

Ce qu’il faut rechercher en shadow mode

Exécutez le shadow mode pendant au moins 24 à 48 heures et surveillez :

  • Vérification de la signature : confirmez que tous les événements légers ont été vérifiés.
  • Récupérer la latence : mesurez le temps nécessaire pour récupérer les événements et les objets associés.
  • Cohérence du comportement : comparez les logs fantômes au comportement réel de votre gestionnaire instantané.
  • Taux d’erreur : surveillez les défaillances inattendues ou données manquantes.

Si les logs fantômes de votre gestionnaire léger diffèrent de ce que fait réellement le gestionnaire instantané, examinez et corrigez cette erreur dès maintenant (sans impact sur la production).

Remarque

Pour les événements interop, le champ snapshot_event contient l’ID de l’événement instantané d’origine. Enregistrez à la fois l’event.id léger et l’event.snapshot_event pour mettre en corrélation les événements entre les deux gestionnaires pendant la transition.

Transférer avec idempotence

Lorsque le shadow mode fonctionne correctement, activez les écritures réelles dans votre gestionnaire léger. Gardez les deux destinations actives pendant une brève période de chevauchement pour ne manquer aucun événement.

Mettre en œuvre l’idempotence

Lors du chevauchement, vous pouvez recevoir deux fois le même événement logique : une fois en tant qu’événement instantané et une fois en tant qu’événement léger. Utilisez des clés d’idempotence pour éviter les doublons de traitement.

Remarque

Le champ snapshot_eventdans les événements interop légers contient l’ID de l’événement instantané d’origine. En utilisant ce champ comme clé d’idempotence, les deux gestionnaires peuvent dédupliquer avec la même clé.

Tout d’abord, configurez une table de base de données d’idempotence :

CREATE TABLE event_idempotency ( idempotency_key TEXT PRIMARY KEY, event_type TEXT NOT NULL, processed_at INTEGER NOT NULL );

Ensuite, implémentez l’assistant d’idempotence :

// Try to insert idempotency key. Returns true if successfully inserted, false if duplicate. function tryInsertIdempotencyKey(idempotencyKey, eventType) { try { db.prepare(` INSERT INTO event_idempotency (idempotency_key, event_type, processed_at) VALUES (?, ?, ?) `).run(idempotencyKey, eventType, Date.now()); return true; // Insert succeeded - event is new } catch (err) { if (err.code === 'SQLITE_CONSTRAINT') { return false; // Duplicate - event already processed (use your database-specific error code for unique constraint violations) } throw err; // Re-throw unexpected errors } }

Mettez à jour les deux gestionnaires pour utiliser ce modèle. Tout d’abord, le gestionnaire instantané :

app.post( '/webhook/snapshot', express.raw({type: 'application/json'}), (req, res) => { const sig = req.headers['stripe-signature']; const snapshotWebhookSecret = process.env.SNAPSHOT_WEBHOOK_SECRET; try { const event = stripe.webhooks.constructEvent( req.body, sig, snapshotWebhookSecret ); // For snapshot events, idempotency key is just the event ID const idempotencyKey = event.id; // Try to insert idempotency key. If fails (duplicate), skip processing. if (!tryInsertIdempotencyKey(idempotencyKey, event.type)) { console.log(`Already processed: ${idempotencyKey}`); return res.sendStatus(200); } // Process the event if (event.type === 'customer.created') { createCustomerInDatabase(event.data.object); } res.sendStatus(200); } catch (err) { console.log(`Webhook Error: ${err.message}`); res.status(400).send(`Webhook Error: ${err.message}`); } } );

En ce qui concerne le gestionnaire léger :

const SHADOW_MODE = process.env.SHADOW_MODE !== 'false'; app.post( '/webhook/thin', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const thinWebhookSecret = process.env.THIN_WEBHOOK_SECRET; try { const thinNotification = stripe.webhooks.constructEvent( req.body, sig, thinWebhookSecret ); const event = await stripe.v2.core.events.retrieve(thinNotification.id); // For thin interop events, use snapshot_event if present, otherwise event ID const idempotencyKey = event.snapshot_event || event.id; // Check idempotency first to avoid unnecessary work if (!SHADOW_MODE) { // Try to insert idempotency key. If fails (duplicate), skip processing. if (!tryInsertIdempotencyKey(idempotencyKey, event.type)) { console.log(`Already processed: ${idempotencyKey}`); return res.sendStatus(200); } } // Process the event if (event.type === 'v1.customer.created') { const customer = await stripe.customers.retrieve(event.related_object.id); if (!SHADOW_MODE) { // Process the event createCustomerInDatabase(customer); } else { console.log(`[SHADOW] Would create customer: ${customer.id}`); console.log(`[SHADOW] Idempotency key: ${idempotencyKey}`); } } res.sendStatus(200); } catch (err) { console.log(`Webhook Error: ${err.message}`); res.status(400).send(`Webhook Error: ${err.message}`); } } );

Comment éviter les doublons :

  1. Lorsqu’un client est créé, Stripe génère les deux événements :

    • Événement instantané : evt_abc123
    • Événement léger : evt_xyz789 avec snapshot_event: "evt_abc123"
  2. Les deux gestionnaires reçoivent les événements simultanément :

    • Gestionnaire instantané : idempotencyKey = event.id > "evt_abc123"
    • Gestionnaire léger : idempotencyKey = event.snapshot_event || event.id → "evt_abc123"
  3. Les deux gestionnaires essaient d’insérer la même clé :

    • Gestionnaire instantané : INSERT INTO ... VALUES ('evt_abc123', ...) > succeeds
    • Gestionnaire léger : INSERT INTO ... VALUES ('evt_abc123', ...) > unique constraint violation
  4. Résultat : le client est créé.

Surveiller la transition

Avec les deux gestionnaires qui écrivent dans votre base de données :

  • Surveiller la détection des doublons : confirmez que votre logique d’idempotence détecte les événements dédoublés.
  • Comparaison des modèles d’écriture : assurez-vous que les gestionnaires léger et instantané produisent des états de base de données identiques.
  • Suivre les taux d’erreur : alerte en cas d’augmentation des échecs.
  • Surveiller les performances : mesurez l’impact des appels API supplémentaires pour récupérer les objets associés.

Avertissement

Si quelque chose ne va pas, désactivez l’écriture dans le gestionnaire léger et faites vos recherches. Votre gestionnaire instantané reste votre point de référence jusqu’à ce que vous ayez confiance dans le chemin léger.

Faites en sorte que la fenêtre de chevauchement soit courte (quelques heures à un jour maximum). Cela limite la période pendant laquelle vous traitez deux fois les événements, et cela simplifie le dépannage en cas de problème.

Retirer la destination instantanée

Une fois que le gestionnaire léger a traité les événements de manière fiable pendant une période confortable, vous pouvez retirer la destination instantanée.

Phase 1 : Désactiver (maintenir le code en place)

  1. Dans le Dashboard Stripe, accédez à Développeurs > Webhooks > Destinations d’événement.
  2. Trouvez la destination de votre événement instantané.
  3. Cliquez sur Désactiver.

Cela empêche Stripe d’envoyer des événements à votre endpoint instantané, mais laisse votre code en place par mesure de sécurité. Surveillez votre flux léger uniquement pour confirmer la stabilité.

Phase 2 : supprimer le snapshot

Si tout reste stable :

  1. Supprimez du Dashboard la destination de l’événement instantané.
  2. Supprimez le code du gestionnaire de webhook instantané de votre application
  3. Supprimez le SNAPSHOT_WEBHOOK_SECRET de votre configuration.
  4. Mettez à jour toute documentation ou livre d’exécution faisant référence à des événements instantanés.

Résolution des problèmes

Le gestionnaire léger ne reçoit aucun événement

Vérifier l’URL de votre endpoint : vérifiez que les endpoints légers correspondent à la bonne URL (par exemple, /webhook/thin, et non /webhook).

Tester en local : utilisez un outil de tunneling tel que ngrok pour exposer votre endpoint local, puis créez une destination d’événement léger pointant vers cette URL.

Échec de la vérification de la signature

Vérifier la clé secrète du webhook : assurez-vous que THIN_WEBHOOK_SECRET contient la clé secrète de signature de votre destination d’événement léger, et non celle de votre destination instantanée.

Inspecter la charge utile brute : la vérification de la signature nécessite le corps brut de la requête. N’analysez pas le JSON avant vérification :

// Correct: use express.raw() app.post('/webhook/thin', express.raw({type: 'application/json'}), handler); // Incorrect: express.json() parses the body app.post('/webhook/thin', express.json(), handler);

Recommandations

Migrer par type d’événement

Nous vous recommandons de migrer événement par événement en vous abonnant à des types d’événements légers spécifiques dans votre nouvelle destination. Par exemple, commencez par v1.customer.created et v1.customer.updated, validez, puis ajoutez d’autres types d’événements.

Double gestionnaire

Nous vous déconseillons d’exécuter deux gestionnaires ou de les laisser s’exécuter indéfiniment. L’exécution de deux gestionnaires augmente la complexité opérationnelle, les coûts (bande passante et traitement) et le risque de comportements divergents. Finalisez la migration en quelques semaines.

Mises à niveau de l’API après migration

Un avantage clé des événements légers est que la charge utile de votre webhook ne change pas. La notification push reste stable, et vous récupérez les détails de la ressource versionnée lorsque vous en avez besoin à l’aide de votre version d’API actuelle.

Voir aussi

  • Aperçu des événements légers
  • Destinations d’événement
  • Bonnes pratiques relatives aux webhooks
  • Gestion des versions de l’API
Cette page vous a-t-elle été utile ?
OuiNon
  • Besoin d'aide ? Contactez le service Support.
  • Consultez notre log des modifications.
  • Des questions ? Contactez l'équipe commerciale.
  • LLM ? Lire llms.txt.
  • Propulsé par Markdoc