Implementation of the Checkout.com offline payment-gateway assessment, using Go, Echo, PostgreSQL, and the official Mountebank bank simulator from the reference repo.
Requirements implemented
| Merchant capability | Endpoint | Notes |
|---|---|---|
| Process a payment | POST /api/payments |
Validates input; Rejected → 400 without calling the bank; Authorized / Declined → 201 after bank call; persists outcome. |
| Retrieve a payment | GET /api/payments/:id |
Returns Authorized / Declined, amount, currency, expiry, last four, masked PAN. |
Bank behaviour (odd/even last digit, 0 → 503) matches the organisation README.
Quick start
1. Start Postgres + bank simulator
cd payment-gateway-challenge
docker compose up -d
2. Configure environment
cp .env.example .env
# defaults assume postgres on localhost:5433 and bank on :8080
3. Run the API
go run ./cmd/server
GET http://127.0.0.1:8090/ping- Gateway listens on
SERVER_ADDR(default:8090).
Swagger (OpenAPI) — same idea as the official Go template
After changing any // @... comments in cmd/server/ or internal/handlers/, regenerate docs:
go install github.com/swaggo/swag/cmd/swag@latest
make swagger
Then open Swagger UI (while the server is running):
http://127.0.0.1:8090/swagger/index.html(ifSERVER_ADDRis:8090)
The server sets the Swagger host from SERVER_ADDR (e.g. :8090 → localhost:8090) so Try it out targets the correct port.
4. Example: process then fetch
# Authorised test PAN (ends in 7) from the brief
curl -sS -X POST http://127.0.0.1:8090/api/payments \
-H 'Content-Type: application/json' \
-d '{
"card_number":"2222405343248877",
"expiry_month":4,
"expiry_year":2028,
"currency":"GBP",
"amount":100,
"cvv":"123"
}'
# Use the returned "id"
curl -sS http://127.0.0.1:8090/api/payments/<id>
Project layout
payment-gateway-challenge/
├── cmd/server/main.go # @title / @host + sets docs.SwaggerInfo.Host at runtime
├── docs/ # generated by `make swagger` (docs.go, swagger.json, swagger.yaml)
├── internal/
│ ├── bank/ # HTTP client for Mountebank
│ ├── config/
│ ├── database/ # GORM + Postgres
│ ├── domain/ # status constants
│ ├── handlers/ # Echo handlers + tests
│ ├── models/
│ ├── repository/
│ ├── router/
│ └── validation/ # field rules + tests
├── imposters/ # official bank_simulator.ejs (do not modify per brief)
├── scripts/create_tables.sql
├── docker-compose.yml
├── DESIGN.md # design notes for reviewers
└── README.md
Tests
go test ./...
SQL
Optional explicit DDL: scripts/create_tables.sql (the app also AutoMigrates on startup).
Do not
Open pull requests against Checkout.com’s cko-recruitment repositories (per their instructions).