OpenPSP — Payment Orchestrator
Sole architect · AI-assisted implementation · in progress
- Hexagonal architecture with a framework-free domain module and an explicit payment state machine that rejects illegal transitions outright.
- Idempotent payment API — Idempotency-Key plus request hash; a reused key with a different body returns 409. Optimistic locking verified by a concurrent-thread test.
- PSP adapters behind an anti-corruption layer with a circuit breaker and timeouts. Status checks retry with exponential backoff + jitter; authorize is never retried, because a timeout means the outcome is unknown, not failed.
- HMAC-verified callbacks with Redis replay protection, and a scheduled reconciler that asks the PSP about payments stuck in CREATED, PENDING_PSP or AUTHORIZED.
- Transactional outbox to Kafka — idempotent producer, acks=all, payment_id partition key for per-payment ordering.
- Double-entry ledger — append-only journal, balanced-entry invariant, minor-unit amounts, consumer idempotent under redelivery.
- Failure-injection e2e suite (Testcontainers, Toxiproxy, WireMock): PSP timeouts, lost and duplicate callbacks, Kafka outage, killed process. The PSP is simulated; it has not run against a real provider or real traffic.
- The first tickets I wrote by hand; later tickets, diagrams, docs and code comments were written with an AI coding agent (Claude Code) and reviewed by me.