The challenge
Payment code has to survive the messy parts of real life: customers closing the tab before the redirect returns, gateways sending the same webhook twice, callbacks arriving before your own page loads, and attackers forging a success notification.
The goal was zero-drop verification, no double-charge or double-credit, and the ability to answer 'what happened to this payment?' from the logs.
How I approached it
- 01
Signed requests and verified responses
API requests are authenticated and signed, and every response or callback is checksum-verified (SHA256 / HMAC) before an order or wallet is updated. A success flag from the browser is never trusted on its own.
- 02
Idempotent webhook handlers
Webhook endpoints check for duplicates, so a gateway retrying the same notification can't mark an order paid twice or credit a wallet twice.
- 03
Fallback verification
If the customer never returns from the gateway redirect, a fallback routine checks payment status with the gateway directly, catching edge-case drop-offs.
- 04
Full transaction audit trail
Each payment lifecycle is logged. No raw card data is stored: the gateway handles card details and the application keeps only references and statuses.
What I built
- Implemented API authentication, request signing and response checksum validation.
- Built secure webhook endpoint handlers with duplicate-request idempotency checks.
- Built fallback verification routines for drop-offs during gateway redirects.
- Kept strict security practice: no raw card credentials stored, full transaction logs maintained.
What this project demonstrates
- Treating every callback as untrusted until verified
- Idempotency as a default, not an afterthought
- Debugging payment flows end to end from logs