Dein stripe webhook secret ist falsch, und Stripe hat bereits aufgehört zu wiederholen — während deine App noch denkt, alles sei in Ordnung.
Der Endpoint existiert. Events sind ausgewählt. Kunden zahlen. Im Stripe-Dashboard unter Entwickler → Webhooks werden die Zustellzeilen rot. Antwortcode 400. Oder dein Handler liefert 200, überspringt die Verifizierung aber komplett — das ist schlimmer.
Was du siehst, wenn das Secret nicht passt
Stripe signiert jeden Webhook-POST mit einem Wert, der aus dem Signing Secret stammt, das du beim Anlegen des Endpoints kopiert hast. Dein Server muss diese Signatur neu berechnen und vergleichen. Wenn das Secret in deiner Umgebung nicht zum Endpoint passt, den Stripe aufruft, schlägt die Verifizierung fehl.
Typische Symptome:
- Dashboard zeigt 400 Bad Request oder einen Body mit
Webhook signature verification failed - Logs erwähnen
No signatures found matching the expected signature - Events wechseln nach mehreren Versuchen zu Failed und stoppen dann
- Test-Events aus dem Dashboard schlagen fehl, während der Rest deiner App gesund wirkt
Stripe klopft nicht ewig. Es wiederholt mit Backoff bis zu drei Tage lang bei Live-Endpoints, markiert das Event dann als fehlgeschlagen. Dein Kunde hat bereits bezahlt. Deine Datenbank wurde nie aktualisiert. Es gibt keine E-Mail von Stripe, die sagt, dein Secret sei falsch. Du siehst es nur, wenn du das Zustellungsprotokoll öffnest.
Wenn du gar keinen Endpoint registriert hast, ist das ein anderes Problem. Folge dem Artikel stripe webhook, um zuerst die Live-URL und Events anzubinden. Dieser Artikel setzt voraus, dass Stripe deinen Server erreichen kann, aber die Payload ablehnt — oder dein Code sie nie prüft.
Signing Secret vs. Endpoint Secret
Stripe nennt es im Dashboard Signing secret. Entwickler sagen auch Webhook Secret, Endpoint Secret oder whsec_-Wert. Für einen gegebenen Endpoint meinen sie dasselbe.
Verwechsle es nicht mit deinem API-Secret-Key (sk_live_... oder sk_test_...). Der API-Key beweist dich gegenüber Stripe, wenn dein Server Checkout-Sessions erstellt oder Kunden liest. Das Signing Secret beweist Stripe gegenüber dir, wenn es Events an deine URL POSTet. Den API-Key im Webhook-Handler zu verwenden verifiziert nichts.
- Test vs. Live. Jeder Modus hat sein eigenes
whsec_. Ein in Test-Modus kopiertes Secret schlägt bei Live-Zahlungen fehl. - Stripe CLI vs. Dashboard.
stripe listengibt ein temporäres Secret für deinen Laptop aus — nicht das Production-Endpoint-Secret. - Alter Endpoint, neues Deploy. Beim Neuanlegen eines Endpoints entsteht ein neues Signing Secret. Env-Vars vor dem nächsten Deploy aktualisieren.
Ein Endpoint, ein Secret, ein Modus. Halte Dashboard, Hosting-Env-Vars und constructEvent auf einer Linie.
Dein stripe webhook secret muss zur Production passen
Das Signing Secret ist kein Vorschlag. Ohne das korrekte stripe webhook secret in Production liefert jeder verifizierende Handler einen Fehler — und Stripe gibt irgendwann auf.
Prüfe das Umgebungs-Panel deines Hosts. Vercel, Railway, Render und Lovable-Publish-Flows haben alle einen Platz für Secrets. Der Variablenname muss zu dem passen, den dein Code liest — oft STRIPE_WEBHOOK_SECRET oder STRIPE_SIGNING_SECRET. Ein Tippfehler im Namen bedeutet, der Handler liest undefined — und die Verifizierung schlägt immer fehl.
Bestätige auch, dass du nach dem Setzen der Variable deployed hast. Manche Plattformen injizieren Env nur beim Build. Ein Secret von gestern hilft nicht, wenn Production noch den Build von letzter Woche fährt.
Zeigen Zustellungen 200, wird aber kein Zugang gewährt, ist die Verifizierung vielleicht umgangen. Manche generierte Handler kommentieren Signaturprüfungen aus und liefern so aus.
Keine Signaturprüfung ist ein Sicherheitsloch
Webhook-URLs sind nicht geheim. Wenn deine Route nur JSON parst und dem Body vertraut, kann jeder ein gefälschtes checkout.session.completed-Event POSTen. Dein Handler gewährt Zugang. Kein Geld bewegt sich. Stripe hat dieses Event nie gesendet.
Signaturverifizierung schließt diese Lücke. Stripe sendet einen Stripe-Signature-Header mit. Dein Code nutzt das Signing Secret, um zu bestätigen, dass der POST von Stripe kam. Überspringst du diesen Schritt, ist dein Payment-Gate eine öffentliche API.
KI-Coding-Tools generieren oft eine Webhook-Route, die event.type parst und die Datenbank aktualisiert. Verifizierung sind ein paar Extra-Zeilen, die das Modell fallen lässt, wenn es schnell „Zahlungen zum Laufen bringen“ will.
Die Checkliste zum lovable deploy enthält Env-Vars und Webhooks unter den Einstellungen, die Publish-Screens selten zeigen.
stripe webhook secret in Stripe und beim Host korrigieren
Arbeite im Live-Modus, wenn echte Kunden zahlen. Wiederhole im Test-Modus für Staging.
- Öffne das Stripe-Dashboard und wechsle zu Live (oder Test für Staging).
- Gehe zu Entwickler → Webhooks und klicke den Endpoint an, der zu deiner Production-URL passt. Existiert keiner, lege zuerst einen an — siehe den Artikel stripe webhook.
- Unter Signing secret auf Anzeigen klicken und den Wert ab
whsec_kopieren. - Öffne die Umgebungseinstellungen deines Hosting-Anbieters für das Production-Deployment.
- Setze
STRIPE_WEBHOOK_SECRET(oder wie dein Code es erwartet) auf genau diesen Wert. Keine Anführungszeichen im UI-Feld. Kein trailing Newline. - Bestätige, dass dein Handler den rohen Request-Body an Stripes Verifizierungs-Helper übergibt. Frameworks, die JSON zuerst parsen, zerstören Signaturprüfungen. Nutze den rohen String, den Stripe signiert hat.
- Redeploy oder starte den Service neu, damit die neue Env-Var geladen wird.
- Im Dashboard den Endpoint öffnen und Test-Webhook senden klicken. Im Zustellungsprotokoll 200 OK und in den Server-Logs ein verifiziertes Event bestätigen.
Schlägt die Verifizierung weiter fehl, vergleiche Zeichen für Zeichen. Rotiere das Secret im Dashboard mit Secret rotieren, aktualisiere den Host, redeploy und teste erneut. Alte Secrets funktionieren sofort nach einer Rotation nicht mehr.
Checkliste vor dem Launch
- Live-Endpoint existiert im Stripe-Dashboard (nicht nur CLI-Tunnel)
- Signing Secret von demselben Endpoint kopiert, den Production nutzt
whsec_in Production-Env-Vars, nicht in Client-Code oder Git- Test- und Live-Secrets sind nicht vertauscht
- Handler prüft
Stripe-Signaturebei jedem POST - Roher Request-Body für Verifizierung, dann parsen
- Test-Webhook aus dem Dashboard liefert 200
- Fehlgeschlagene Zustellungen im Log sind nach dem Fix bereinigt
Stripe wiederholt ein falsches Secret tagelang, dann stoppt es. Eine fehlende Prüfung wiederholt nie — es gibt nichts zu fixen, bis jemand eine Zahlung fälscht.
FAQ
Ist das stripe webhook secret dasselbe wie mein API-Secret-Key?
Nein. Dein API-Secret-Key (sk_live_...) authentifiziert ausgehende Aufrufe von deinem Server zu Stripe. Das Webhook-Signing-Secret (whsec_...) erlaubt deinem Server, eingehende POSTs von Stripe zu verifizieren. Das sind verschiedene Werte für verschiedene Richtungen.
Wo finde ich das stripe webhook secret im Dashboard?
Öffne Entwickler, dann Webhooks, klicke deinen Endpoint an und zeige Signing secret an. Jeder Endpoint in Test- und Live-Modus hat einen eigenen whsec_-Wert. Kopiere den, der zum Modus deiner Production-Seite passt.
Was passiert, wenn ich die Webhook-Signaturprüfung überspringe?
Jeder, der deine Webhook-URL findet, kann gefälschte Zahlungs-Events senden. Deine App gewährt vielleicht Zugang, liefert digitale Güter oder schreibt Bestellungen für Zahlungen, die nie stattfanden. Stripe blockiert diese gefälschten POSTs nicht für dich.