Ein Kunde hat bezahlt. Dein stripe webhook hat nicht gefeuert — und du liest Support-Mails statt Produkt zu shippen.
Stripe zeigt ein grünes Paid-Badge. Der Kunde hat eine Quittung. Deine App behandelt ihn noch wie einen Fremden. Kein Account-Upgrade, kein Lizenzschlüssel, keine Bestätigungsmail vom Backend. Die Checkout-Seite hat funktioniert. Der Teil, der dem Server Geldankunft meldet, nicht.
Kunde hat bezahlt, deine App bleibt still
Das ist der häufigste Fehler nach dem Launch. Checkout leitet mit einer Success-URL zurück auf deine Seite. Der Kunde sieht eine Danke-Seite. Die Seite ist Kosmetik. Sie beweist nicht, dass dein Backend die Zahlung verarbeitet hat.
Stripe ruft deine Datenbank nicht direkt an. Es schickt einen HTTP-POST an eine URL, die du registrierst. Ist die URL falsch, offline oder antwortet mit Fehler, versucht Stripe eine Weile und hört dann auf. Kein Alert im Editor. Kein Banner im Stripe-Dashboard — außer du schaust in die Webhook-Delivery-Logs.
KI-Coding-Tools rendern gut einen Pay-Button und einen Erfolgsscreen. Oft fehlt die Server-Route, die laufen muss, wenn Stripe die Zahlung bestätigt. Du bekommst einen hübschen Funnel und ein stilles Backend.
Stripe sagt bezahlt. Deine Datenbank wurde nicht aktualisiert
Öffne nach einer echten Zahlung deine App-Datenbank. Die User-Zeile zeigt noch free. Die Order-Tabelle ist leer. Die Subscription-Spalte ist null. Stripe hat das Geld. Deine Produktlogik ist nie gelaufen.
Diese Logik sitzt fast immer in einem Webhook-Handler: Event verifizieren, Customer-ID lesen, Zeile schreiben, Zugang freischalten, Mail einreihen. Liegt die Handler-Datei nur auf deinem Laptop oder läuft nur auf localhost, ändern sich Produktionsdaten nie.
Manche Teams rufen auf der Success-Seite clientseitig fetch('/api/confirm-payment') auf. Das ist fragil. Der Nutzer kann den Tab schließen, bevor die Anfrage fertig ist. Ein Webhook ist Stripe, das dich anruft — unabhängig vom Browser.
- Zahlung existiert im Stripe-Dashboard
- Keine passende Zeile in Orders oder Subscriptions
- Nutzer hat das Feature noch nicht, für das er bezahlt hat
- Webhook-Delivery-Log zeigt Fehler oder gar keine Versuche
Dein stripe webhook Endpoint fehlt in Produktion
Lokal nutzt man oft die Stripe CLI: stripe listen --forward-to localhost:3000/api/webhooks/stripe. Der Tunnel stirbt, wenn du das Terminal schließt. Das ist kein Produktions-Endpoint.
Nach Deploy auf Vercel, Railway oder einem VPS brauchst du eine öffentliche HTTPS-URL auf dem Live-Host, z. B. https://yourdomain.com/api/webhooks/stripe. Hast du nur eine localhost-URL im Stripe-Dashboard registriert, haben Live-Zahlungen kein Ziel.
Typische Produktions-Lücken:
- Webhook-Route nicht deployed (fehlt im Build oder falscher Pfad)
- Endpoint unter Test-Modus registriert, Site nutzt Live-Keys
- Firewall oder Auth-Middleware blockiert Stripes POST
- Server antwortet 404, weil der Framework-Routenname nicht zur Registrierung passt
Deployments aus Lovable, Bolt oder ähnlichen Editoren liefern oft die Checkout-UI ohne dauerhafte API-Route auf derselben Domain. Siehe lovable deploy für die anderen Produktionseinstellungen, nach denen Editoren selten fragen.
Webhook-Events, die deine App verarbeiten muss
Einen Endpoint registrieren reicht nicht. Du musst die richtigen Webhook-Events abonnieren. Zu wenige — Zahlungen laufen durch, ohne deinen Code zu triggern. Alles abonnieren — Lärm ohne Bugfix.
Starte mit diesen:
checkout.session.completed— Einmalzahlungen über Stripe Checkoutinvoice.paid— Abos und wiederkehrende Abrechnung
Nutzt deine Integration Payment Intents ohne Checkout, ergänze payment_intent.succeeded. Für typisches KI-SaaS mit Checkout decken die ersten beiden Events den meisten Launch ab.
Im Stripe-Dashboard jede fehlgeschlagene Delivery öffnen und den Response-Body lesen. 500 mit Stacktrace — Stripe hat deinen Server erreicht, der Handler ist gecrasht. Timeout — URL falsch oder Server down. Gar keine Delivery-Zeile — Endpoint in Live nie angelegt.
Im Stripe-Dashboard reparieren
Diese Liste auf der Live-Site mit Live-Keys durchgehen, bevor der nächste Kunde zahlt.
- In Stripe Dashboard einloggen und auf Live umschalten (Toggle oben rechts). Test-Webhooks feuern nicht für echte Charges.
- Zu Developers → Webhooks gehen.
- Add endpoint klicken (oder bestehenden bearbeiten, wenn die URL falsch ist).
- Endpoint URL auf deinen Produktions-HTTPS-Pfad setzen, z. B.
https://yourdomain.com/api/webhooks/stripe. Nicht localhost. Keine Preview-URL, außer Kunden nutzen genau diese Preview. - Under Events to send
checkout.session.completedundinvoice.paidwählen (weitere nur, wenn dein Stack sie braucht). - Endpoint speichern. Stripe zeigt ein Signing Secret. Dein Server muss Signaturen damit prüfen — Thema im Artikel stripe webhook secret, nicht hier.
- Test-Event aus dem Dashboard senden oder kleine Live-Zahlung. Delivery-Log auf 200 OK prüfen und Datenbank-Update bestätigen.
Dieselben Schritte im Test-Modus mit Staging-URL und Test-Keys wiederholen. Test und Live sind getrennte Welten. Eines zu fixen fixt nicht das andere.
Warum die KI Checkout ohne Webhook gebaut hat
Generatoren optimieren sichtbaren Fortschritt: Pricing-Page, Stripe-Checkout-Redirect, Erfolgsmeldung. Webhooks sind unsichtbar, bis sie versagen. Das Modell pastet Beispiel-Keys, überspringt Env-Variablen auf dem Host oder lässt den Handler als Kommentar. Die Lücke merkst du erst, wenn eine echte Karte belastet wird.
Webhook-Route als Teil des Payment-Features behandeln, nicht als Extra. Wenn Checkout shipped, shipped Handler und Dashboard-Endpoint im selben Pull Request.
Pre-Launch-Checkliste
- Live-Endpoint-URL existiert im Stripe-Dashboard unter Live-Modus
- Produktions-Server exponiert die Route und antwortet 200 auf gültige Events
checkout.session.completedund/oderinvoice.paidsind ausgewählt- Signing Secret aus dem Dashboard liegt in Produktions-Env-Vars (siehe Schwester-Artikel)
- Testzahlung im Test-Modus aktualisiert die Datenbank auf Staging
- Kleine Live-Zahlung aktualisiert die Datenbank in Produktion
- Webhook-Delivery-Log hat keine offenen Fehler
Stripe hält dein Geld sicher. Es rät nicht, wie deine App reagieren soll. Du musst ihm sagen, wo es klopfen soll.
FAQ
Warum zeigt Stripe bezahlt, aber meine App reagiert nicht?
Die Zahlung in Stripe war erfolgreich, aber dein Server hat das Webhook-Event nicht empfangen oder verarbeitet. Ohne Live-Endpoint für checkout.session.completed oder invoice.paid bleiben Datenbank und App unverändert.
Brauche ich separate stripe webhook Endpoints für Test und Live?
Ja. Test- und Live-Modus nutzen verschiedene API-Keys und verschiedene Webhook-Endpoints. Eine URL, die mit Test-Keys läuft, existiert in Live nicht automatisch.
Welche stripe webhook Events soll ich zuerst abonnieren?
Starte mit checkout.session.completed für einmalige Checkout-Zahlungen und invoice.paid für Abos. payment_intent.succeeded nur, wenn du Payment Intents direkt statt Checkout nutzt.