Payment Guard
SNAP-compliant payment aggregator with a real-time fraud/AML rule engine: double-entry ledger, HMAC-signed webhook delivery with automatic retry, Kafka event streaming, and Prometheus observability, all verified end-to-end against a real Postgres and Kafka broker.
Overview
Payment Guard is a payment aggregator built around Bank Indonesia's SNAP (Standar Nasional Open API Pembayaran) specification, the standard every Indonesian payment service provider has to speak. Incoming payments are checked against a real-time fraud and AML rule engine (velocity checks, merchant blacklist, large-amount thresholds) before a double-entry ledger ever gets touched. Every state change publishes a Kafka event, which fans out to merchant webhooks with HMAC-SHA256 signatures and automatic retry with backoff. A daily reconciliation job checks the ledger's own DEBIT/CREDIT invariant, and Prometheus metrics plus Swagger-documented endpoints round out the operational side.
The Challenge
- The hard part was not any single feature, it was making the money-moving logic provably correct while keeping every technical decision honest.
- The ledger has to stay balanced under concurrent requests, a flagged transaction must never settle without a human decision, an event published to Kafka must never roll back a financial decision that already happened, and a webhook retry must be safely dedupable by the merchant.
- All of that had to be verified by actually running the system end-to-end with a real Postgres and a real Kafka broker, not just by reading the code back.
The Solution
- Built as a four-module hexagonal architecture (domain, application, infrastructure, api) so the fraud rules and ledger math stay pure Java with zero framework dependency and can be unit tested without a database.
- SNAP's RSA signature scheme is verified against a real generated keypair, including a genuine tamper test where a body signed for one payload is rejected when swapped for another.
- Kafka runs natively in KRaft mode for local development, feeding a webhook dispatcher (HMAC-signed, exponential backoff, delivery-id idempotency).
- Every layer has its own test strategy: JUnit and Mockito for business logic, real Postgres integration tests for the repository adapters (which is how a ledger foreign-key ordering bug was actually caught), and a seed script that drives the real REST API to produce a demoable dataset.