Notification Handling - Best Practices

  • Aktualisiert

Notifications (Callbacks) sind das zentrale Steuerungselement im Zahlungsprozess von collana pay. Für jeden API-Request sendet collana pay asynchron eine Notification an die vom integrierenden System hinterlegte Callback-URL mit dem Ergebnis der Interaktion und der Angabe, welche Aktion als nächstes erwartet wird. Das integrierende System muss diese Notifications korrekt empfangen, verarbeiten und darauf reagieren.

Zu einer einzelnen Interaktion können mehrere Notifications eintreffen, dies ist jedoch nicht zwingend der Fall und hängt vom PSP sowie der Zahlungsform ab. Typisch sind mehrere Notifications bei Interaktionen, die eine Kundeninteraktion erfordern (z. B. Prepare mit iFrame oder Weiterleitung). In solchen Fällen folgen auf eine oder mehrere Pending-Notifications abschließend eine Successful- oder Failed-Notification. Das integrierende System muss daher alle eingehenden Notifications auswerten und darf nicht davon ausgehen, dass eine Interaktion mit einer einzigen Notification abgeschlossen ist.

Das grundlegende Kommunikationsmuster (Request → synchrone Bestätigung → Notification) und die Status-Übersicht sind in diesem Artikel beschrieben. Der aktuelle Artikel geht tiefer in die Implementierungsdetails.

Aufbau einer Notification

Jede Notification ist ein POST-Request, den collana pay an die Callback-URL des integrierenden Systems sendet. Der Body ist ein JSON-Objekt. Die folgende Tabelle beschreibt die Felder, die für das Notification-Handling relevant sind. Eine vollständige Feldbeschreibung findet sich in der API-Dokumentation.

Feld Typ Beschreibung
transactionId GUID Eindeutiger Bezeichner der Transaktion. Grundlage für die Zuordnung aller eingehenden Notifications.
interactionId GUID Eindeutiger Bezeichner dieser konkreten Interaktion. Basis für idempotente Verarbeitung.
status string Ergebnis der Interaktion. Mögliche Werte: Successful, Pending, FailedFinal, FailRetryable.
statusDetails string Ergänzende Statusinformation als Text (z. B. "CreateInteraction; Successful; AfterPayV1; Invoice"). Enthält Interaktionstyp, Status sowie ggf. PSP- und Zahlartinformation.
endpointType string Gibt an, welcher Prozessschritt die Notification ausgelöst hat (z. B. Transactions, Prepares). Primäre Grundlage für das Routing.
continuationAllowed boolean true, wenn der nächste Prozessschritt angestoßen werden kann; false, wenn collana pay noch auf eine PSP-Antwort wartet oder eine Kundeninteraktion aussteht.
merchantReference string Die vom integrierenden System übergebene eigene Referenz (z. B. Bestellnummer). Wird unverändert zurückgegeben.
transactionPassThroughValue string Frei definierbares Feld auf Transaktionsebene. Wird unverändert zurückgegeben.
interactionPassThroughValue string Frei definierbares Feld auf Interaktionsebene. Wird unverändert zurückgegeben.
interactionReference string Referenz auf eine vorherige Interaktion innerhalb der Transaktion (z. B. die zugehörige Create-Interaktion).
redirectUri string / null URL, zu der der Kunde bei Status Pending weitergeleitet werden soll.
embedmentUri string / null URL zu einem iFrame für die Zahlungsdateneingabe direkt auf der Shop-Seite.
scriptSrcUri string / null URL zu einem JavaScript, das einen Payment-Button rendert (bei Buttonzahlarten).
scriptTagId string / null ID des HTML-<script>-Tags, mit dem das Script aus scriptSrcUri eingebunden wird.
pspInteractionStatus string Interner Status der Interaktion beim PSP. Ergänzende Information, nicht für die primäre Ablaufsteuerung verwenden.
pspNotificationStatus string Interner Status der PSP-Benachrichtigung. Ergänzende Information.
userInteractionStatus string Interner Status der Nutzerinteraktion. Ergänzende Information.

EndpointType: Welcher Prozessschritt hat geantwortet?

Das Feld endpointType gibt an, welcher API-Endpunkt die Notification ausgelöst hat. Es ermöglicht dem integrierenden System, eingehende Notifications dem entsprechenden Prozessschritt zuzuordnen:

EndpointType Prozessschritt Folgeaktion bei Successful
Transactions Create: Transaktion angelegt Prepare anstoßen
Prepares Prepare: Zahlung vorbereitet Reserve anstoßen (oder auf Kundeninteraktion warten)
Reservations Reserve: Betrag reserviert Bestellung im Shop anlegen und ans ERP übergeben; Capture durch ERP nach Lieferung
Captures Capture: Betrag eingezogen Keine weitere Pflichtaktion
Refunds Refund: Betrag erstattet Keine weitere Pflichtaktion
Reversals Reversal: Reservierung aufgehoben Keine weitere Pflichtaktion
Cancels Cancel: Transaktion abgebrochen Keine weitere Pflichtaktion
Das endpointType-Feld ist die primäre Grundlage für das Routing eingehender Notifications. Es ist zuverlässiger als das Parsen des statusDetails-Texts, der sich in Zukunft ändern kann.

Best Practices

Statusabhängige Verarbeitung

Successful

