Stripe Webhooks: einrichten, verifizieren und testen

Stripe-Webhooks-Anleitung

Stripe Webhooks: Endpunkt, Signatur, Tests mit der CLI | We.Inc

Richte einen Stripe-Webhook-Endpunkt ein, prüfe Stripe-Signature mit dem Raw Body, teste mit stripe listen und stripe trigger und führe Checkout-Bestellungen genau einmal aus.

Ein Stripe-Webhook ist ein HTTPS-Endpunkt auf deinem Server, an den Stripe Event-JSON per POST sendet, etwa checkout.session.completed nach einer Zahlung. Dein Handler muss den Stripe-Signature-Header mit dem whsec_-Secret des Endpunkts gegen den unveränderten Raw Body prüfen, schnell einen 2xx-Status zurückgeben und damit klarkommen, dass dasselbe Event mehr als einmal ankommt.

Das Wichtigste zu Stripe-Webhooks (abgeglichen mit der Stripe-Dokumentation, Oktober 2026)

Die meisten kaputten Stripe-Integrationen scheitern an einer von drei Stellen: Das Framework hat den Body vor der Prüfung geparst, der Handler hat langsame Arbeit erledigt und ist in ein Timeout gelaufen, oder ein wiederholtes Event hat eine Bestellung doppelt ausgeführt. Diese Anleitung zeigt einen Handler, der alle drei vermeidet, und unten einen Checker, der einen Stripe-Signature-Header in deinem Browser prüft, damit du genau siehst, was die Library berechnet.

Häufige Fragen

Warum bekomme ich "No signatures found matching the expected signature"?

Fast immer, weil der Body vor der Prüfung verändert wurde, zum Beispiel durch express.json() oder einen Body-Parser, der das JSON neu kodiert. Binde express.raw({ type: "application/json" }) nur an die Webhook-Route oder lies request.text() in einem Next.js-Route-Handler. Ein falsches Secret führt zur selben Meldung.

Welche Events brauche ich für Stripe Checkout?

checkout.session.completed für Kartenzahlungen, dazu checkout.session.async_payment_succeeded für verzögerte Methoden wie Lastschriften. Stripe empfiehlt außerdem, checkout.session.async_payment_failed zu verarbeiten, damit du den Kunden informieren kannst. Prüfe vor dem Ausführen den payment_status der Session.

Kann ich mich statt auf einen Webhook auf die Erfolgsseite verlassen?

Nein. Laut Stripes eigener Dokumentation kann ein Kunde bezahlen und den Tab schließen, bevor deine Erfolgsseite lädt. Nutze die Erfolgsseite gern für eine schnelle Bestätigung, aber der Webhook muss die Ausführung ebenfalls auslösen, und beide Wege müssen gefahrlos zweimal laufen können.

Kommen Stripe-Events in der richtigen Reihenfolge an?

Stripe garantiert keine Reihenfolge. invoice.paid kann vor customer.subscription.created ankommen. Speichere Event-IDs, um Duplikate zu erkennen, und hol das zugehörige Objekt über die API, wenn du seinen aktuellen Stand brauchst.

Wie sende ich ein fehlgeschlagenes Event erneut?

Klicke im Dashboard beim Event auf Resend (funktioniert bis 15 Tage nach der Erstellung) oder führe mit der CLI stripe events resend <event_id> --webhook-endpoint=<endpoint_id> aus (bis 30 Tage). Automatische Wiederholungen laufen trotzdem weiter.

Die Raw-Body-Regel

Erst antworten, dann arbeiten

Genau einmal ausführen

Handler-Code

Express mit stripe-node

express.raw ist nur auf dieser Route eingebunden, sodass der Body als Originalbytes bei constructEvent ankommt.

Next.js-App-Router-Route-Handler

request.text() liefert den ungeparsten Body. Wirft constructEvent einen Fehler, sind Signatur oder Secret falsch.

Testen mit der Stripe CLI

Events lokal weiterleiten und auslösen

listen gibt für diese Sitzung ein whsec_-Secret aus. Trag es in deine lokale Umgebung ein und löse dann in einem zweiten Terminal Events aus.

Events, die du verarbeiten solltest

Häufige Stripe-Event-Typen und was zu tun ist

Stripe-Signature-Checker

Füge einen Stripe-Signature-Header, den Raw Body und dein whsec_-Secret ein, um dieselbe Prüfung zu sehen, die die Libraries ausführen. Alles läuft mit Web Crypto in deinem Browser und es wird nichts gesendet. Verwende ein Secret aus dem Testmodus, niemals ein Live-Secret.

Stripe-Signature-Header

Raw Request Body

Endpunkt-Secret (whsec_...)

Toleranz in Sekunden

Diesen Body jetzt signieren

Prüfen

Ergebnis

Der Header hat keinen t=-Zeitstempel.

Der Header hat keine v1=-Signatur.

Erwartetes v1: {v}

Die Signatur stimmt.

Die Signatur stimmt nicht: Der Body wurde verändert oder das Secret ist falsch.

Der Zeitstempel ist {n} Sekunden alt und liegt innerhalb der Toleranz.

Der Zeitstempel ist {n} Sekunden alt und liegt außerhalb der Toleranz: Eine Library würde ihn ablehnen.

Kostenlos starten · Keine Kreditkarte nötig

Verwandt: Ratgeber

Produkt

Für wen

Funktionen

Ressourcen

Unternehmen

Sitemap