Webhook-Wiederholungsstrategie für Zahlungssysteme
Wie Qvard einen Zahlungs-Webhook wiederholt, was als fehlgeschlagene Zustellung zählt und wie Sie einen Handler bauen, der Wiederholungen, Duplikate und Ausfälle übersteht, ohne eine Bestellung doppelt zu erfüllen.

Ein Zahlungs-Webhook ist eine Nachricht, die nicht verloren gehen und auf die nicht zweimal reagiert werden darf. Netzwerke fallen aus und Server starten neu, also wiederholt der Absender; deshalb muss Ihr Handler im Hinblick auf Wiederholungen geschrieben sein. Dieser Leitfaden beschreibt, wie Qvard wiederholt, was es als Fehler wertet und wie Sie rund um dieses Verhalten einen Handler und eine Wiederherstellungsroutine bauen.
Wann ein Webhook gesendet wird
Qvard sendet den Webhook, wenn eine Zahlung abgeschlossen ist. Es ist ein POST an die in Ihrem Projekt gespeicherte Callback-URL, mit einem kleinen JSON, das Ihre id (die Kennung, die Sie beim Erstellen der Zahlung angegeben haben) und den status enthält, im Header X-Qvard-Signature signiert.
Eine zu kurze, abgelehnte oder noch wartende Zahlung erzeugt keinen Abschluss-Webhook. Wenn Sie von solchen Zahlungen wissen müssen, sehen Sie sie im Konto nach; warten Sie nicht auf eine Nachricht, die nicht gesendet wird.
Was als zugestellt zählt
Qvard wertet eine Zustellung nur dann als erfolgreich, wenn Ihr Endpunkt genau mit HTTP 200 antwortet. Alles andere ist ein Fehler:
- jeder andere Statuscode, einschließlich
201,202,204und aller4xxund5xx; - ein Timeout, weil Ihr Server langsam oder nicht erreichbar war;
- eine Weiterleitung: Qvard folgt
301oder302nicht, eine Regel, diehttpaufhttpsumleitet oder einen abschließenden Schrägstrich anfügt, lässt die Zustellung also fehlschlagen.
Diese Genauigkeit ist gewollt. Ein 204 No Content sieht wie eine völlig gute Antwort aus und ist dennoch eine fehlgeschlagene Zustellung. Liefern Sie 200, gern mit leerem Body.
Wie die Wiederholungen funktionieren
Nach einer fehlgeschlagenen Zustellung versucht Qvard es erneut. Insgesamt gibt es fünf Versuche in rund sechs Minuten. Zwei Folgen:
- Ein kurzer Ausfall ist abgedeckt. Startet Ihr Server neu oder dauert ein Deployment ein bis zwei Minuten, gelingt ein späterer Versuch und Sie verlieren nichts.
- Ein längerer Ausfall nicht. Nach dem letzten Versuch hört Qvard auf. War Ihr Server länger als diese sechs Minuten ausgefallen, kommt die Benachrichtigung nicht von selbst an; senden Sie sie für diese Zahlung aus dem Konto erneut.
Wegen der Wiederholungen sieht Ihr Handler manchmal dasselbe Ereignis mehrfach, etwa wenn Ihr Server die Arbeit erledigt hat, die Antwort aber auf dem Rückweg verloren ging. Das Beispiel unten ist dafür gebaut: Die Aktualisierung ändert nur eine noch nicht bezahlte Bestellung, die Erfüllung wird nur eingereiht, wenn sich eine Zeile geändert hat, und die Antwort ist in beiden Fällen 200.
import os
from fastapi import FastAPI, Request, Response
from qvard import Qvard
app = FastAPI()
SECRET = os.environ["QVARD_SECRET_KEY"]
qvard = Qvard(SECRET)
@app.post("/webhooks/qvard")
async def qvard_webhook(request: Request):
try:
body = qvard.webhooks.construct_event(await request.body(), request.headers.get("X-Qvard-Signature", ""), SECRET)
except ValueError:
return Response(status_code=400)
order_id, status = body.get("id"), body.get("status")
# Idempotent: the UPDATE changes a row only for an order that is not paid yet.
if status == "completed":
changed = await db.execute(
"UPDATE orders SET state = 'paid' WHERE id = :id AND state <> 'paid'", {"id": order_id}
)
if changed:
await queue.enqueue("fulfil", order_id) # slow work after the answer
return Response(status_code=200) # exactly 200, also for repeats and unknown ordersWas Ihr Handler tun muss
Vier Regeln decken fast alle Probleme ab:
- Signatur prüfen. Prüfen Sie den Header
X-Qvard-Signature(HMAC-SHA256 mit Ihrem geheimen Schlüssel über den rohen Body) in konstanter Zeit und antworten Sie sonst mit400. Prüfen Sie ihn, bevor Sie auf die Zahlung reagieren. Siehe Krypto-Zahlungs-Webhooks absichern. - Idempotent sein. Machen Sie die Statusänderung bedingt, „als bezahlt markieren, wenn noch nicht bezahlt“, idealerweise in einer einzigen Datenbankanweisung, damit zwei parallele Zustellungen nicht beide gewinnen.
- Schnell antworten. Prüfen, aktualisieren, einreihen, genau mit 200 antworten. Erledigen Sie E-Mails, Dateierzeugung und Aufrufe anderer Systeme aus einer Queue, damit ein langsamer Dienst nicht zum Timeout des Webhooks wird.
- 200 auf das antworten, was Sie nie bearbeiten werden. Eine unbekannte Bestellung oder eine Wiederholung sollte ebenfalls 200 liefern; sonst wiederholt Qvard weiter eine Nachricht, die Sie schon bearbeitet haben oder nie bearbeiten werden.
Ausfälle, die wie Qvard-Fehler aussehen
Die meisten Meldungen „der Webhook kam nicht an“ haben eine Ursache auf der Empfängerseite:
- Eine Firewall oder ein WAF, die Anfragen unbekannter Adressen blockiert, oder eine „Demnächst“- oder Wartungsseite.
- Eine Weiterleitung von
httpaufhttps, vonwwwauf die nackte Domain oder auf einen abschließenden Schrägstrich. - Ein Framework-Fehler, nachdem die Antwort schon feststand, etwa eine Ausnahme in einer Middleware, die Ihre 200 in eine 500 verwandelt.
- Ein langsamer Handler, der die Arbeit vor der Antwort erledigt und in ein Timeout läuft.
- Ein Cache oder CDN vor der Route.
- Die falsche URL im Projekt oder ein Tippfehler in der Route.
Testen Sie den Endpunkt von außerhalb Ihres Netzwerks mit einer Anfrage, die einen gültigen Header X-Qvard-Signature trägt, und sehen Sie im Zugriffslog Ihres Servers den Antwortcode an, nicht nur, ob die Anfrage ankam.
Eine Wiederherstellungsroutine für verpasste Benachrichtigungen
Wiederholungen decken kurze Ausfälle ab; für den Rest ergänzen Sie ein Sicherheitsnetz.
- Protokollieren Sie jede Zustellung mit
id,status, Ihrer Entscheidung (angewendet, Wiederholung, unbekannte Bestellung, Schlüssel abgelehnt) und der Zeit. Eine fehlende Logzeile ist Ihr Weg, eine Lücke zu bemerken. - Gleichen Sie nach Zeitplan ab. Vergleichen Sie einmal täglich die Bestellungen, die Sie noch als unbezahlt ansehen, mit den Zahlungen und dem Guthaben in Ihrem Qvard-Konto. Alles, was das Konto als abgeschlossen und Sie als unbezahlt zeigen, ist eine verpasste Benachrichtigung.
- Senden Sie aus dem Konto erneut für diese Zahlungen und lassen Sie den idempotenten Handler sie anwenden.
- Alarmieren Sie, wenn eine Serie von Anfragen mit einem Fehler beantwortet wird, damit Sie einen kaputten Endpunkt in Minuten und nicht am Tagesende bemerken.
Der Rest der Integration, einschließlich des Erstellens der Zahlung, steht in Krypto-Zahlungen auf einer Website akzeptieren und Krypto-Zahlungs-API für Entwickler.
FAQ
Wie oft wiederholt Qvard einen Webhook?
Insgesamt fünf Versuche in rund sechs Minuten. Danach hört Qvard auf, und Sie können die Benachrichtigung für die Zahlung aus dem Konto erneut senden.
Welchen Statuscode muss mein Endpunkt zurückgeben?
Genau 200. Jeder andere Status, einschließlich 204, ein Timeout oder eine Weiterleitung zählt als fehlgeschlagene Zustellung und wird wiederholt.
Kann derselbe Webhook zweimal ankommen?
Ja, etwa wenn Ihr Server die erste Zustellung verarbeitet hat, die Antwort aber verloren ging. Machen Sie den Handler idempotent und antworten Sie auch auf Wiederholungen mit 200.
Erhalte ich einen Webhook bei einer zu kurzen oder abgelehnten Zahlung?
Nein. Der Webhook wird gesendet, wenn eine Zahlung abgeschlossen ist. Prüfen Sie andere Zahlungen im Konto.
