# Recevez les événements Stripe dans votre endpoint de webhook Écoutez les événements depuis Stripe sur votre endpoint webhook afin que votre intégration puisse déclencher automatiquement des réactions. ## Start here: Install agent skills Stripe recommends using official skills to integrate with the API using best practices. Follow the instructions below to learn how. **Tip: Use curl instead of Fetch tools.** Skills are detailed 10–20 KB markdown files. Fetch tools summarize them. `curl -sL` guarantees the full content. **Using `npx skills`**: Check if `npx` is installed on the system. If `npx` is available, run `npx skills add https://docs.stripe.com --list` to list available skills, then run `npx skills add https://docs.stripe.com --yes --skill <--skill other-skills>` to install individual skills. **If `npx skills` isn’t available**: You can use curl to fetch the index of available skills, what they do, and their files from `https://docs.stripe.com/.well-known/skills/index.json`. To download a skill and its related files, use curl to download them from `https://docs.stripe.com/.well-known/skills/`. For this article, we recommend using these skills: `stripe-best-practices` > #### Envoyer des événements vers votre compte AWS ou abonnement Azure > > Vous pouvez envoyer des événements directement à [Amazon EventBridge](https://docs.stripe.com/event-destinations/eventbridge.md) ou [Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md) comme destinations d’événement. Créez une destination d’événement pour recevoir des événements à un endpoint de webhook HTTPS. Une fois que vous avez enregistré l’endpoint de webhook, Stripe peut transmettre des données d’événement en temps réel à l’endpoint de webhook de votre application lorsque des [événements](https://docs.stripe.com/event-destinations.md#events-overview) surviennent sur votre compte Stripe. Stripe utilise HTTPS pour envoyer des événements de webhook à votre application en tant que charge utile JSON qui inclut un [objet Event](https://docs.stripe.com/api/events.md). La réception d’événements webhook vous permet de répondre à des événements asynchrones, par exemple lorsque la banque d’un client confirme un paiement, qu’un client conteste un débit ou qu’un paiement récurrent aboutit. ## Démarrer Pour commencer à recevoir des événements de webhook dans votre application : 1. Créez un gestionnaire d’endpoint de webhook pour recevoir des requêtes POST de données d’événement. 1. Testez votre gestionnaire d’endpoint de webhook localement à l’aide de la CLI Stripe. 1. Créez une nouvelle [destination d’événement](https://docs.stripe.com/event-destinations.md) pour votre endpoint de webhook. 1. Sécurisez votre endpoint de webhook. Vous pouvez enregistrer et créer un endpoint pour gérer plusieurs types d’événements en même temps, ou configurer des endpoints individuels pour des événements spécifiques. ## Comportements de type d’événement non pris en charge pour les destinations d’événements d’organisation Stripe envoie la plupart des types d’événements de manière asynchrone, mais attend une réponse pour certains types d’événements. Dans ces cas, Stripe se comporte différemment selon que la destination de l’événement répond ou non. Si votre destination d’événement reçoit des événements [d’organisation](https://docs.stripe.com/get-started/account/orgs.md), ceux qui nécessitent une réponse présentent les limitations suivantes : - Vous ne pouvez pas vous abonner à `issuing_authorization.request` pour les destinations d’organisation. Configurez plutôt un [endpoint de webhook](https://docs.stripe.com/webhooks.md#example-endpoint) sur un compte Stripe au sein de l’organisation pour vous abonner à ce type d’événement. Utilisez `issuing_authorization.request` pour autoriser les demandes d’achat en temps réel. - Les destinations de l’organisation qui reçoivent `checkout_sessions.completed` ne peuvent pas [gérer le comportement de redirection](https://docs.stripe.com/checkout/fulfillment.md#redirect-hosted-checkout) lorsque vous intégrez [Checkout](https://docs.stripe.com/payments/checkout.md) directement dans votre site internet ou redirigez les clients vers une page de paiement hébergée par Stripe. Pour influencer le comportement de redirection de Checkout, traitez ce type d’événement avec un [webhook endpoint](https://docs.stripe.com/webhooks.md#example-endpoint) configuré dans un compte Stripe au sein de l’organisation. - Les destinations d’organisation qui ne répondent pas avec succès à un événement `invoice.created` ne peuvent pas influencer la [finalisation automatique des factures lorsque le recouvrement automatique est activé](https://docs.stripe.com/billing/subscriptions/webhooks.md#understand). Vous devez traiter ce type d’événement via un [endpoint webhook](https://docs.stripe.com/webhooks.md#example-endpoint) configuré dans un compte Stripe au sein de l’organisation afin de déclencher la finalisation automatique des factures. ## Créer un gestionnaire Configurez une fonction endpoint HTTP ou HTTPS pouvant accepter des requêtes de webhook avec une méthode POST. Si votre fonction endpoint est toujours en développement sur votre machine locale, elle peut utiliser HTTP. Une fois publique, elle devra utiliser HTTPS. Configurez votre fonction endpoint pour qu’elle : - Gère les requêtes POST avec une charge utile JSON composée d’un [objet Event](https://docs.stripe.com/api/events/object.md). - Pour les gestionnaires d’événements [d’organisation](https://docs.stripe.com/get-started/account/orgs.md), il inspecte la valeur `context` pour déterminer quel compte d’une organisation a généré l’événement, puis paramètre l’en-tête `Stripe-Context` correspondant à la valeur `context`. - Renvoie rapidement un code d’état réussi (`2xx`) avant le déclenchement de toute logique complexe qui pourrait provoquer une expiration du délai imparti. Par exemple, vous devez renvoyer une réponse `200` avant de mettre à jour la facture d’un client comme étant payée dans votre système comptable. > - Utilisez notre [outil interactif de création d’endpoints webbhook](https://docs.stripe.com/webhooks/quickstart.md) pour créer une fonction d’endpoint webhook dans votre langage de programmation. - Utilisez la documentation de l’API Stripe pour identifier les [objets d’événements légers](https://docs.stripe.com/api/v2/core/events/event-types.md) ou d’[événements instantanés](https://docs.stripe.com/api/events/object.md) que votre gestionnaire de webhooks doit traiter. #### Exemple de endpoint Cet extrait de code est une fonction de webhook configurée pour vérifier les événements reçus d’un compte Stripe, gérer les événements et renvoyer une réponse `200`. Référencez le gestionnaire d’événements [instantanés](https://docs.stripe.com/event-destinations.md#events-overview) lorsque vous utilisez des ressources d’API v1, et référencez le gestionnaire d’événements [légers](https://docs.stripe.com/event-destinations.md#events-overview) lorsque vous utilisez des ressources d’API v2. #### Gestionnaire d'événements instantanés Lorsque vous créez un gestionnaire d’événements instantanés, utilisez la définition d’objet d’API au moment de l’événement pour votre logique en accédant aux champs `data.object` de l’événement. Vous pouvez également récupérer la ressource d’API à partir de l’API Stripe pour accéder à la définition d’objet la plus récente et à jour. #### Ruby ```ruby require 'json' # Replace this endpoint secret with your unique endpoint secret key # If you're testing with the CLI, run 'stripe listen' to find the secret key # If you defined your endpoint using the API or the Dashboard, check your webhook settings for your endpoint secret: https://dashboard.stripe.com/webhooks endpoint_secret = 'whsec_...'; # Using Sinatra post '/webhook' do payload = request.body.read event = nil begin event = Stripe::Event.construct_from( JSON.parse(payload, symbolize_names: true) ) rescue JSON::ParserError => e # Invalid payload status 400 return end # Check that you have configured webhook signing if endpoint_secret # Retrieve the event by verifying the signature using the raw body and the endpoint secret signature = request.env['HTTP_STRIPE_SIGNATURE']; begin event = Stripe::Webhook.construct_event( payload, signature, endpoint_secret ) rescue Stripe::SignatureVerificationError => e puts "⚠️ Webhook signature verification failed. #{e.message}" status 400 end end # Handle the event case event.type when 'payment_intent.succeeded' payment_intent = event.data.object # contains a Stripe::PaymentIntent # Then define and call a method to handle the successful payment intent. # handle_payment_intent_succeeded(payment_intent) when 'payment_method.attached' payment_method = event.data.object # contains a Stripe::PaymentMethod # Then define and call a method to handle the successful attachment of a PaymentMethod. # handle_payment_method_attached(payment_method) # ... handle other event types else puts "Unhandled event type: #{event.type}" end status 200 end ``` #### Gestionnaire d’événements légers (Clover+) Lorsque vous créez un gestionnaire d’événements dynamiques, utilisez la méthode `fetchRelatedObject()` pour récupérer la dernière version de l’objet associé à l’événement. Les événements peuvent contenir des [données supplémentaires](https://docs.stripe.com/event-destinations.md#fetch-data) que vous ne pouvez récupérer que via la méthode d’instance `.fetchEvent()` sur`EventNotification`. La forme exacte de ces données dépend du `type` de l’événement. Les types d’événements doivent être disponibles au moment de la publication pour générer des classes dans cette version du SDK. Pour gérer les événements pour lesquels le SDK n’a pas de classes, utilisez la classe `UnknownEventNotification`. #### Python ```python import os from stripe import StripeClient from stripe.events import UnknownEventNotification from flask import Flask, request, jsonify app = Flask(__name__) api_key = os.environ.get("STRIPE_API_KEY", "") webhook_secret = os.environ.get("WEBHOOK_SECRET", "") client = StripeClient(api_key) @app.route("/webhook", methods=["POST"]) def webhook(): webhook_body = request.data sig_header = request.headers.get("Stripe-Signature") try: event_notif = client.parse_event_notification( webhook_body, sig_header, webhook_secret ) # type checkers will narrow the type based on the `type` property if event_notif.type == "v1.billing.meter.error_report_triggered": # in this block, event_notification is typed as # a V1BillingMeterErrorReportTriggeredEventNotification # there's basic info about the related object in the notification print(f"Meter w/ id {event_notif.related_object.id} had a problem") # or you can fetch the full object form the API for more details meter = event_notif.fetch_related_object() print( f"Meter {meter.display_name} ({meter.id}) had a problem" ) # And you can always fetch the full event: event = event_notif.fetch_event() print(f"More info: {event.data.developer_message_summary}") elif event_notif.type == "v1.billing.meter.no_meter_found": # in this block, event_notification is typed as # a V1BillingMeterNoMeterFoundEventNotification # that class doesn't define `fetch_related_object` because the event # has no related object. # so this line would correctly give a type error: # meter = event_notif.fetch_related_object() # but fetching the event always works: event = event_notif.fetch_event() print( f"Err! No meter found: {event.data.developer_message_summary}" ) # Events that were introduced after this SDK version release are # represented as `UnknownEventNotification`s. # They're valid, the SDK just doesn't have corresponding classes for them. # You must match on the "type" property instead. elif isinstance(event_notif, UnknownEventNotification): # these lines are optional, but will give you more accurate typing in this block from typing import cast event_notif = cast(UnknownEventNotification, event_notif) # continue matching on the type property # from this point on, the `related_object` property _may_ be None # (depending on the event type) if event_notif.type == "some.new.event": # if this event type has a related object, you can fetch it obj = event_notif.fetch_related_object() # otherwise, `obj` will just be `None` print(f"Related object: {obj}") # you can still fetch the full event, but it will be untyped event = event_notif.fetch_event() print(f"New event: {event.data}") # type: ignore return jsonify(success=True), 200 except Exception as e: return jsonify(error=str(e)), 400 ``` #### Gestionnaire d’événements minces (Acacia ou Basilic) Lorsque vous créez un gestionnaire d’événements léger, utilisez la méthode `fetchRelatedObject()` pour récupérer la dernière version de l’objet associé à l’événement. Les événements légers peuvent contenir des [données contextuelles supplémentaires](https://docs.stripe.com/event-destinations.md#fetch-data) que vous ne pouvez récupérer qu’avec l’API. Utilisez l’appel `retrieve()` avec l’ID d’événement léger pour accéder à ces champs de charge utile supplémentaires. #### Python ```python import os from stripe import StripeClient from stripe.events import V1BillingMeterErrorReportTriggeredEvent from flask import Flask, request, jsonify app = Flask(__name__) api_key = os.environ.get('STRIPE_API_KEY') webhook_secret = os.environ.get('WEBHOOK_SECRET') client = StripeClient(api_key) @app.route('/webhook', methods=['POST']) def webhook(): webhook_body = request.data sig_header = request.headers.get('Stripe-Signature') try: thin_event = client.parse_thin_event(webhook_body, sig_header, webhook_secret) # Fetch the event data to understand the failure event = client.v2.core.events.retrieve(thin_event.id) if isinstance(event, V1BillingMeterErrorReportTriggeredEvent): meter = event.fetch_related_object() meter_id = meter.id # Record the failures and alert your team # Add your logic here return jsonify(success=True), 200 except Exception as e: return jsonify(error=str(e)), 400 if __name__ == '__main__': app.run(port=4242) ``` #### Utilisant `context` #### Événements instantanés Cet extrait de code est une fonction webhook configurée pour vérifier les événements reçus, détecter le compte d’origine le cas échéant, gérer l’événement et renvoyer une réponse `200`. #### Ruby ```ruby require 'json' # Using Sinatra post '/webhook' do payload = request.body.read event = nil begin event = Stripe::Event.construct_from( JSON.parse(payload, symbolize_names: true) ) rescue JSON::ParserError => e # Invalid payload status 400 return end # Extract the context context = event.context # Define your API key variables (ideally loaded securely) ACCOUNT_123_API_KEY = "sk_test_123" ACCOUNT_456_API_KEY = "sk_test_456" account_api_keys = { "account_123" => ACCOUNT_123_API_KEY, "account_456" => ACCOUNT_456_API_KEY } api_key = account_api_keys[context] if api_key.nil? puts "No API key found for context: #{context}" status 400 return end # Handle the event case event.type when 'customer.created' customer = event.data.object begin latest_customer = Stripe::Customer.retrieve( customer.id, { api_key: api_key } ) handle_customer_created(latest_customer, context) rescue => e puts "Error retrieving customer: #{e.message}" status 500 return end when 'payment_method.attached' payment_method = event.data.object begin latest_payment_method = Stripe::PaymentMethod.retrieve( payment_method.id, { api_key: api_key } ) handle_payment_method_attached(latest_payment_method, context) rescue => e puts "Error retrieving payment method: #{e.message}" status 500 return end else puts "Unhandled event type: #{event.type}" end status 200 end ``` #### Gestionnaire d’événements légers (Clover+) Utilisez la propriété `context` de l’`EventNotification` pour identifier le compte pour les événements au sein de votre [organisation](https://docs.stripe.com/get-started/account/orgs.md). Vous devez définir manuellement l[’en-tête Stripe-Context](https://docs.stripe.com/context.md) pour tous les appels à l’API, sauf pour `.fetchRelatedObject()` et `.fetchEvent()`, qui le font automatiquement pour vous. #### Python ```python org_api_key = os.environ.get("STRIPE_API_KEY") webhook_secret = os.environ.get("WEBHOOK_SECRET") client = StripeClient(org_api_key) # inside your webhook handler event_notification = client.parse_event_notification(payload, sig_header, webhook_secret) # uses `context` automatically event_notification.fetch_event() # pass context manually for other API requests client.v1.invoices.list(stripe_context=event_notification.context) ``` #### Gestionnaire d’événements minces (Acacia ou Basilic) Cet extrait de code est une fonction de webhook configurée pour recevoir des événements légers à l’échelle d’une organisation, vérifier la signature, déterminer le compte d’origine avec le champ `context`, et utiliser la clé API de ce compte pour les appels API ultérieurs. #### Python ```python import os from flask import Flask, request, jsonify from stripe import StripeClient from stripe.events import V1BillingMeterErrorReportTriggeredEvent app = Flask(__name__) org_api_key = os.environ.get("STRIPE_API_KEY") webhook_secret = os.environ.get("WEBHOOK_SECRET") client = StripeClient(org_api_key) account_api_keys = { "account_123": os.environ.get("ACCOUNT_123_API_KEY"), "account_456": os.environ.get("ACCOUNT_456_API_KEY"), } @app.route("/webhook", methods=["POST"]) def webhook(): payload = request.data sig_header = request.headers.get("Stripe-Signature") try: thin_event = client.parse_thin_event(payload, sig_header, webhook_secret) # Retrieve the event using the org client to inspect context event = client.v2.core.events.retrieve(thin_event.id) context = getattr(event, "context", None) if not context: return jsonify(error="Missing context"), 400 account_key = account_api_keys.get(context) if not account_key: return jsonify(error="Unknown context"), 400 account_client = StripeClient(account_key) full_event = account_client.v2.core.events.retrieve(thin_event.id) if isinstance(full_event, V1BillingMeterErrorReportTriggeredEvent): meter = full_event.fetch_related_object() meter_id = meter.id # Record the failures and alert your team # Add your logic here return jsonify(success=True), 200 except Exception as e: return jsonify(error=str(e)), 400 if __name__ == "__main__": app.run(port=4242) ``` ## Tester votre gestionnaire Avant de mettre en production votre fonction endpoint de webhook, nous vous recommandons de tester l’intégration de votre application. Pour ce faire, configurez un écouteur local pour envoyer des événements à votre ordinateur local, puis envoyez des événements de test. Vous devez utiliser la [CLI](https://docs.stripe.com/stripe-cli.md) pour effectuer le test. #### Transmettre des événements à un endpoint local Pour transférer des événements vers votre endpoint local, exécutez la commande suivante via l’[interface de ligne de commande](https://docs.stripe.com/stripe-cli.md) pour configurer un écouteur local. L’indicateur `--forward-to` envoie tous les [événements Stripe](https://docs.stripe.com/cli/trigger#trigger-event) dans un [environnement de test](https://docs.stripe.com/sandboxes.md) à votre endpoint de webhook local. Utilisez les commandes d’interface de ligne de commande appropriées ci-dessous, selon que vous utilisez des événements [légers](https://docs.stripe.com/event-destinations.md#events-overview) ou des événements instantanés. #### Transférer des événements instantanés Utilisez la commande suivante pour transférer des [événements instantanés](https://docs.stripe.com/event-destinations.md#events-overview) vers votre écouteur local. ```bash stripe listen --forward-to localhost:4242/webhook ``` #### Transférer des événements légers Utilisez la commande suivante pour transférer des [événements légers](https://docs.stripe.com/event-destinations.md#events-overview) vers votre écouteur local. ```bash $ stripe listen --forward-thin-to localhost:4242/webhook --thin-events "*" ``` > Vous pouvez également exécuter `stripe listen` pour voir les événements dans [Stripe Shell](https://docs.stripe.com/workbench/shell.md), bien que vous ne pourrez pas transférer les événements du shell vers votre endpoint local. Voici quelques exemples de configurations utiles pour vous aider à effectuer vos tests avec votre écouteur local : - Pour désactiver la vérification des certificats HTTPS, utilisez le flag facultatif `--skip-verify`. - Pour ne transférer que des événements spécifiques, utilisez le flag facultatif `--events` et transmettez une liste d’événements séparés par des virgules. #### Transférer des événements instantanés cibles Utilisez la commande suivante pour transférer des événements instantanés cibles vers votre écouteur local. ```bash stripe listen --events payment_intent.created,customer.created,payment_intent.succeeded,checkout.session.completed,payment_intent.payment_failed \ --forward-to localhost:4242/webhook ``` #### Transférer des événements légers cibles Utilisez la commande suivante pour transférer les événements légers cibles vers votre écouteur local. ```bash stripe listen --thin-events v1.billing.meter.error_report_triggered,v1.billing.meter.no_meter_found \ --forward-thin-to localhost:4242/webhook ``` - Pour transférer des événements vers votre endpoint de webhook local à partir du endpoint de webhook public que vous avez déjà enregistré sur Stripe, utilisez le flag facultatif `--load-from-webhooks-api`. Il charge votre endpoint enregistré, analyse le chemin d’accès et ses événements enregistrés, puis ajoute le chemin d’accès à votre endpoint de webhook local à `--forward-to path`. #### Transférer des événements instantanés à partir d'un endpoint de webhook public Utilisez la commande suivante pour transférer les événements instantanés d’un endpoint de webhook public vers votre écouteur local. ```bash stripe listen --load-from-webhooks-api --forward-to localhost:4242/webhook ``` #### Transférer les événements légers à partir d'un endpoint de webhook public Utilisez la commande suivante pour transférer les événements légers d’un endpoint de webhook public vers votre écouteur local. ```bash stripe listen --load-from-webhooks-api --forward-thin-to localhost:4242/webhook ``` - Pour vérifier les signatures de webhook, utilisez le paramètre `{{WEBHOOK_SIGNING_SECRET}}` dans la sortie initiale de la commande listen. ```output Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit) ``` #### Déclencher des événements test Pour envoyer des événements de test, déclenchez un type d’événement auquel votre destination d’événement est abonnée en créant manuellement un objet dans le Dashboard Stripe. Découvrez comment déclencher des événements avec [Stripe pour VS Code](https://docs.stripe.com/stripe-vscode.md). #### Déclencher un événement instantané Vous pouvez utiliser la commande suivante dans [Stripe Shell](https://docs.stripe.com/workbench/shell.md) ou [Stripe CLI](https://docs.stripe.com/stripe-cli.md). Cet exemple déclenche un événement `payment_intent.succeeded` : ```bash stripe trigger payment_intent.succeeded Running fixture for: payment_intent Trigger succeeded! Check dashboard for event details. ``` #### Déclencher un événement léger Vous pouvez utiliser la commande suivante dans le [Stripe CLI](https://docs.stripe.com/stripe-cli.md). Cet exemple déclenche l’événement `v1.billing.meter.error_report_triggered` : ```bash stripe trigger v1.billing.meter.error_report_triggered Setting up fixture for: list_billing_meters Running fixture for: list_billing_meters Setting up fixture for: billing_meter Running fixture for: billing_meter Setting up fixture for: list_billing_meters_after_creation Running fixture for: list_billing_meters_after_creation Setting up fixture for: billing_meter_event_session Running fixture for: billing_meter_event_session Setting up fixture for: create_billing_meter_event_stream Running fixture for: create_billing_meter_event_stream Trigger succeeded! Check dashboard for event details. ``` ## Enregistrer votre endpoint Après avoir testé la fonction de votre endpoint de webhook, utilisez l’[API](https://docs.stripe.com/api/v2/event-destinations.md) ou l’onglet **Webhooks** de Workbench pour enregistrer l’URL accessible de votre endpoint de webhook afin que Stripe sache où envoyer les événements. Vous pouvez enregistrer jusqu’à 16 endpoints de webhook sur Stripe. Les endpoints de webhook enregistrés doivent être des URL **HTTPS** accessibles au public. #### Format d’URL de webhook L’endpoint de webhook doit être enregistré avec le format d’URL suivant : ``` https:/// ``` Par exemple, si votre domaine est `https://mycompanysite.com` et que le chemin vers votre endpoint de webhook est `@app.route('/stripe_webhooks', methods=['POST'])`, spécifiez `https://mycompanysite.com/stripe_webhooks` comme **URL d’endpoint**. #### Créer une destination d’événement pour votre endpoint de webhook Créez une destination d’événement à l’aide de Workbench dans le Dashboard ou par programmation avec l’[API](https://docs.stripe.com/api/v2/event-destinations.md). Vous pouvez enregistrer jusqu’à 16 destinations d’événements sur chaque compte Stripe. #### Dashboard Pour créer un nouvel endpoint de webhook dans le Dashboard : 1. Ouvrez l’onglet [Webhooks](https://dashboard.stripe.com/webhooks) dans Workbench. 1. Cliquez sur **Créer une destination d’événement**. 1. Sélectionnez l’emplacement d’où vous souhaitez recevoir les événements. Stripe prend en charge deux types de configurations : **Votre compte** et [Comptes connectés](https://docs.stripe.com/connect.md). Sélectionnez **Compte** pour écouter les événements de votre propre compte. Si vous avez créé une [application Connect](https://docs.stripe.com/connect.md) et que vous souhaitez écouter les événements de vos comptes connectés, sélectionnez **Comptes connectés**. > #### Écouter les événements à partir d'un endpoint de webhook d'organisation > > Si vous créez un endpoint de webhook dans un [compte d’organisation](https://docs.stripe.com/get-started/account/orgs.md), sélectionnez **Comptes** pour écouter les événements des comptes de votre organisation. Si des [plateformes Connect](https://docs.stripe.com/connect.md) figurent parmi les membres de vos organisations et que vous souhaitez écouter les événements de tous les comptes connectés des plateformes, sélectionnez **Comptes connectés**. 1. Sélectionnez la version de l’API pour l’[objet Events](https://docs.stripe.com/api/events.md) que vous souhaitez utiliser. 1. Sélectionnez les [types d’événement](https://docs.stripe.com/api/events/types.md) que vous souhaitez envoyer à un endpoint de webhook. 1. Sélectionnez **Continuer**, puis **endpoint de webhook** comme type de destination. 1. Cliquez sur **Continuer**, puis renseignez l’**URL de l’endpoint** ainsi qu’une description facultative du webhook. #### API Vous pouvez créer une destination d’événement qui vous informe lorsqu’une erreur de validation [facturation à l’usage](https://docs.stripe.com/billing/subscriptions/usage-based.md) est déclenchée à l’aide de l’[API](https://docs.stripe.com/api/v2/event-destinations.md). Si vous avez créé un [formulaire d’inscription Connect](https://docs.stripe.com/connect.md) et que vous souhaitez écouter vos comptes connectés, utilisez le paramètre [events_from](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from) et définissez sa valeur sur `@accounts`. Pour les destinations d’événement [Organisation](https://docs.stripe.com/get-started/account/orgs.md), utilisez `@organisation_members` pour les événements des comptes de votre organisation, ou `@organisation_members/@accounts` pour les événements des comptes connectés de votre organisation. ```curl curl -X POST https://api.stripe.com/v2/core/event_destinations \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-03-25.preview" \ --json '{ "name": "My event destination", "description": "This is my event destination, I like it a lot", "type": "webhook_endpoint", "event_payload": "thin", "enabled_events": [ "v1.billing.meter.error_report_triggered" ], "webhook_endpoint": { "url": "https://example.com/my/webhook/endpoint" } }' ``` > [Workbench](https://docs.stripe.com/workbench.md) remplace le [Dashboard des développeurs](https://docs.stripe.com/development/dashboard.md) existant. Si vous utilisez encore le Dashboard des développeurs, découvrez comment [créer un nouvel endpoint de webhook](https://docs.stripe.com/development/dashboard/webhooks.md). ## Sécuriser votre endpoint Après avoir confirmé que votre endpoint fonctionne comme prévu, sécurisez le en implémentant les [bonnes pratiques en matière de webhook](https://docs.stripe.com/webhooks.md#best-practices). Sécurisez votre intégration en vous assurant que votre gestionnaire vérifie que toutes les requêtes de webhook proviennent bien de Stripe. Vous pouvez vérifier les signatures des webhooks à l’aide de nos bibliothèques officielles ou procéder à une vérification manuelle. #### Vérifier à l'aide de bibliothèques officielles (recommandé) ### Vérifier les signatures de webhook à l’aide de bibliothèques officielles Nous vous recommandons d’utiliser nos bibliothèques officielles pour vérifier les signatures. Pour effectuer la vérification, vous devez fournir la charge utile de l’événement, l’en-tête `Stripe-Signature` et la clé secrète de l’endpoint. Une erreur s’affiche en cas d’échec de la vérification. Si vous obtenez une erreur de vérification de la signature, consultez notre guide de [résolution des problèmes](https://docs.stripe.com/webhooks/signature.md). > Stripe a besoin du contenu brut de la requête pour procéder à la vérification de la signature. Si vous utilisez un framework, assurez-vous qu’il ne manipule pas le contenu brut, auquel cas cela entraînerait automatiquement l’échec de la vérification. #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. Stripe.api_key = '<>' require 'stripe' require 'sinatra' # If you are testing your webhook locally with the Stripe CLI you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboardendpoint_secret = 'whsec_...' # Using the Sinatra framework set :port, 4242 post '/my/webhook/url' do payload = request.body.readsig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil beginevent = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload puts "Error parsing payload: #{e.message}" status 400 return rescue Stripe::SignatureVerificationError => e# Invalid signature puts "Error verifying webhook signature: #{e.message}" status 400 return end # Handle the event case event.type when 'payment_intent.succeeded' payment_intent = event.data.object # contains a Stripe::PaymentIntent puts 'PaymentIntent was successful!' when 'payment_method.attached' payment_method = event.data.object # contains a Stripe::PaymentMethod puts 'PaymentMethod was attached to a Customer!' # ... handle other event types else puts "Unhandled event type: #{event.type}" end status 200 end ``` #### Vérifier manuellement ### Vérifier manuellement les signatures de webhook Bien que nous vous recommandions d’utiliser nos bibliothèques officielles pour vérifier les signatures d’événements webhook, cette section vous explique comment créer une solution personnalisée. L’en-tête `Stripe-Signature` inclus dans chaque événement signé contient un horodatage et une ou plusieurs signatures que vous devez vérifier. L’horodatage est précédé d’un préfixe `t=` et chaque signature est précédée d’un préfixe *schéma*. Les schémas commencent par `v`, suivi d’un nombre entier. À l’heure actuelle, le seul schéma de signature valide en mode production est `v1`. Afin de faciliter les tests, Stripe envoie une signature supplémentaire avec un faux schéma `v0` pour les événements de test. ``` Stripe-Signature: t=1492774577, v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd, v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39 ``` > Nous avons ajouté des nouvelles lignes pour plus de clarté, mais un véritable en-tête `Stripe-Signature` tient sur une seule ligne. Stripe génère des signatures à l’aide d’un code d’authentification de message basé sur le hachage ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) avec [SHA-256](https://en.wikipedia.org/wiki/SHA-2). Pour éviter les [attaques par repli](https://en.wikipedia.org/wiki/Downgrade_attack), ignorez tous les schémas qui ne sont pas `v1`. Vous pouvez avoir plusieurs signatures avec la même paire schéma-clé secrète lorsque vous [invalidez la clé secrète d’un endpoint](https://docs.stripe.com/webhooks.md#roll-endpoint-secrets) et que vous gardez la clé secrète précédente active jusqu’à 24 heures. Pendant cette période, votre endpoint possède plusieurs clés secrètes actives et Stripe génère une signature pour chacune d’entre elles. Pour créer une solution manuelle de vérification des signatures, vous devez suivre les étapes suivantes : #### Étape 1 : Extraire l’horodatage et les signatures de l’en-tête Fractionnez l’en-tête en utilisant le caractère `,` comme séparateur pour obtenir une liste d’éléments. Fractionnez ensuite chaque élément en utilisant le caractère `=` comme séparateur pour obtenir une paire préfixe-valeur. La valeur du préfixe `t` correspond à l’horodatage, et `v1` correspond à la signature (ou aux signatures). Vous pouvez ignorer tous les autres éléments. #### Étape 2 : Préparer la chaîne `signed_payload` La chaîne `signed_payload` est créée par concaténation des éléments suivants : - L’horodatage (sous forme de chaîne) - Le caractère `.` - La charge utile JSON réelle (c’est-à-dire le contenu de la requête) #### Étape 3 : Déterminer la signature attendue Calculez un HMAC avec la fonction de hachage SHA256. Utilisez la clé secrète de signature du endpoint comme clé et la chaîne `signed_payload` comme message. #### Étape 4 : Comparer les signatures Comparez la signature (ou les signatures) dans l’en-tête à la signature attendue. Pour une correspondance d’égalité, calculez la différence entre l’horodatage actuel et l’horodatage reçu, puis déterminez si la différence se situe dans les limites de votre tolérance. Pour vous protéger des attaques temporelles, utilisez une comparaison de chaîne de temps constante pour comparer la signature attendue à chacune des signatures reçues. ## Déboguer des intégrations de webhooks Plusieurs types de problèmes peuvent survenir lors de la remise d’événements à votre endpoint de webhook : - Il est possible que Stripe ne parvienne pas à remettre un événement à votre endpoint de webhook. - Votre endpoint de webhook comporte peut-être une erreur SSL. - Votre connectivité réseau est intermittente. - Votre endpoint de webhook ne reçoit pas les événements attendus. ### Afficher les événements remis Pour consulter les livraisons d’événements, sélectionnez le point de terminaison du webhook dans **Webhooks**, puis ouvrez l’onglet **Événements**. L’onglet **Événement** affiche la liste des événements ainsi que leur statut (`Delivered`, `Pending`, ou `Failed`). Cliquez sur un événement pour voir les métadonnées, notamment le code de statut HTTP de la tentative de livraison et l’heure des prochaines livraisons en attente. Vous pouvez également utiliser l’[interface de ligne de commande Stripe](https://docs.stripe.com/stripe-cli.md) pour [écouter des événements](https://docs.stripe.com/webhooks.md#test-webhook) directement dans votre terminal. ### Corriger les codes d’état HTTP Quand un événement affiche un code d’état de `200`, cela indique qu’il a bien été remis au endpoint de webhook. Vous pouvez aussi recevoir un code d’état autre que `200`. La liste ci-après détaille les codes d’état fréquents pour le protocole HTTPS, ainsi que les solutions préconisées. | État des webhooks en attente | Description | Rectifier | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | | ERR (connexion impossible) | Nous ne parvenons pas à établir une connexion avec le serveur de destination. | Assurez-vous que votre domaine d’hébergement est accessible publiquement sur internet. | | (`302`) ERR (ou autre état `3xx`) | Le serveur de destination a tenté de rediriger la requête vers un autre emplacement. Nous considérons les réponses de redirection aux requêtes de webhook comme des échecs. | Définissez la destination de votre endpoint de webhook vers l’URL déterminée par la redirection. | | ERR (`400`) (ou autre état `4xx`) | Le serveur de destination ne parvient pas à traiter ou rejette la requête. Cela peut se produire si le serveur détecte une erreur (`400`), si l’URL de destination présente des restrictions d’accès (`401`, `403`) ou si l’URL de destination n’existe pas (`404`). | - Assurez-vous que votre endpoint est accessible publiquement sur Internet. - Assurez-vous que votre endpoint accepte une méthode HTTP POST. | | (`500`) ERR (ou autre état `5xx`) | Le serveur de destination a rencontré une erreur lors du traitement de la requête. | Vérifiez les logs de votre application pour comprendre pourquoi vous recevez une erreur `500`. | | ERR (erreur TLS) | Nous ne sommes pas parvenus à établir une connexion sécurisée avec le serveur de destination. Ces erreurs sont généralement causées par un problème avec le certificat SSL/TLS ou un certificat intermédiaire dans la chaîne de certificats du serveur de destination. Stripe exige *TLS* (TLS refers to the process of securely transmitting data between the client—the app or browser that your customer is using—and your server. This was originally performed using the SSL (Secure Sockets Layer) protocol) version `v1.2` ou supérieure. | Pour identifier d’éventuels problèmes pouvant engendrer cette erreur, effectuez un [test du serveur SSL](https://www.ssllabs.com/ssltest/). | | ERR (expiré) | Le serveur de destination a mis trop de temps à répondre à la requête de webhook. | Veillez à reporter la logique complexe et à renvoyer immédiatement une réponse positive dans votre code de gestion des webhooks. | ## Comportements de remise d’événements Cette section vous aide à comprendre les différents comportements auxquels vous pouvez vous attendre concernant la manière dont Stripe envoie des événements à votre endpoint de webhook. ### Retentatives automatiques Stripe tente de livrer des événements à votre destination pendant un maximum de trois jours avec un recul exponentiel en mode production. Le cas échéant, vous pouvez voir quand la prochaine tentative aura lieu dans l’onglet **Événements envoyés** de votre destination d’événement. Les livraisons d’événements créées dans un environnement de test sont relancées trois fois en l’espace de quelques heures. Si votre destination a été désactivée ou supprimée lorsque nous effectuons une nouvelle tentative de remise, nous annulons toute relance ultérieure de cet événement. Toutefois, si vous désactivez puis réactivez la destination de l’événement avant que nous ne puissions effectuer la relance, les tentatives ultérieures seront toujours visibles. ### Retentatives manuelles Il existe deux façons de relancer manuellement des événements : - Dans le Dashboard Stripe, cliquez sur **Renvoyer** lorsque vous consultez un événement spécifique. Cette relance fonctionne jusqu’à 15 jours après la création de l’événement. - À l’aide de la [CLI Stripe](https://docs.stripe.com/cli/events/resend), exécutez la commande `stripe events resend --webhook-endpoint=`. Cette relance fonctionne jusqu’à 30 jours après la création de l’événement. Le renvoi manuel d’un événement dont la livraison à un endpoint de webhook a précédemment échoué n’annule pas le [comportement de nouvelle tentative automatique](https://docs.stripe.com/webhooks.md#automatic-retries) de Stripe, même si cela occasionne un code d’état `2xx`.Découvrez comment [traiter les événements webhook dont la livraison a échoué](https://docs.stripe.com/webhooks/process-undelivered-events.md) pour éviter toute nouvelle tentative. ### Ordre des événements Stripe ne garantit pas la remise des événements dans l’ordre dans lequel ils ont été générés. Par exemple, la création d’un abonnement peut générer les événements suivants : - `customer.subscription.created` - `invoice.created` - `invoice.paid` - `charge.created` (si un paiement a lieu) Assurez-vous que la destination de votre événement ne dépend pas de la réception des événements dans un ordre spécifique. Soyez prêt à gérer correctement leur livraison. Vous pouvez également utiliser l’API pour récupérer les éventuels objets manquants. Par exemple, vous pouvez récupérer les objets invoice, charge et subscription avec les informations de `invoice.paid` si vous recevez cet événement en premier. ### Gestion des versions de l’API Lorsque l’événement survient, la version de l’API dans les paramètres de votre compte détermine la version de l’API, et par extension la structure d’un [événement](https://docs.stripe.com/api/events.md), envoyées à votre destination. Par exemple, si votre compte utilise une ancienne version d’API, comme 2015-02-16, et que vous modifiez la version de l’API pour une requête spécifique avec [le contrôle de version](https://docs.stripe.com/api.md#versioning), l’objet [Event](https://docs.stripe.com/api/events.md) généré et envoyé à votre destination est toujours basé sur la version de l’API du 16/02/2015. Vous ne pouvez pas modifier les objets [Event](https://docs.stripe.com/api/events.md) une fois qu’ils ont été créés. Par exemple, si vous mettez à jour un paiement, l’événement de paiement d’origine reste inchangé. Par conséquent, les mises à jour apportées par la suite à la version de l’API de votre compte ne modifient pas de manière rétroactive les objets [Event](https://docs.stripe.com/api/events.md) existants. La récupération d’un ancien [Event](https://docs.stripe.com/api/events.md) par l’appel à `/v1/events` à l’aide d’une version récente de l’API n’a pas non plus de conséquence sur la structure de l’événement reçu. Vous pouvez définir les destinations des événements de test sur votre version d’API par défaut ou sur la version la plus récente de l’API. L’objet [Event](https://docs.stripe.com/api/events.md) envoyé à la destination est structuré en fonction de la version spécifiée pour la destination de l’événement. ## Bonnes pratiques pour l’utilisation des webhooks Passez en revue ces bonnes pratiques pour vous assurer que vos webhooks restent sécurisés et fonctionnent bien avec votre intégration. ### Gérer les événements en double Les endpoints de webhook peuvent parfois recevoir plusieurs fois le même événement. Vous pouvez vous prémunir contre ce phénomène en enregistrant l’[ID des événements](https://docs.stripe.com/api/events/object.md#event_object-id) que vous avez traités, puis ignorer les événements déjà enregistrés. Dans certains cas, deux objets Event distincts sont générés et envoyés. Pour identifier ces doublons, utilisez l’ID de l’objet dans `data.object` ainsi que le type d’événement (`event.type`). ### Écouter uniquement les types d’événements requis par votre intégration Configurez vos endpoints de webhook de sorte à ne recevoir que les types d’événements requis par votre intégration. L’écoute d’événements supplémentaires (ou de tous les événements) alourdit inutilement la charge de votre serveur, c’est pourquoi nous vous déconseillons cette pratique. Vous pouvez [modifier les événements](https://docs.stripe.com/api/webhook_endpoints/update.md#update_webhook_endpoint-enabled_events) qu’un endpoint de webhook reçoit dans le Dashboard ou à l’aide de l’API. ### Gérer les événements de manière asynchrone Configurez votre gestionnaire de façon à ce qu’il traite les événements entrants avec une file d’attente asynchrone. Vous pouvez rencontrer des problèmes d’évolutivité si vous choisissez de traiter les événements de manière synchrone. Tout pic important d’envoi de webhooks (par exemple, au début du mois, lorsque tous les abonnements sont renouvelés) peut submerger vos hôtes d’endpoint. Les files d’attente asynchrones vous permettent de traiter les événements simultanés à une vitesse que votre système peut prendre en charge. ### Exempter la route des webhooks de la protection CSRF Si vous utilisez Rails, Django ou une autre infrastructure Web, il est possible que votre site vérifie automatiquement que chaque requête POST contient un *token CSRF*. Il s’agit d’une fonctionnalité de sécurité importante qui vous protège, vous et vos utilisateurs, contre les tentatives de [falsification de requêtes intersites](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_\(CSRF\)). Cependant, cette mesure de sécurité peut également empêcher votre site de traiter des événements légitimes. Dans ce cas, vous devrez peut-être retirer la protection CSRF du chemin des webhooks. #### Rails ```ruby class StripeController < ApplicationController # If your controller accepts requests other than Stripe webhooks, # you'll probably want to use `protect_from_forgery` to add CSRF # protection for your application. But don't forget to exempt # your webhook route! protect_from_forgery except: :webhook def webhook # Process webhook data in `params` end end ``` ### Recevoir des événements sur un serveur HTTPS Si vous utilisez une URL HTTPS pour votre endpoint de webhook (obligatoire en mode production), Stripe vérifie que la connexion à votre serveur est sécurisée avant d’envoyer les données de votre webhook. Pour que ce processus fonctionne, votre serveur doit être configuré de sorte à prendre en charge le protocole HTTPS et disposer d’un certificat valide. Les webhooks de Stripe prennent uniquement en charge les versions de *TLS* (TLS refers to the process of securely transmitting data between the client—the app or browser that your customer is using—and your server. This was originally performed using the SSL (Secure Sockets Layer) protocol) v1.2 et v1.3. ### Invalider régulièrement les clés secrètes de signature des endpoints La clé secrète utilisée pour vérifier que les événements proviennent de Stripe peut être modifiée dans la section **Webhooks** de Workbench. Pour assurer leur sécurité, nous vous recommandons d’invalider (changer) les clés secrètes à intervalles réguliers ou lorsque vous soupçonnez que l’une d’entre elles est compromise. Pour invalider une clé secrète : 1. Dans l’onglet **Webhooks** de Workbench, cliquez sur chaque endpoint dont vous souhaitez invalider la clé secrète. 1. Accédez au menu déroulant (⋯) et cliquez sur **Invalider la clé secrète**. Vous pouvez choisir de faire expirer immédiatement la clé secrète actuelle ou de retarder son expiration de 24 heures (maximum) pour vous laisser le temps de mettre à jour le code de vérification sur votre serveur. Dans l’intervalle, plusieurs clés secrètes seront actives pour le endpoint concerné. Stripe génère une signature par clé secrète jusqu’à son expiration. ### Vérifiez que les événements sont envoyés depuis Stripe Sans vérification, un attaquant pourrait envoyer de faux événements webhook à votre endpoint afin de déclencher des actions telles que l’exécution de commandes, l’octroi d’un accès à un compte ou la modification d’enregistrements. Vérifiez toujours que les événements webhook proviennent bien de Stripe avant d’agir. Utilisez les deux protections suivantes : - **Autorisation par liste d’IP** : Stripe envoie les événements webhook depuis une liste définie d’[adresses IP](https://docs.stripe.com/ips.md). Configurez votre serveur ou votre pare-feu pour n’accepter les requêtes webhook que depuis ces adresses. - **Vérification de signature** : Stripe signe chaque événement webhook en incluant une signature dans l’en-tête `Stripe-Signature`. Vérifiez cette signature à l’aide de nos [bibliothèques officielles](https://docs.stripe.com/webhooks.md#verify-official-libraries) ou [manuellement](https://docs.stripe.com/webhooks.md#verify-manually) afin de confirmer que l’événement n’a pas été envoyé ou modifié par un tiers. La section suivante décrit comment vérifier les signatures de webhook : 1. Récupérez la clé secrète de votre endpoint. 1. Vérifiez la signature. #### Récupérer la clé secrète de votre endpoint Utilisez Workbench et accédez à l’onglet **Webhooks** pour afficher tous vos endpoints. Sélectionnez celui dont vous souhaitez obtenir la clé secrète, puis cliquez sur **Cliquer pour révéler**. Stripe génère une clé secrète unique pour chaque endpoint. Si vous utilisez le même endpoint pour les [clés API de test et de production](https://docs.stripe.com/keys.md#test-live-modes), la clé secrète est différente pour chacune d’elles. En outre, si vous utilisez plusieurs endpoints, vous devez obtenir une clé secrète pour chacun de ceux dont vous souhaitez vérifier les signatures. Une fois cette configuration terminée, Stripe commence à signer chaque webhook qu’il envoie à l’endpoint. ### Prévention des attaques par rejeu Une [attaque par rejeu](https://en.wikipedia.org/wiki/Replay_attack) se produit lorsqu’un attaquant intercepte une charge utile valide et sa signature, puis les retransmet. Pour limiter ce type d’attaques, Stripe inclut un horodatage dans l’en-tête `Stripe-Signature`. Comme cet horodatage fait partie de la charge utile signée, il est également vérifié par la signature. Un attaquant ne peut donc pas modifier l’horodatage sans invalider la signature. Si la signature est valide mais que l’horodatage est trop ancien, votre application peut refuser la charge utile. Nos bibliothèques ont une tolérance par défaut de 5 minutes entre l’horodatage et l’heure actuelle. Vous pouvez modifier cette tolérance en fournissant un paramètre supplémentaire lors de la vérification des signatures. Utilisez le protocole Network Time Protocol ([NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol)) pour vous assurer que l’heure indiquée par l’horloge de votre serveur est correcte et synchronisée avec l’heure des serveurs de Stripe. > N’utilisez pas une valeur de tolérance de `0`, sous peine de désactiver entièrement le contrôle de récence. Stripe génère l’horodatage et la signature chaque fois que nous envoyons un événement à votre endpoint. Si Stripe tente à nouveau de transmettre un événement (par exemple, si votre endpoint a précédemment répondu avec un code d’état autre que `2xx`), nous générons une nouvelle signature et un nouvel horodatage pour la nouvelle tentative de remise. ### Renvoyer rapidement une réponse 2xx Votre [endpoint](https://docs.stripe.com/webhooks.md#example-endpoint) doit renvoyer rapidement un code d’état réussi (`2xx`) avant le déclenchement de toute logique complexe qui pourrait provoquer une expiration du délai imparti. Par exemple, vous devez renvoyer une réponse `200` avant de mettre à jour la facture d’un client comme payée dans votre système comptable. ## See also - [Envoyer des événements à Amazon EventBridge](https://docs.stripe.com/event-destinations/eventbridge.md) - [Envoyer des événements vers Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md) - [Liste des types d’événements légers](https://docs.stripe.com/api/v2/core/events/event-types.md) - [Liste des types d’événements instantanés](https://docs.stripe.com/api/events/.md) - [Outil interactif pour la création d’endpoints de webhook](https://docs.stripe.com/webhooks/quickstart.md)