This document satisfies the Checkout.com offline assessment request to capture key design considerations and assumptions.
API surface
POST /api/payments— merchants submit card data to process a payment.GET /api/payments/:id— merchants retrieve a previously stored payment by UUID.
Paths follow the public payment-gateway-challenge-go template convention (/api/payments).
Status model
| Status | When |
|---|---|
Rejected |
Validation failed before calling the bank (HTTP 400). No database row is created. |
Authorized |
Bank returned HTTP 200 with "authorized": true. Row persisted (HTTP 201). |
Declined |
Bank returned HTTP 200 with "authorized": false. Row persisted (HTTP 201). |
If the simulator returns 503 (PAN ending in 0), the gateway returns 503 to the merchant and does not persist a payment (no definitive auth outcome).
PCI / data minimisation
- Full PAN and CVV exist only in memory for the lifetime of a single request.
- PostgreSQL stores last four digits and original PAN length so we can render a mask like
************8877without storing the full number. - We never log raw card numbers or CVVs.
Card expiry validation
The brief requires the expiry month/year combination to remain valid. We treat a card as valid through the end of the printed expiry month (common card-network interpretation), implemented with time.Date(y, m+1, 0, …) in UTC.
Currencies
The assessment allows at most three ISO 4217 codes. Default: USD, GBP, EUR, overridable via ALLOWED_CURRENCIES (comma-separated).
Bank simulator contract
Mountebank expects:
card_number,expiry_dateasMM/YYYY,currency,amount,cvv- Odd last digit → authorised; even → declined;
0→ HTTP 503
The gateway maps merchant JSON (expiry_month + expiry_year) into expiry_date.
Swagger / OpenAPI
- Uses swag (
github.com/swaggo/swag) annotations oncmd/server/main.goand handlers, same pattern as Checkout’s official payment-gateway-challenge-go template. - echo-swagger serves UI at
/swagger/*. - Regenerate after annotation changes:
make swagger(requiresswagCLI).
Technology choices
- Echo — lightweight HTTP router as requested.
- PostgreSQL + GORM — durable storage (the original brief allows an in-memory test double; we use Postgres as requested).
- Automated tests — validation unit tests + handler test with
httptestbank stub (no Docker required forgo test).
Out of scope (deliberately)
- Merchant authentication / API keys
- Idempotency keys & double-submit protection
- Rate limiting, circuit breaking beyond basic HTTP client timeout
- 3DS / SCA flows