# Registrieren Sie Stripe-Ereignisse in Ihrem Webhook-Endpoint

Überwachen Sie Ereignisse von Stripe auf Ihrem Webhook-Endpoint, damit Ihre Integration automatisch Reaktionen auslösen kann.

Sie können einen HTTPS-Webhook-Endpoint zum Empfangen von Ereignissen erstellen. Nachdem Sie einen Webhook-Endpoint registriert haben, überträgt Stripe Echtzeitdaten an diesen Endpoint, wenn [Ereignisse](https://docs.stripe.com/event-destinations.md#events-overview) in Ihrem Stripe-Konto eintreten. Stripe verwendet HTTPS, um Webhook-Ereignisse als JSON-Nutzlast mit Ereignisinformationen an Ihre App zu senden.

Der Empfang von Webhook-Ereignissen hilft Ihnen, auf asynchrone Ereignisse zu reagieren, z.B. wenn die Bank eines Kunden/einer Kundin eine Zahlung bestätigt, ein Kunde/eine Kundin eine Zahlungsanfechtung einleitet oder eine wiederkehrende Zahlung erfolgreich ist.

Sie können auch Stripe-Ereignisse in Ihrer AWS- oder Azure-Infrastruktur nutzen, indem Sie Ereignisse direkt an [Amazon EventBridge](https://docs.stripe.com/event-destinations/eventbridge.md) oder [Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md) senden.

Führen Sie die folgenden Schritte aus, um mit dem Empfangen von Webhook-Ereignissen in Ihrer App zu beginnen. Sie können einen Endpoint registrieren und erstellen, um mehrere verschiedene Ereignistypen gleichzeitig zu verarbeiten, oder einzelne Endpoints für bestimmte Ereignisse einrichten.

## Richten Sie Ihren Endpoint ein

Verwenden Sie die Registerkarte [API](https://docs.stripe.com/api/v2/event-destinations.md) oder [Webhooks](https://dashboard.stripe.com/webhooks) in Workbench, um die zugängliche URL Ihres Webhook-Endpoints zu registrieren. So weiß Stripe, wohin die Ereignisse zugestellt werden sollen. Sie können bis zu 16 Webhook-Endpoints bei Stripe registrieren. Registrierte Webhook-Endpoints müssen öffentlich zugängliche HTTPS-URLs sein.

- Wenn Sie über einen Localhost-Server, aber nicht über eine öffentlich zugängliche HTTPS-URL verfügen, können Sie ein Tunneling-Tool wie [ngrok](https://ngrok.com/) nutzen, um eine temporäre, öffentlich zugängliche HTTPS-URL zu Testzwecken zu generieren.
- Alternativ können Sie vor der Registrierung einer öffentlich zugänglichen HTTPS-URL einen [lokalen Test mit der Stripe-CLI durchführen](https://docs.stripe.com/webhooks.md#local-listener).

### Webhook-URL-Format

Das URL-Format zum Registrieren eines Webhook-Endpoints ist:

```
https://<your-website>/<your-webhook-endpoint>
```

Wenn Ihre Domain z.&nbsp;B. `https://mycompanysite.com` und die Weiterleitung zu Ihrem Webhook-Endpoint `@app.route('/stripe_webhooks', methods=['POST'])` lautet, geben Sie `https://mycompanysite.com/stripe_webhooks` als Endpoint-URL an.

### Ein Ereignisziel für Ihren Webhook-Endpoint erstellen

#### Dashboard

So erstellen Sie einen neuen Webhook-Endpoint im Dashboard:

1. Öffnen Sie die Registerkarte [Webhooks](https://dashboard.stripe.com/webhooks) in Workbench.
2. Klicken Sie auf **Erstellen Sie ein Ereignisziel**.
3. Wählen Sie **Ihr Konto**, um Ereignisse aus Ihrem eigenen Konto zu überwachen.
4. Wählen Sie die API-Version für das [Ereignisobjekt](https://docs.stripe.com/api/events.md) aus, das Sie verwenden möchten.
5. Wählen Sie die [Ereignistypen](https://docs.stripe.com/api/events/types.md) aus, die Sie an einen Webhook-Endpoint senden möchten.
6. Wählen Sie **Weiter** und dann **Webhook-Endpoint** als Zieltyp.
7. Klicken Sie auf **Weiter** und geben Sie dann die **Endpoint-URL** und eine optionale Beschreibung für den Webhook ein.
8. Auf der Seite mit den Webhook-Einstellungen wird ein Signatur-Geheimschlüssel angezeigt, der mit `whsec_` beginnt. Klicken Sie auf **Geheimschlüssel anzeigen** und kopieren Sie den Wert, um ihn beim [Erstellen eines Handlers](https://docs.stripe.com/webhooks.md#webhook-endpoint-def) zu verwenden.

> [Workbench](https://docs.stripe.com/workbench.md) ersetzt das vorhandene [Entwickler-Dashboard](https://docs.stripe.com/development/dashboard.md). Sie können im Entwickler-Dashboard weiterhin einen [neuen Webhook-Endpoint erstellen](https://docs.stripe.com/development/dashboard/webhooks.md). Wir empfehlen jedoch die Verwendung von Workbench.

#### API

Verwenden Sie den Endpoint [/v2/core/event_destinations](https://docs.stripe.com/api/v2/event-destinations.md), um einen neuen Endpoint zu registrieren.

#### Snapshot-Ereignisse

Um [Snapshot-Ereignisse](https://docs.stripe.com/api/events/types.md) aus Ihrem eigenen Konto zu überwachen, legen Sie für den Wert [event_payload](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-event_payload) `snapshot` und für den Wert [enabled_events](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-enabled_events) die Ereignistypen fest, die Sie an den Webhook-Endpoint senden möchten:

```curl
curl -X POST https://api.stripe.com/v2/core/event_destinations \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-08-26.preview" \
  --json '{
    "name": "My event destination",
    "type": "webhook_endpoint",
    "events_from": [
        "@self"
    ],
    "event_payload": "snapshot",
    "enabled_events": [
        "payment_intent.succeeded",
        "payment_intent.payment_failed"
    ],
    "webhook_endpoint": {
        "url": "https://mycompanysite.com/webhook"
    },
    "include": [
        "webhook_endpoint.signing_secret"
    ]
  }'
```

Die Ausgabe enthält einen Wert für `webhook_endpoint.signing_secret`, der mit `whsec_` beginnt. Kopieren Sie diesen Wert, um ihn beim [Erstellen eines Handlers](https://docs.stripe.com/webhooks.md#webhook-endpoint-def) zu verwenden.

#### Thin-Ereignisse

Wenn Sie [Thin-Ereignisse](https://docs.stripe.com/api/v2/core/events/event-types.md) verwenden, müssen Sie einen separaten Webhook-Endpoint registrieren. Lesen Sie mehr über [die Unterschiede zwischen Thin-Ereignissen und Snapshot-Ereignissen](https://docs.stripe.com/event-destinations.md#events-overview).

Um [Thin-Ereignisse](https://docs.stripe.com/api/v2/core/events/event-types.md) aus Ihrem eigenen Konto zu überwachen, legen Sie für den Wert [event_payload](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-event_payload) `thin` und für den Wert [enabled_events](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-enabled_events) die Ereignistypen fest, die Sie an den Webhook-Endpoint senden möchten:

```curl
curl -X POST https://api.stripe.com/v2/core/event_destinations \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-08-26.preview" \
  --json '{
    "name": "My event destination",
    "type": "webhook_endpoint",
    "events_from": [
        "@self"
    ],
    "event_payload": "thin",
    "enabled_events": [
        "v1.billing.meter.error_report_triggered"
    ],
    "webhook_endpoint": {
        "url": "https://mycompanysite.com/webhook"
    },
    "include": [
        "webhook_endpoint.signing_secret"
    ]
  }'
```

Die Ausgabe enthält einen Wert für `webhook_endpoint.signing_secret`, der mit `whsec_` beginnt. Kopieren Sie diesen Wert, um ihn beim [Erstellen eines Handlers](https://docs.stripe.com/webhooks.md#webhook-endpoint-def) zu verwenden.

### Testen Sie lokal ohne registrierte URL

Wenn Sie über keine registrierte, öffentlich zugängliche HTTPS-URL verfügen, können Sie Webhooks lokal testen, indem Sie die Stripe-CLI verwenden, um [Ereignisse an Ihren lokalen Endpoint weiterzuleiten](https://docs.stripe.com/cli/use-cli#forward-events-to-your-local-webhook-endpoint):

1. Falls noch nicht geschehen, [installieren Sie die Stripe-CLI](https://docs.stripe.com/cli/install) auf Ihrem Computer.

2. Melden Sie sich in Ihrem Stripe-Konto an und richten Sie die CLI ein, indem Sie in der Befehlszeile `stripe login` ausführen.

3. Geben Sie Ihrem lokalen Host die Möglichkeit, ein simuliertes Ereignis zu empfangen, indem Sie je nach Umfang und Typ des Ereignisses den Befehl [stripe listen](https://docs.stripe.com/cli/listen) ausführen:

   #### Snapshot-Ereignisse weiterleiten

   Verwenden Sie den folgenden Befehl, um [Snapshot-Ereignisse](https://docs.stripe.com/event-destinations.md#events-overview) von Ihrem Konto an Ihren lokalen Listener weiterzuleiten.

   ```bash
   stripe listen --forward-to localhost:4242/webhook
   ```

   #### Thin-Ereignisse weiterleiten

   Verwenden Sie den folgenden Befehl, um [Thin-Ereignisse](https://docs.stripe.com/event-destinations.md#events-overview) von Ihrem Konto an Ihren lokalen Listener weiterzuleiten.

   ```bash
   stripe listen --forward-thin-to localhost:4242/webhook --thin-events "*"
   ```

   Dieser Befehl geht davon aus, dass Sie über eine Localhost-Website auf dem Port 4242 mit einem Endpoint `POST /webhook` verfügen, den Sie beim [Erstellen eines Handlers](https://docs.stripe.com/webhooks.md#webhook-endpoint-def) konfigurieren können.

4. Der Befehl `stripe listen` gibt den Wert `{{WEBHOOK_SIGNING_SECRET}}` aus. Kopieren Sie diesen Wert, um ihn beim [Erstellen eines Handlers](https://docs.stripe.com/webhooks.md#webhook-endpoint-def) zu verwenden.

   ```output
   Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)
   ```

> Um das Argument `--forward-to` mit `stripe listen` zu verwenden, müssen Sie den Befehl mit der [Stripe-CLI](https://docs.stripe.com/cli.md) in einem Datenterminal ausführen. Dieser Befehl kann nicht in der [Workbench Shell](https://docs.stripe.com/workbench/shell.md) ausgeführt werden, da das Argument `--forward-to` dort nicht unterstützt wird.

## Handler erstellen

Richten Sie eine HTTP- oder HTTPS-Endpoint-Funktion ein, die Webhook-Anfragen mit einer POST-Methode akzeptieren kann. Wenn Sie noch dabei sind, Ihre Endpoint-Funktion auf Ihrem lokalen Computer zu entwickeln, kann HTTP für diese verwendet werden. Nachdem sie öffentlich zugänglich ist, muss Ihre Webhook-Endpoint-Funktion HTTPS nutzen.

Verwenden Sie die Stripe-API-Dokumentation, um die [Thin-Ereignisobjekte](https://docs.stripe.com/api/v2/core/events/event-types.md) oder [Snapshot-Ereignisobjekte](https://docs.stripe.com/api/events/types.md) zu ermitteln, die Ihr Webhook-Handler verarbeiten muss.

Richten Sie Ihre Endpoint-Funktion wie folgt ein:

- Verarbeitet POST-Anfragen mit einer JSON-Nutzlast, die Ereignisinformationen enthält.
- Bestätigt anhand der JSON-Nutzlast, dem Header `Stripe-Signature` und dem mit `whsec_` beginnenden Webhook-Signatur-Geheimschlüssel aus dem vorherigen Schritt, dass die Webhook-Anfrage von Stripe generiert wurde. Wenn die Bestätigung fehlschlägt, erhalten Sie eine Fehlermeldung.
- Gibt schnell einen erfolgreichen Statuscode (`2xx`) zurück&nbsp;– also vor jeglicher komplexer Logik, die eine Zeitüberschreitung verursachen könnte. Beispielsweise müssen Sie eine `200`-Antwort zurückgeben, bevor Sie die Rechnung einer Kundin oder eines Kunden in Ihrem Buchhaltungssystem als bezahlt aktualisieren können.

> #### Bearbeiten Sie nicht den reinen Text der Anfrage
> 
> Stripe benötigt den Rohtext der Anfrage, um die Signaturprüfung durchzuführen. Wenn Sie ein Framework verwenden, müssen Sie sicherstellen, dass der Rohtext nicht manipuliert wird. Jegliche Manipulation des Rohtextes der Anfrage führt dazu, dass die Verifizierung fehlschlägt.
> 
> Erfahren Sie, wie Sie [Fehler bei der Überprüfung der Signatur beheben](https://docs.stripe.com/webhooks/signature.md) können.

#### Beispiel-Endpoint

Bei diesem Codeausschnitt handelt es sich um eine Webhook-Funktion, die so konfiguriert ist, dass sie nach empfangenen Ereignissen sucht, das Ereignis verarbeitet und eine `200`-Antwort zurückgibt. Verweisen Sie auf den [Snapshot](https://docs.stripe.com/event-destinations.md#events-overview)-Ereignis-Handler, wenn Sie API v1-Ressourcen verwenden, und verweisen Sie auf den [Thin](https://docs.stripe.com/event-destinations.md#events-overview)-Ereignis-Handler, wenn Sie API v2-Ressourcen verwenden.

#### Snapshot-Ereignis-Handler

Wenn Sie einen Snapshot-Ereignis-Handler erstellen, verwenden Sie die API-Objektdefinition zum Zeitpunkt des Ereignisses für Ihre Logik, indem Sie auf die `data.object`-Felder des Ereignisses zugreifen. Sie können die API-Ressource auch von der Stripe API abrufen, um auf die neueste und aktuellste Objektdefinition zuzugreifen.

#### Ruby

```ruby
require 'json'
require 'stripe'

client = Stripe::StripeClient.new(ENV.fetch('STRIPE_API_KEY'))

# 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
```

#### Thin-Ereignishandler (Clover+)

Wenn Sie einen Thin-Eventhandler erstellen, verwenden Sie die `fetchRelatedObject()`-Methode, um die neueste Version des mit dem Ereignis verbundenen Objekts abzurufen. Ereignisse können [zusätzliche Daten](https://docs.stripe.com/event-destinations.md#fetch-data) enthalten, die Sie nur über die Instanzmethode `.fetchEvent()` in `EventNotification` abrufen können. Die genaue Form dieser Daten hängt vom `type` des Ereignisses ab.

Ereignistypen müssen zum Zeitpunkt der Veröffentlichung verfügbar sein, um Klassen in dieser SDK-Version zu generieren. Um Ereignisse zu verarbeiten, für die das SDK keine Klassen hat, verwenden Sie die `UnknownEventNotification`-Klasse.

#### 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
```

## Handler testen

Bevor Sie mit Ihrer Webhook-Endpoint-Funktion live gehen, empfehlen wir Ihnen, Ihre Anwendungsintegration zu testen, indem Sie Ereignisse in einer Sandbox auslösen oder Testereignisse mit der [Stripe-CLI](https://docs.stripe.com/cli.md) senden.

### Lösen Sie Testereignisse aus

Um Testereignisse zu senden, lösen Sie einen Ereignistyp aus, den Ihr Ereignisziel abonniert hat, indem Sie manuell ein Objekt im Stripe-Dashboard erstellen. Erfahren Sie, wie Sie Ereignisse mit [Stripe für VS-Code](https://docs.stripe.com/stripe-vscode.md) auslösen können.

#### Snapshot-Ereignis auslösen

Sie können den folgenden Befehl entweder in der [Stripe Shell](https://docs.stripe.com/workbench/shell.md) oder in der [Stripe-CLI](https://docs.stripe.com/cli.md) verwenden. Dieses Beispiel löst das Ereignis `payment_intent.succeeded` aus:

```bash
stripe trigger payment_intent.succeeded
Running fixture for: payment_intent
Trigger succeeded! Check dashboard for event details.
```

#### Thin-Ereignis auslösen

Sie können den folgenden Befehl in der [Stripe-CLI](https://docs.stripe.com/cli.md) verwenden. Dieses Beispiel löst das Ereignis `v1.billing.meter.error_report_triggered` aus:

```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.
```

## Optional: Erstellen Sie ein Ereignisziel für Connect

Wenn Sie als Connect-Plattform ein [Ereignisziel erstellen](https://docs.stripe.com/webhooks.md#create-webhook-endpoint), wählen Sie aus, welchen Bereich dieses Ziel überwacht:

#### Dashboard

- **Ihr Konto**: Ereignisse von Ressourcen in Ihrem Konto.
- **Verbundene Konten**: Ereignisse von Ressourcen, die zu Ihren verbundenen Konten gehören.

#### API

- [events_from=[“@self”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): Ereignisse von Ressourcen in Ihrem Konto.
- [events_from=[“@accounts”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): Ereignisse von Ressourcen, die zu Ihren verbundenen Konten gehören.

Registrieren Sie ein Ereignisziel für **verbundene Konten**, um Ereignisse für Ressourcen zu empfangen, die zu Ihren verbundenen Konten gehören. Beispiele hierfür sind [Direct Charges](https://docs.stripe.com/connect/direct-charges.md), Kunden/Kundinnen und Zahlungsmethoden verbundener Konten, fehlgeschlagene Auszahlungen und Aktualisierungen des alten Snapshot-Lifecycle für verbundene Konten, wie Onboarding, Verifizierung, Änderungen an externen Konten und Kontotrennungen. Bei Accounts v2 empfängt dieser Bereich nur Snapshot-Ereignisse für Account-Objekte, die Ihre verbundenen Konten darstellen.

Je nach Ihrer Connect-Integration müssen Sie möglicherweise auch ein Ereignisziel für **Ihr Konto** registrieren. Dies kann unter anderem folgende Gründe haben:

- Das Abwickeln von Ereignissen für Ressourcen auf Ihrem Plattformkonto, einschließlich Kundinnen und Kunden der Plattform, plattformeigene Zahlungen, [Destination Charges](https://docs.stripe.com/connect/destination-charges.md) und [separate Zahlungen und Überweisungen](https://docs.stripe.com/connect/separate-charges-and-transfers.md).
- Das Abwickeln von Thin-Ereignissen im Zusammenhang mit Accounts v2-Objekten, die verbundene Konten darstellen.

Weitere Details finden Sie unter [Connect-Webhooks](https://docs.stripe.com/connect/webhooks.md?accounts-namespace=v2).

### Testen Sie Connect lokal ohne registrierte URL

#### Snapshot-Ereignisse

Verwenden Sie den folgenden Befehl, um [Snapshot-Ereignisse](https://docs.stripe.com/event-destinations.md#events-overview) von verbundenen Konten an Ihren lokalen Listener weiterzuleiten.

```bash
stripe listen --forward-connect-to localhost:4242/webhook
```

#### Thin-Ereignisse

Verwenden Sie den folgenden Befehl, um [Thin-Ereignisse](https://docs.stripe.com/event-destinations.md#events-overview) von verbundenen Konten an Ihren lokalen Listener weiterzuleiten.

```bash
stripe listen --forward-thin-connect-to localhost:4242/webhook --thin-events "*"
```

## Optional: Erstellen Sie ein Ereignisziel für Organizations

Wenn Sie als Organization ein [Ereignisziel erstellen](https://docs.stripe.com/webhooks.md#create-webhook-endpoint), wählen Sie aus, welchen Bereich dieses Ziel überwacht:

#### Dashboard

- **Konten in Ihrer Organization**: Ereignisse von Ressourcen in den Konten Ihrer Organization.
- **Verbundene Konten**: Ereignisse von Ressourcen innerhalb der verbundenen Konten Ihrer Organization.

#### API

- [events_from=[“@organization_members”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): Ereignisse von Ressourcen in den Konten Ihrer Organization.
- [events_from=[“@organization_members/@accounts”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): Ereignisse von Ressourcen innerhalb der verbundenen Konten Ihrer Organization.

### Nicht unterstütztes Ereignistypverhalten für Organisationsereignisziele

Stripe sendet die meisten Ereignistypen asynchron, wartet jedoch bei einigen Ereignistypen auf eine Antwort. In diesen Fällen verhält sich Stripe unterschiedlich, je nachdem, ob das Ereignisziel antwortet.

Wenn Ihr Ereignisziel [Organisations-](https://docs.stripe.com/get-started/account/orgs.md)Ereignisse empfängt, besitzen diejenigen, die eine Antwort erfordern, die folgenden Einschränkungen:

- Sie können `issuing_authorization.request` für Organisationsziele nicht abonnieren. Richten Sie stattdessen einen [Webhook-Endpoint](https://docs.stripe.com/webhooks.md#example-endpoint) in einem Stripe-Konto innerhalb der Organisation ein, um diesen Ereignistyp zu abonnieren. Verwenden Sie `issuing_authorization.request`, um Kaufanfragen in Echtzeit zu autorisieren.
- Organisationsziele, die `checkout_sessions.completed` empfangen, können nicht [mit dem Weiterleitungsverhalten](https://docs.stripe.com/checkout/fulfillment.md#redirect-hosted-checkout) umgehen, wenn Sie [Checkout](https://docs.stripe.com/payments/checkout.md) direkt in Ihre Website einbetten oder Kunden/Kundinnen auf eine von Stripe gehostete Bezahlseite umleiten. Um das Weiterleitungsverhalten von Checkout zu beeinflussen, verarbeiten Sie diesen Ereignistyp mit einem [Webhook Endpoint](https://docs.stripe.com/webhooks.md#example-endpoint), der in einem Stripe-Konto innerhalb der Organisation konfiguriert ist.
- Organisationsziele, die erfolglos auf ein `invoice.created`-Ereignis reagieren, können den [automatischen Rechnungsabschluss nicht beeinflussen, wenn Sie den automatischen Einzug](https://docs.stripe.com/billing/subscriptions/webhooks.md#understand) verwenden. Sie müssen diesen Ereignistyp mit einem [Webhook-Endpoint](https://docs.stripe.com/webhooks.md#example-endpoint) verarbeiten, der in einem Stripe-Konto innerhalb der Organisation konfiguriert ist, um den automatischen Abschluss der Rechnung auszulösen.

#### Verwendet `context`

#### Snapshot-Ereignisse

Dieser Codeausschnitt ist eine Webhook-Funktion, die so konfiguriert ist, dass sie nach empfangenen Ereignissen sucht, das Ursprungskonto gegebenenfalls erkennt, das Ereignis verarbeitet und eine `200`-Antwort zurückgibt.

#### Ruby

```ruby
require 'json'

client = Stripe::StripeClient.new('sk_...')

# 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 = client.v1.customers.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 = client.v1.payment_methods.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
```

#### Thin-Ereignishandler (Clover+)

Verwenden Sie die Eigenschaft `context` von `EventNotification`, um das Konto für Ereignisse innerhalb Ihrer [Organisation](https://docs.stripe.com/get-started/account/orgs.md) zu identifizieren. Sie müssen den [Stripe-Context-Header](https://docs.stripe.com/context.md) manuell für alle API-Aufrufe festlegen, mit Ausnahme von `.fetchRelatedObject()` und `.fetchEvent()`, die dies automatisch für Sie übernehmen.

#### 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)
```

## Webhook-Integrationen debuggen

Bei der Übermittlung von Ereignissen an Ihren Webhook-Endpoint können mehrere Arten von Problemen auftreten:

- Stripe kann ein Ereignis möglicherweise nicht an Ihren Webhook-Endpoint übermitteln.
- Bei Ihrem Webhook-Endpoint besteht möglicherweise ein SSL-Problem.
- Ihre Netzwerkverbindung ist unterbrochen.
- Ihr Webhook-Endpoint empfängt die von Ihnen erwarteten Ereignisse nicht.

### Ereignisübermittlungen anzeigen

Um die Zustellungen von Events anzuzeigen, öffnen Sie [Workbench](https://docs.stripe.com/workbench.md), wählen Sie den Webhook-Endpoint unter **Webhooks** aus und klicken Sie anschließend auf die Registerkarte **Übermittlungen von Events**. Auf der Registerkarte **Übermittlungen von Events** finden Sie eine Liste der Events und den Status `Delivered`, `Pending` oder `Failed`. Klicken Sie auf ein Event, um die Metadaten anzuzeigen, darunter den HTTP-Statuscode des Zustellversuchs und den Zeitpunkt ausstehender zukünftiger Übermittlungen.

Sie können auch die [Stripe-CLI](https://docs.stripe.com/cli.md) verwenden, um direkt in Ihrem Datenterminal [auf Ereignisse zu warten](https://docs.stripe.com/webhooks.md#test-webhook).

### HTTP-Statuscodes korrigieren

Wenn ein Ereignis den Statuscode `200` anzeigt, bedeutet dies eine erfolgreiche Zustellung an den Webhook-Endpoint. Möglicherweise erhalten Sie auch einen anderen Statuscode als `200`. In der folgenden Tabelle finden Sie eine Liste gängiger HTTP-Statuscodes und empfohlener Lösungen.

| Webhook-Status ausstehend | Beschreibung | Korrigieren |
| --- | --- | --- |
| (Verbindung nicht möglich) FHLR | Wir können keine Verbindung zum Zielserver herstellen. | Stellen Sie sicher, dass Ihre Host-Domain im Internet öffentlich zugänglich ist. |
| (`302`) FHLR (oder ein anderer `3xx`-Status) | Der Zielserver hat versucht, die Anfrage an einen anderen Standort umzuleiten. Wir betrachten Weiterleitungsantworten auf Webhook-Anfragen als fehlgeschlagen. | Legen Sie das Webhook-Endpoint-Ziel auf die durch die Weiterleitung aufgelöste URL fest. |
| (`400`) FHLR (oder ein anderer `4xx`-Status) | Der Zielserver kann oder will die Anfrage nicht verarbeiten. Dies kann vorkommen, wenn der Server einen Fehler erkennt (`400`), wenn die Ziel-URL Zugriffsbeschränkungen aufweist (`401`, `403`, `405`) oder wenn die Ziel-URL nicht existiert (`404`). | Stellen Sie sicher, dass Ihr Endpoint öffentlich für das Internet zugänglich ist und eine POST HTTP-Methode akzeptiert. |
| (`500`) FHLR (oder ein anderer `5xx`-Status) | Bei der Verarbeitung der Anfrage ist auf dem Zielserver ein Fehler aufgetreten. | Überprüfen Sie die Protokolle Ihrer Anwendung, um zu verstehen, warum der Fehler `500` zurückgegeben wird. |
| (TLS-Fehler) FHLR | Wir konnten keine sichere Verbindung zum Zielserver herstellen. Diese Fehler werden in der Regel durch Probleme mit dem SSL/TLS-Zertifikat oder einem Zwischenzertifikat in der Zertifikatskette des Zielservers verursacht. Stripe erfordert die *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` oder neuer. | Führen Sie einen [SSL-Servertest](https://www.ssllabs.com/ssltest/) durch, um Probleme zu finden, die diesen Fehler möglicherweise verursacht haben. |
| (Zeit überschritten) FHLR | Die Antwort des Zielservers auf die Webhook-Anfrage dauerte zu lange. | Stellen Sie sicher, dass Sie komplexe Logik zurückstellen und sofort eine erfolgreiche Antwort in Ihrem Webhook-Verarbeitungscode zurückgeben. |

## Verhaltensweisen der Ereignisübermittlung

In diesem Abschnitt erfahren Sie, welche Verhaltensweisen Sie in Bezug auf das Senden von Ereignissen durch Stripe an Ihren Webhook-Endpoint erwarten können.

### Automatische Wiederholungsversuche

Stripe versucht, Ereignisse mit einem exponentiellen Backoff im Live-Modus bis zu drei Tage an Ihr Ziel zu senden. Wann der nächste Wiederholungsversuch stattfinden wird, sofern zutreffend, sehen Sie auf der Registerkarte **Ereignisübermittlungen** Ihres Ereignisziels. Wir versuchen, Ereignisse, die in einer Sandbox erstellt wurde, innerhalb weniger Stunden dreimal zu übermitteln. Wenn Ihr Ziel bei unserem Wiederholungsversuch deaktiviert oder gelöscht wurde, unternehmen wir keine zukünftigen Wiederholungsversuche für dieses Ereignis. Wenn Sie ein Ereignisziel jedoch deaktivieren und wieder reaktivieren, bevor wir einen erneuten Versuch starten können, sehen Sie nach wie vor zukünftige Wiederholungsversuche.

### Manuelle Wiederholungsversuche

Es gibt zwei Möglichkeiten, Ereignisse manuell zu wiederholen:

- Klicken Sie im Stripe-Dashboard auf **Erneut senden**, wenn Sie sich ein bestimmtes Ereignis ansehen. Dies funktioniert bis zu 15 Tage nach der Erstellung des Ereignisses.
- Führen Sie mit der [Stripe CLI](https://docs.stripe.com/cli/events/resend) den Befehl `stripe events resend <event_id> --webhook-endpoint=<endpoint_id>` aus. Dies funktioniert bis zu 30&nbsp;Tage nach der Erstellung des Ereignisses.

Das manuelle erneute Senden eines Ereignisses, bei dem zuvor Fehler bei der Zustellung an einen Webhook-Endpoint aufgetreten sind, hebt das [automatische Wiederholungsverhalten](https://docs.stripe.com/webhooks.md#automatic-retries) von Stripe nicht auf, selbst wenn dies zu einem `2xx`-Statuscode führt. Erfahren Sie, wie Sie [nicht zugestellte Webhook-Ereignisse verarbeiten können](https://docs.stripe.com/webhooks/process-undelivered-events.md), um zukünftige Wiederholungsversuche zu verhindern.

### Anordnung von Ereignissen

Stripe garantiert die Übermittlung von Ereignissen nicht in der Reihenfolge, in der sie generiert wurden. Beim Erstellen eines Abonnements können beispielsweise die folgenden Ereignisse generiert werden:

- `customer.subscription.created`
- `invoice.created`
- `invoice.paid`
- `charge.created` (wenn eine Zahlung vorhanden ist)

Stellen Sie sicher, dass Ihr Ereignisziel nicht davon abhängig ist, dass Ereignisse in einer bestimmten Reihenfolge empfangen werden. Snapshot-Ereignisse erfassen `erstellt` in Sekunden, sodass unterschiedliche Ereignisse denselben Zeitstempel haben können. Verwenden Sie `erstellt` nicht, um die Ereignisreihenfolge zu bestimmen oder ob Sie ein Ereignis bereits verarbeitet haben. Verfolgen Sie stattdessen [Ereignis-IDs](https://docs.stripe.com/api/events/object.md#event_object-id), um doppelte Zustellungen zu identifizieren. Sie können auch die API verwenden, um fehlende Objekte abzurufen. Beispielsweise können Sie die Rechnungs-, Abbuchungs- und Abonnement-Objekte mit den Informationen aus `invoice.paid` abrufen, wenn Sie dieses Ereignis zuerst empfangen.

### API-Versionierung

Die API-Version in Ihren Kontoeinstellungen beim Auftreten des Ereignisses bestimmt die API-Version und damit die Struktur eines [Ereignisses](https://docs.stripe.com/api/events.md), das an Ihr Ziel gesendet wird. Wenn für Ihr Konto beispielsweise eine ältere API-Version festgelegt ist, z.&nbsp;B. 16.02.2015, und Sie die API-Version mit [Versionierung](https://docs.stripe.com/api.md#versioning) für eine bestimmte Anfrage ändern, basiert das generierte und an Ihr Ziel gesendete [Ereignis](https://docs.stripe.com/api/events.md)-Objekt weiterhin auf der API-Version 2015-02-16. Sie können [Ereignis](https://docs.stripe.com/api/events.md)-Objekte nach der Erstellung nicht mehr ändern. Wenn Sie beispielsweise eine Zahlung aktualisieren, bleibt das ursprüngliche Zahlungsereignis unverändert. Nachfolgende Aktualisierungen der API-Version Ihres Kontos ändern daher vorhandene [Ereignis](https://docs.stripe.com/api/events.md)-Objekte nicht rückwirkend. Auch das Abrufen eines älteren [Ereignisses](https://docs.stripe.com/api/events.md) durch Aufrufen von `/v1/events` mithilfe einer neueren API-Version wirkt sich nicht auf die Struktur des empfangenen Ereignisses aus. Sie können Testereignisziele entweder auf Ihre Standard-API-Version oder die neueste API-Version festlegen. Das an das Ziel gesendete [Ereignis](https://docs.stripe.com/api/events.md) ist für die angegebene Version des Ereignisziels strukturiert.

## Best Practices für die Verwendung von Webhooks

Überprüfen Sie diese Best Practices, um sicherzustellen, dass Ihre Webhook-Endpoints sicher bleiben und gut mit Ihrer Integration funktionieren.

### Umgang mit doppelten Ereignissen

Webhook-Endpoints empfangen gelegentlich dasselbe Ereignis mehrmals. Sie können sich vor dem Erhalt doppelter Ereignisse schützen, indem Sie Ihre verarbeiteten [Ereignis-IDs](https://docs.stripe.com/api/events/object.md#event_object-id) protokollieren und bereits protokollierte Ereignisse dann nicht erneut verarbeiten.

In einigen Fällen werden zwei separate Ereignisobjekte generiert und gesendet. Um diese Duplikate zu identifizieren, verwenden Sie die ID des Objekts in `data.object` zusammen mit dem `event.type`.

### Nur die Ereignistypen überwachen, die Ihre Integration erfordert

Konfigurieren Sie Ihre Webhook-Endpoints so, dass sie nur die für Ihre Integration erforderlichen Ereignistypen empfangen. Die Überwachung zusätzlicher Ereignisse (oder aller Ereignisse) belastet Ihren Server und wird nicht empfohlen.

Sie können [die Ereignisse](https://docs.stripe.com/api/webhook_endpoints/update.md#update_webhook_endpoint-enabled_events), die ein Webhook-Endpoint empfängt, im Dashboard oder mit der API ändern.

### Ereignisse asynchron verarbeiten

Konfigurieren Sie Ihren Handler so, dass eingehende Ereignisse mit einer asynchronen Warteschlange verarbeitet werden. Möglicherweise treten Skalierbarkeitsprobleme auf, wenn Sie sich für die synchrone Verarbeitung von Ereignissen entscheiden. Jeder große Anstieg bei den Webhook-Übermittlungen (z.&nbsp;B. zu Beginn des Monats, wenn alle Abonnements verlängert werden) kann Ihre Endpoint-Hosts überfordern.

Asynchrone Warteschlangen ermöglichen es Ihnen, die gleichzeitigen Ereignisse mit einer Geschwindigkeit zu verarbeiten, die Ihr System unterstützen kann.

### Webhook-Route vom CSRF-Schutz ausgenommen

Wenn Sie Rails, Django oder ein anderes Web-Framework verwenden, überprüft Ihre Website möglicherweise automatisch, ob jede POST-Anfrage ein *CSRF-Token* enthält. Dies ist eine wichtige Sicherheitsfunktion, die Sie und Ihre Nutzer/innen vor [Cross-Site-Request-Forgery](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_\(CSRF\)) -Angriffen schützt. Diese Sicherheitsmaßnahme kann Ihre Website jedoch auch daran hindern, legitime Ereignisse zu verarbeiten. In diesem Fall müssen Sie möglicherweise die Webhooks-Route vom CSRF-Schutz ausnehmen.

#### 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
```

### Ereignisse mit einem HTTPS-Server empfangen

Wenn Sie eine HTTPS-URL für Ihren Webhook-Endpoint verwenden (im Live-Modus erforderlich), validiert Stripe, dass die Verbindung zu Ihrem Server sicher ist, bevor wir Ihre Webhook-Daten senden. Damit dies funktioniert, muss der Server so konfiguriert sein, dass er HTTPS mit einem gültigen Server-Zertifikat unterstützt. Stripe-Webhooks unterstützen nur die *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)-Versionen v1.2 und v1.3.

### Geheimschlüssel für Signaturen für Endpoints in regelmäßigen Abständen neu generieren

Der Geheimschlüssel, der verwendet wird, um zu überprüfen, ob Ereignisse von Stripe stammen, kann auf der Registerkarte [Webhooks](https://dashboard.stripe.com/webhooks) in Workbench geändert werden. Um Geheimschlüssel zu schützen, empfehlen wir, sie in regelmäßigen Abständen neu zu generieren (zu ändern) oder wenn Sie vermuten, dass ein Geheimschlüssel kompromittiert wurde.

So generieren Sie einen Geheimschlüssel neu:

1. Klicken Sie auf der Registerkarte [Webhooks](https://dashboard.stripe.com/webhooks) in Workbench auf jeden Endpoint, für den Sie den Geheimschlüssel neu generieren möchten.
2. Navigieren Sie zum Überlaufmenü (⋯) und klicken Sie auf **Geheimschlüssel neu generieren**. Sie können den aktuellen Geheimschlüssel sofort ablaufen lassen oder den Ablauf um bis zu 24&nbsp;Stunden verzögern, damit Sie Zeit haben, den Verifizierungscode auf Ihrem Server zu aktualisieren. Während dieses Zeitraums sind mehrere Geheimschlüssel für den Endpoint aktiv. Stripe generiert bis zum Ablauf eine Signatur pro Geheimschlüssel.

### Überprüfen, ob Ereignisse von Stripe gesendet werden

Ohne Verifizierung können bei einem Angriff gefälschte Webhook-Ereignisse an Ihren Endpoint gesendet werden, um Aktionen wie die Ausführung von Bestellungen, die Gewährung von Kontozugriff oder die Änderung von Datensätzen auszulösen. Überprüfen Sie immer, ob Webhook-Ereignisse von Stripe stammen, bevor Sie sie verarbeiten.

Verwenden Sie diese beiden Schutzmaßnahmen:

- **IP-Zulassungsliste**: Stripe sendet Webhook-Ereignisse von einer festgelegten Liste von [IP-Adressen](https://docs.stripe.com/ips.md). Konfigurieren Sie Ihren Server oder Ihre Firewall so, dass nur Webhook-Anfragen von diesen Adressen akzeptiert werden.
- **Signaturüberprüfung**: Stripe signiert jedes Webhook-Ereignis, indem es eine Signatur in den Header `Stripe-Signature` einfügt. Überprüfen Sie diese Signatur mithilfe unserer [offiziellen Bibliotheken](https://docs.stripe.com/webhooks.md#verify-signature) oder befolgen Sie die [Schritte zur manuellen Überprüfung](https://docs.stripe.com/webhooks.md?verify=verify-manually#verify-signature), um sicherzustellen, dass das Ereignis nicht von einem Dritten gesendet oder verändert wurde.

Im folgenden Abschnitt wird beschrieben, wie Sie Webhook-Signaturen verifizieren:

1. Rufen Sie den Geheimschlüssel Ihres Endpoints ab.
2. Überprüfen Sie die Signatur.

#### Geheimschlüssel Ihres Endpoints abrufen

Verwenden Sie Workbench und rufen Sie die Registerkarte [Webhooks](https://dashboard.stripe.com/webhooks) auf, um alle Ihre Endpoints anzuzeigen. Wählen Sie einen Endpoint aus, für den Sie den Geheimschlüssel abrufen möchten, und klicken Sie dann auf **Zum Anzeigen klicken**.

Stripe generiert für jeden Endpoint einen eindeutigen Geheimschlüssel. Wenn Sie denselben Endpoint sowohl für [Test- als auch für Live-API-Schlüssel](https://docs.stripe.com/keys.md#test-live-modes) verwenden, ist der Geheimschlüssel für jeden dieser Schlüssel unterschiedlich. Wenn Sie mehrere Endpoints verwenden, müssen Sie außerdem für jeden Endpoint, für den Sie Signaturen verifizieren möchten, einen Geheimschlüssel abrufen. Nach dieser Einrichtung beginnt Stripe, jeden Webhook zu signieren, der an den Endpoint gesendet wird.

#### Überprüfen Sie die Signatur

#### Verifizierung mit offiziellen Bibliotheken (empfohlen)

### Webhook-Signaturen mit offiziellen Bibliotheken verifizieren

Wir empfehlen die Verwendung unserer offiziellen Bibliotheken, um Signaturen zu überprüfen. Sie führen die Verifizierung durch, indem Sie die Ereignisnutzlast, den `Stripe-Signature`-Header und das Geheimnis des Endpoints angeben. Wenn die Verifizierung fehlschlägt, erhalten Sie eine Fehlermeldung.

Wenn Sie einen Fehler bei der Signaturüberprüfung erhalten, lesen Sie unseren Leitfaden zur [Fehlerbehebung](https://docs.stripe.com/webhooks/signature.md).

> Stripe benötigt den Rohtext der Anfrage, um die Signaturprüfung durchzuführen. Wenn Sie ein Framework verwenden, müssen Sie sicherstellen, dass der Rohtext nicht manipuliert wird. Jegliche Manipulation des Rohtextes der Anfrage führt dazu, dass die Verifizierung fehlschlägt.

#### 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.
client = Stripe::StripeClient.new('<<YOUR_SECRET_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 Dashboard
endpoint_secret = 'whsec_...'

# Using the Sinatra framework
set :port, 4242

post '/my/webhook/url' do
  payload = request.body.read
  sig_header = request.env['HTTP_STRIPE_SIGNATURE']
  event = nil

  begin
    event = 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
```

#### Manuell verifizieren

### Webhook-Signaturen manuell verifizieren

Obwohl wir empfehlen, unsere offiziellen Bibliotheken zu verwenden, um Webhook-Ereignissignaturen zu überprüfen, können Sie mithilfe dieses Abschnitts eine nutzerdefinierte Lösung erstellen.

Der `Stripe-Signature`-Header in jedem signierten Ereignis enthält einen Zeitstempel und eine oder mehrere Signaturen, die Sie überprüfen müssen. Dem Zeitstempel wird `t=` vorangestellt und jeder Signatur wird ein *Schema* vorangestellt. Schemata beginnen mit `v`, gefolgt von einer ganzen Zahl. Derzeit ist `v1` die einzige gültige Live-Signatur. Als Hilfe bei Tests sendet Stripe eine zusätzliche Signatur mit einem falschen `v0`-Schema für Ereignisse im Test-Modus.

```
Stripe-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd,
v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39
```

> Wir haben der Übersichtlichkeit halber neue Zeilen eingefügt, aber ein echter `Stripe-Signature`-Header befindet sich in einer einzigen Zeile.

Stripe generiert Signaturen mithilfe eines Hash-basierten Nachrichtenauthentifizierungscodes ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) mit [SHA-256](https://en.wikipedia.org/wiki/SHA-2). Um [Downgrade-Angriffe](https://en.wikipedia.org/wiki/Downgrade_attack) zu verhindern, ignorieren Sie alle Schemata, die nicht `v1` sind.

Sie können mehrere Signaturen mit demselben Schema-Geheimschlüssel-Paar haben, wenn Sie den [Geheimschlüssel eines Endpoints neu generieren](https://docs.stripe.com/webhooks.md#roll-endpoint-secrets) und den vorherigen Geheimschlüssel bis zu 24&nbsp;Stunden aktiv lassen. Während dieses Zeitraums verfügt Ihr Endpoint über mehrere aktive Geheimschlüssel und Stripe generiert für jeden dieser Geheimschlüssel eine Signatur.

Um eine manuelle Lösung zum Verifizieren von Signaturen zu erstellen, müssen Sie die folgenden Schritte ausführen:

#### Schritt 1: Entfernen Sie den Zeitstempel und die Signaturen aus der Kopfzeile

Teilen Sie die Kopfzeile mit dem Zeichen `,` auf, um eine Liste der Elemente zu erhalten. Teilen Sie dann jedes Element mit dem Zeichen `=` als Trennzeichen auf, um ein Präfix und ein Wertpaar zu erhalten.

Der Wert des Präfixes `t` entspricht dem Zeitstempel und `v1` entspricht der Signatur (oder den Signaturen). Sie können alle anderen Elemente verwerfen.

#### Schritt 2: Bereiten Sie die Zeichenfolge `signed_payload` vor

Die Zeichenfolge `signed_payload` wird durch Verketten folgender Elemente erstellt:

- Zeitstempel (als Zeichenfolge)
- Das Zeichen `.`
- Die tatsächliche JSON-Nutzlast (also der Anfragetext)

#### Schritt 3: Die erwartete Signatur ermitteln

Berechnen Sie einen HMAC mit der SHA256-Hash-Funktion. Verwenden Sie den Signatur-Geheimschlüssel des Endpoints als Schlüssel und die Zeichenfolge `signed_payload` als Nachricht.

#### Schritt 4: Vergleichen Sie die Signaturen

Vergleichen Sie die Signatur (oder Signaturen) in der Kopfzeile. Für eine identische Übereinstimmung, berechnen Sie die Differenz zwischen dem aktuellen und dem empfangenen Zeitstempel und entscheiden Sie dann, ob die Differenz in Ihrem Toleranzbereich liegt.

Zum Schutz vor Timing-Angriffen verwenden Sie einen konstanten Zeit-String-Vergleich, um die erwartete Signatur mit jeder der empfangenen Signaturen zu vergleichen.

### Replay-Angriffe verhindern

Bei einem [Replay-Angriff](https://en.wikipedia.org/wiki/Replay_attack) fängt ein Angreifer eine gültige Nutzlast und deren Signatur ab und überträgt sie dann erneut. Um solche Angriffe zu verhindern, fügt Stripe einen Zeitstempel in den `Stripe-Signature`-Header ein. Da der Zeitstempel zu der signierten Nutzlast gehört, ist er ebenfalls durch die Signatur verifiziert. So kann ein Angreifer den Zeitstempel nicht ändern, ohne dass die Signatur ungültig wird. Wenn die Signatur gültig, der Zeitstempel aber zu alt ist, kann Ihre Anwendung die Nutzlast ablehnen.

Unsere Bibliotheken haben eine Standardtoleranz von 5 Minuten zwischen dem Zeitstempel und der aktuellen Zeit. Sie können diese Toleranz ändern, indem Sie bei der Überprüfung von Signaturen einen zusätzlichen Parameter angeben. Verwenden Sie das Network Time Protocol ([NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol)), um sicherzustellen, dass die Uhrzeit Ihres Servers korrekt ist und mit der Zeit auf den Servern von Stripe synchronisiert wird.

> Verwenden Sie keinen Toleranzwert von `0`.Mit einem Toleranzwert von `0` wird die Aktualitätsprüfung vollständig deaktiviert.

Stripe generiert den Zeitstempel und die Signatur jedes Mal, wenn wir ein Ereignis an Ihren Endpoint senden. Wenn Stripe ein Ereignis wiederholt (zum Beispiel weil Ihr Endpoint zuvor mit einem Nicht-`2xx`-Statuscode geantwortet hat), generieren wir eine neue Signatur und einen neuen Zeitstempel für den neuen Zustellungsversuch.

### Schnelle Rückgabe einer 2xx-Antwort

Ihr [Endpoint](https://docs.stripe.com/webhooks.md#example-endpoint) muss schnell einen erfolgreichen Statuscode (`2xx`) zurückgeben, bevor eine komplexe Logik ausgeführt wird, die eine Zeitüberschreitung verursachen könnte. Beispielsweise müssen Sie eine `200`-Antwort zurückgeben, bevor Sie die Rechnung einer Kundin oder eines Kunden in Ihrem Buchhaltungssystem als bezahlt aktualisieren können.

## See also

- [Ereignisse an Amazon EventBridge senden](https://docs.stripe.com/event-destinations/eventbridge.md)
- [Senden Sie Ereignisse an Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md)
- [Liste der schlanken Ereignistypen](https://docs.stripe.com/api/v2/core/events/event-types.md)
- [Liste der Snapshot-Ereignistypen](https://docs.stripe.com/api/events/.md)
- [Interaktiver Generator für Webhook-Endpoints](https://docs.stripe.com/webhooks/quickstart.md)