Die Interaktion wurde erfolgreich abgeschlossen. Das integrierende System sollte:

  1. Den lokalen Transaktionsstatus aktualisieren.
  2. Prüfen, ob continuationAllowed den Wert true hat.
  3. Den nächsten Prozessschritt gemäß endpointType anstoßen.

FailedFinal und FailRetryable

Die Interaktion ist fehlgeschlagen. Zu unterscheiden sind:

  • FailedFinal: Die Interaktion ist endgültig fehlgeschlagen. Die Transaktion kann nicht fortgesetzt werden. Typische Reaktion: Zahlung abbrechen, Kunden informieren, ggf. neue Transaktion starten.
  • FailRetryable: Die Interaktion ist fehlgeschlagen, die Transaktion kann jedoch fortgesetzt werden, indem dieselbe Interaktion wiederholt wird. Die Verfügbarkeit dieses Status hängt vom PSP und der Zahlart ab.

In beiden Fällen empfiehlt sich:

  • Fehler lokal protokollieren (Logging mit transactionId, interactionId, statusDetails).
  • Keine automatischen Retries ohne vorherige Statusprüfung der Transaktion.

Pending

Die Interaktion ist noch nicht abgeschlossen. Das Verhalten hängt davon ab, welches Feld befüllt ist:

Befülltes Feld Aktion
redirectUri Kunden zur angegebenen URL weiterleiten
embedmentUri URL in einem iFrame auf der Shop-Seite anzeigen
scriptSrcUri + scriptTagId JavaScript laden und in ein <script>-Tag mit der ID aus scriptTagId einbinden
Keines der obigen Auf eine weitere Notification warten
Die Felder pspInteractionStatus und userInteractionStatus können den Wert Pending tragen, ohne dass tatsächlich eine Nutzerinteraktion erforderlich ist. Diese Felder sind interne Statusindikatoren und sollten nicht als primäre Grundlage für die Ablaufsteuerung verwendet werden. Maßgeblich sind status und die URI-Felder (redirectUri, embedmentUri, scriptSrcUri).
Wichtig: Eine Interaktion kann mehrere Notifications mit Status Pending auslösen. Beispiel: Beim Prepare-Schritt beispielsweise trifft zunächst eine Notification mit Pending und einer embedmentUri ein (Aufforderung zur Zahlungsdateneingabe im iFrame). Nach erfolgreicher Eingabe durch den Kunden folgt eine weitere Pending-Notification ohne URI (Nutzerinteraktion abgeschlossen, collana pay wartet auf PSP). Erst danach kommt die abschließende Successful-Notification. Das integrierende System muss daher alle Pending-Notifications auswerten und darf erst bei Successful mit dem nächsten Prozessschritt fortfahren.

Reihenfolge von Notifications

Notifications treffen nicht zwingend in der Reihenfolge ein, in der die entsprechenden Interaktionen angestoßen wurden. Das integrierende System sollte:

  • Jede Notification anhand der transactionId dem lokalen Transaktionsdatensatz zuordnen.
  • Den eigenen Transaktionsstatus zustandsbasiert führen, d. h. auf Basis aller bisher eingegangenen Notifications, nicht auf Basis einer erwarteten Reihenfolge.
  • Notifications idempotent verarbeiten: Eine erneut eingegangene Notification für dieselbe interactionId darf keine doppelten Aktionen auslösen.

Timeout-Handling

Falls eine erwartete Notification über einen längeren Zeitraum ausbleibt:

  1. Transaktionsstatus aktiv abfragen: Der aktuelle Status einer Transaktion kann jederzeit über den collana pay Status-Endpunkt abgefragt werden. Dies ermöglicht eine aktive Prüfung ohne Abhängigkeit von der Notification-Zustellung.
  2. Dead-Letter-Queue prüfen: Notifications, die collana pay nicht erfolgreich zustellen konnte, landen in der Dead-Letter-Queue. Diese kann über copal oder den /deadletters-API-Endpunkt eingesehen und die Nachrichten erneut verarbeitet werden.
  3. Kein unbegrenztes Warten: Nach einer definierten Wartezeit den Status aktiv abfragen und entsprechend reagieren, anstatt unbegrenzt auf eine Notification zu warten.

Sicherheit

Die Callback-URL ist ein öffentlich erreichbarer Endpunkt und muss gegen unberechtigte Aufrufe abgesichert werden:

  • HTTPS: Die Callback-URL muss zwingend über HTTPS erreichbar sein.
  • Authentifizierungsheader: Beim API-Request an collana pay kann im Callback-Objekt ein oder mehrere benutzerdefinierte HTTP-Header (Name + Value) konfiguriert werden. collana pay sendet diese Header bei jeder Notification mit. Der empfangende Endpunkt sollte das Vorhandensein und den korrekten Wert dieses Headers validieren (z. B. ein gemeinsames Secret-Token).
  • Transaktionsvalidierung: Die transactionId aus der Notification muss gegen eine im eigenen System bekannte Transaktion validiert werden. Notifications für unbekannte Transaktions-IDs sollten verworfen werden.
  • Serverseitige Verarbeitung: Die Verarbeitung von Notifications muss ausschließlich serverseitig erfolgen. Clientseitige Daten (Browser, Frontend) dürfen nicht als Grundlage für Zahlungsstatusänderungen dienen.

Verknüpfung mit