Payment Domain
Zahlungsabsichten, Autorisierung, Erfassung und Rückerstattung sicher steuern.
1. GeschäftsauftragGrundverständnis
Die Payment Domain kapselt den Umgang mit Zahlungsanbietern. Sie verwaltet Zahlungsabsicht und Status, sorgt für Idempotenz und trennt fachliche Zahlungsergebnisse von anbieterspezifischen Details.
2. Domänenmodell und AggregateDDD
Das zentrale Aggregate heißt Payment. Es schützt Invarianten innerhalb einer Transaktion. Externe Komponenten arbeiten über Commands, Queries und Events, nicht über interne Tabellen.
| Aspekt | Festlegung | Begründung |
|---|---|---|
| Aggregate | Payment | Konsistenzgrenze der Fachregeln |
| Entity-ID | stabil und global eindeutig | ermöglicht Idempotenz und Korrelation |
| Value Objects | fachliche Werte statt primitive Strings | Validierung wird Teil des Modells |
3. ZustandsmodellLifecycle
Nur definierte Übergänge sind erlaubt. Jeder Übergang benötigt einen fachlichen Auslöser, Vorbedingungen, ein Ergebnis und einen nachvollziehbaren Audit-Kontext.
Zahlung ohne globale Transaktion
Eine Zahlung ist wie eine Überweisung mit mehreren beteiligten Stellen: Der Order Service fordert die Zahlung an, der Payment Service verarbeitet sie und meldet das Ergebnis zurück. Jeder Service führt nur seine eigene lokale Transaktion aus.
Alltagstaugliche Ablaufbeschreibung
Dieser Abschnitt beschreibt den Ablauf ohne unnötige Fachsprache. Er dient als Brücke zwischen dem sichtbaren Ergebnis und der technischen Umsetzung.
- Order erstellt Zahlungsauftrag
- Event oder API-Aufruf erreicht Payment
- Payment prüft Idempotency Key
- Provider wird angesprochen
- Ergebnis wird gespeichert
- Payment Event aktualisiert Order.
Fachlicher Ablauf
Ein Kunde möchte eine Bestellung zuverlässig abschließen. Fachlich müssen Preis, Bestand, Zahlung und Bestellstatus zusammenpassen, auch wenn einzelne Schritte zeitversetzt erfolgen oder ein Teilsystem vorübergehend ausfällt.
- Fachliches Ziel: Der Ablauf liefert ein fachlich eindeutiges und für Benutzer beziehungsweise Betrieb nachvollziehbares Ergebnis.
- Verantwortung: Jeder beteiligte Bereich entscheidet nur innerhalb seiner eigenen fachlichen Zuständigkeit.
- Sichtbares Ergebnis: Der Kunde sieht eine eindeutige Bestätigung oder einen nachvollziehbaren Zwischenstatus, niemals eine unklare Doppelbuchung.
Technischer Ablauf
Der Request erreicht das Gateway und den Order Service. Das Aggregate prüft Regeln, PostgreSQL speichert den lokalen Zustand, die Transactional Outbox hält das Event in derselben Transaction fest und Kafka verteilt es an Inventory, Payment und Notification. Correlation IDs verbinden Logs und Traces über alle Stationen.
- Daten und Schnittstellen: Daten werden an jeder Grenze validiert und nur über definierte APIs, Ports oder Events weitergegeben.
- Fehlerbehandlung: Fehler werden dort behandelt, wo ausreichender Kontext und Verantwortung vorhanden sind; Wiederholungen müssen sicher und nachvollziehbar bleiben.
- Technischer Nachweis: Geprüft werden Idempotency Key, Transaction Boundary, Outbox-Verarbeitung, Event-Status und End-to-End-Trace.
Zusammenspiel: Der fachliche Ablauf erklärt, warum etwas geschieht und welches Ergebnis zählt. Der technische Ablauf erklärt, wie dieses Ergebnis zuverlässig, sicher und beobachtbar umgesetzt wird.
4. Use CasesAnwendung
- InitiatePayment: eigener Application Use Case mit Autorisierung, Validierung und idempotentem Ergebnis.
- AuthorizePayment: eigener Application Use Case mit Autorisierung, Validierung und idempotentem Ergebnis.
- CapturePayment: eigener Application Use Case mit Autorisierung, Validierung und idempotentem Ergebnis.
- RefundPayment: eigener Application Use Case mit Autorisierung, Validierung und idempotentem Ergebnis.
Use Cases orchestrieren das Aggregate und Ports. Sie enthalten keine HTTP-, SQL- oder Kafka-Details.
5. API-VertragIntegration
POST /api/payments
GET /api/payments/{paymentId}
POST /api/payments/{id}/capture
POST /api/payments/{id}/refund6. Event ContractsMessaging
PaymentAuthorized– unveränderliches vergangenes Ereignis mit eventId, occurredAt, aggregateId, schemaVersion und correlationId.PaymentDeclined– unveränderliches vergangenes Ereignis mit eventId, occurredAt, aggregateId, schemaVersion und correlationId.PaymentCaptured– unveränderliches vergangenes Ereignis mit eventId, occurredAt, aggregateId, schemaVersion und correlationId.PaymentRefunded– unveränderliches vergangenes Ereignis mit eventId, occurredAt, aggregateId, schemaVersion und correlationId.
Events werden versioniert. Consumer müssen doppelte Zustellung tolerieren und unbekannte optionale Felder ignorieren.
7. Datenverantwortung und KonsistenzDaten
Eigene Daten: Zahlungsreferenz, Betrag, Währung, Status, Provider-Referenz und Idempotency Key. Keine vollständigen Kartendaten.
Andere Domänen erhalten benötigte Informationen über API oder Event. Gemeinsame Tabellen und domänenübergreifende SQL-Joins werden vermieden. Für verteilte Abläufe gilt meist Eventual Consistency; der aktuelle Prozessstatus wird explizit sichtbar gemacht.
8. Sicherheit und DatenschutzSecurity
PCI-relevante Daten bleiben beim Zahlungsanbieter. Secrets werden kurzlebig verwaltet. Jeder statusändernde Aufruf verlangt Idempotency Key, starke Service-Authentisierung und Auditierung.
- Least Privilege für Benutzer und Services.
- Auditierbare Statusänderungen.
- Minimierung personenbezogener Daten.
- Secrets nie in Code, Events oder Logs.
9. SLOs und BetriebszieleSRE
99,9 % korrekte Verarbeitung autorisierter Zahlungen; p95 Provider-unabhängig unter 2 s; 100 % idempotente Wiederholung.
| Signal | Messung | Reaktion |
|---|---|---|
| Erfolg | fachlich erfolgreiche Use Cases | Error Budget und Release-Risiko bewerten |
| Latenz | p50/p95/p99 pro Use Case | Abhängigkeit und Warteschlange lokalisieren |
| Korrektheit | Invarianten und Reconciliation | Geschäftsschaden begrenzen |
10. Typische FehlerbilderTroubleshooting
- Provider antwortet nach Timeout doch erfolgreich
- doppelte Abbuchung durch Retry
- Webhook kommt vor API-Antwort
- Refund wird mehrfach ausgelöst
11. DiagnosewegBetrieb
- Betroffene Bestellung oder fachliche ID bestimmen.
- Correlation-ID über API, Event und Datenzustand verfolgen.
- Erwarteten und tatsächlichen Status vergleichen.
- Letzte erfolgreiche Transition und fehlgeschlagenen Schritt identifizieren.
- Idempotente, reversible Wiederherstellung wählen.
- Nach der Behebung Reconciliation und Benutzerwirkung prüfen.
12. Lernkontrolle und eigene NotizenSelbsttest
Erkläre die Verantwortung der Payment Domain ohne technische Produktnamen. Benenne zwei Invarianten, einen erlaubten Zustandsübergang und ein SLO.
Zahlung: vollständiger Zusammenhang
Payment trennt Autorisierung, Erfassung, Ablehnung und Rückerstattung. Geldbewegungen benötigen besonders starke Idempotenz, Auditierbarkeit und Schutz sensibler Daten. CommerceOne speichert keine vollständigen Kartendaten.
Wie funktioniert der Ablauf?Funktionsweise
Die Zahlung-Domäne verarbeitet Befehle ausschließlich über ihre Anwendungsgrenze. Das Aggregat prüft Invarianten und erzeugt Events. Persistenz und Messaging sind Adapter. Andere Domänen kommunizieren über dokumentierte APIs oder Events und greifen nicht direkt auf interne Tabellen zu.
Konkretes CommerceOne-BeispielPraxis
Nach erfolgreicher Bestandsreservierung autorisiert Payment den Betrag beim Provider. Ein Timeout bedeutet nicht automatisch Ablehnung: Der Status muss über eine Provider-Referenz geklärt werden, bevor erneut belastet wird.
POST /payment-authorizations
Idempotency-Key: order-4711
{ "orderId":"4711", "amount":{"value":"49.90","currency":"EUR"} }So liest du das Beispiel: Identitäten und Zustände werden ausdrücklich benannt. Wiederholung, Teilfehler und Beobachtbarkeit sind Teil des Designs. Das Beispiel ist zum Lesen und Anpassen gedacht; es wird nichts automatisch ausgeführt.
Entscheidungs- und DiagnosefragenReflexion
- Welches fachliche Ergebnis soll für den Benutzer entstehen?
- Welche Komponente besitzt die Verantwortung und welche Daten gehören ihr?
- Was passiert bei Timeout, Wiederholung oder Teilausfall?
- Welches Signal beweist, dass der Ablauf korrekt funktioniert?
- Welche einfachere Alternative wäre ausreichend?