Ein Bestellsystem erhält eine Nachricht über einen geänderten Zahlungsstatus. Es verarbeitet sie, doch die Antwort geht unterwegs verloren. Kommt dieselbe Nachricht erneut, kann eine schlecht geplante Integration einen zweiten Lagerauftrag erzeugen. Das ist ein Modellszenario, keine Kundengeschichte.
Ein Webhook ist eine Nachricht, die ein Dienst bei einem Ereignis an einen vorbereiteten Endpunkt einer anderen Anwendung sendet. Systeme können so reagieren, ohne ständig nach Änderungen zu fragen. Zuverlässigkeit entsteht aber nicht allein durch HTTP 200. Echtheit, Annahme und Abschluss des Geschäftsvorgangs sind getrennte Fragen.
zuverlässige Webhooks
Eine zugestellte Nachricht ist keine abgeschlossene Bestellung
Die HTTP-Antwort bestätigt das Ergebnis einer Anfrage gemäß dem Vertrag des jeweiligen Anbieters. Bei asynchroner Verarbeitung kann eine Nachricht sicher angenommen sein, während die eigentliche Arbeit in einer Warteschlange wartet. Das Unternehmen braucht deshalb zwei Sichten: Ist die Nachricht angekommen, und wurde der Vorgang ausgeführt?
Der Integrationsentwurf sollte angenommene, in Bearbeitung befindliche, abgeschlossene und fehlerhafte Einträge unterscheiden. Diese Zustände sind eine Entwurfshilfe, keine vorgeschriebenen Bezeichnungen von Stripe oder GitHub. Entscheidend ist, dass der Support eine liegen gebliebene Bestellung erklären und die Verarbeitung sicher fortsetzen kann.
Zuerst den Absender prüfen
GitHub empfiehlt HTTPS und ein Webhook-Secret. Prüfen Sie Signaturen genau nach Vorgabe des jeweiligen Anbieters. Die Kenntnis einer öffentlichen URL beweist keine Berechtigung des Absenders. Geheimnisse gehören weder in URLs noch in normale Logs oder Kundenbeispiele.
Bei Stripe-Webhooks muss der ursprüngliche Anfrageinhalt für die Signaturprüfung erhalten bleiben. Eigenmächtige JSON-Änderungen vor der Prüfung können diese scheitern lassen. Das bedeutet nicht, rohe Inhalte unbegrenzt in Anwendungslogs zu archivieren. Zugriff und Aufbewahrung sollten sich am Integrationsbedarf orientieren.
Die Signaturprüfung genügt nicht: Danach folgen Ereignistyp und die Frage, ob die Anwendung ihn unterstützt. Vor Einführung eines neuen Typs sollten erwartete und unbekannte Inhalte getestet werden. Ein unbekanntes Feld ist nicht zwingend ein Angriff, darf aber keinen unzulässigen Geschäftsvorgang stillschweigend auslösen.
Ein Ereignis kann mehrfach eintreffen
Stripe weist ausdrücklich auf Duplikate hin und garantiert keine Zustellreihenfolge. Daraus folgt kein identisches Verhalten aller Anbieter. Jede Integration hat eigene Regeln für Wiederholungen und Wiederanlauf, die in der Dokumentation geprüft werden müssen.
Idempotente Verarbeitung bedeutet, dass die Wiederholung desselben beabsichtigten Vorgangs keinen weiteren unerwünschten Effekt erzeugt. Die Frage „Existiert diese ID bereits?“ vor einem ungeschützten Schreibvorgang genügt nicht. Zwei gleichzeitige Anfragen können beide ein Nein erhalten. Wir empfehlen deshalb Datenbank-Eindeutigkeit zusammen mit transaktionaler Verarbeitung.
Ereignisidentität und Identität des Geschäftsvorgangs unterscheiden sich. Zwei verschiedene Ereignisse können dieselbe Bestellung betreffen. Neben der Zustelldeduplizierung braucht es eine Regel für erlaubte Statusübergänge. Eine ältere Nachricht sollte einen neueren bestätigten Zustand nicht ungeprüft überschreiben.
Ein Modell mit zwei Zustellungen und einem Ergebnis
Angenommen, ein synthetisches Ereignis heißt event-demo-001 und trifft zweimal ein. Der folgende Entwurf dient der Erklärung; er ist weder einsatzfertiger Code noch ein echtes Ereignisformat eines Anbieters:
- Signatur, Typ und Grunddaten prüfen.
- Einen Eingangseintrag dauerhaft mit einem eindeutigen Schlüssel aus Anbieter, Konto und Ereignis-ID speichern.
- Die Annahme erst nach sicherem Speichern bestätigen. Eine erneute Zustellung darf keinen zweiten Eingangseintrag erzeugen.
- Den Eintrag im Hintergrund verarbeiten und die Geschäftsänderung gegen Parallelität und Wiederholung schützen.
- Das Ergebnis festhalten und nach Fehlern kontrollierte Wiederholungen ermöglichen.
Stürzt der Prozess nach Annahme und vor Verarbeitung ab, muss der gespeicherte Eintrag auffindbar bleiben. „Diese ID haben wir gesehen“ genügt nicht, wenn die Arbeit nie abgeschlossen wurde. Bei einer weiteren Anfrage an ein externes System muss auch an dieser Grenze die Wiederholung behandelt werden.
Ein Idempotency Key für ausgehende Stripe-API-Anfragen ist ein anderes Werkzeug als die Erfassung eingehender Webhooks. Das eine ersetzt nicht automatisch das andere. Ebenso erläutert das Muster Competing Consumers, warum Warteschlangenverarbeitung Idempotenz berücksichtigen muss.
Ein praktischer Abnahmetest für die Integration
Senden Sie in einer Testumgebung dasselbe synthetische Ereignis zweimal, auch gleichzeitig. Simulieren Sie danach einen Fehler des Queue-Workers und setzen Sie die Verarbeitung fort. Ändern Sie schließlich die Reihenfolge zusammengehöriger Ereignisse. Das erwartete Geschäftsergebnis muss vorher feststehen, sonst lässt sich Erfolg nicht bewerten.
Dokumentieren Sie Testkennungen, Zustände und Ergebnisse ohne Geheimnisse oder unnötige personenbezogene Daten. Eine grüne Endpunktantwort genügt nicht als Kriterium. Der Test soll auch zeigen, ob das Problem eine handlungsfähige Person erreicht.
Was in die Anforderung an den Dienstleister gehört
Verlangen Sie eine Beschreibung von Signaturen, Duplikaten, Wiederanlauf und Überwachung offener Ereignisse. Legen Sie Betriebsverantwortung und sichere Wiederholungen fest. Bei individueller Anwendungsentwicklung und API-Integration kann Yenwa zunächst ein kritisches Ereignis vom Eingang bis zum Ergebnis im Zielsystem prüfen.
Quellen und weitere Informationen
- Receive Stripe events in your webhook endpoint — Stripe
- Best practices for using webhooks — GitHub
- Idempotent requests — Stripe
- Competing Consumers pattern — Microsoft