UniPay
A fintech payment solution built for students and small businesses.
Overview
UniPay is the project I'm most proud of. It powers a small ledger-based payment flow with idempotency keys, SQL transactions and a strict separation between transport, service and persistence layers. Every endpoint has a clear request/response contract and end-to-end tests.
Highlights
- →Idempotency keys on every mutating endpoint
- →Double-entry ledger with SQL-level constraints
- →Webhook receiver with signature verification and replay protection
- →End-to-end pytest suite covering the happy path and known edge cases
The ledger
Every movement of money is recorded as paired debit and credit entries against accounts. The database enforces that entries always balance, so a malformed payment cannot silently corrupt the books. Reads go through a thin query layer; writes always go through the ledger service.
Idempotency
Clients send an Idempotency-Key header on every payment. The API stores the first response keyed by that header, so retries — whether from a flaky network or a paranoid client — return the original result without double-charging.
Webhooks
Stripe events arrive at a dedicated endpoint that verifies the signature, deduplicates by event ID, and enqueues processing. The ledger only updates once the event has been fully reconciled, which keeps the system honest even when events arrive out of order.
What I would do differently
Next time I would reach for an event-sourced model from day one instead of bolting reconciliation on later. The current system works well, but a true event log would make audits and replays significantly cheaper.
Challenges
- ×Getting idempotency right under concurrent retries
- ×Reconciling Stripe webhook ordering with our internal ledger state
- ×Designing refund flows that never leave money in an inconsistent state