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; Rejected400 without calling the bank; Authorized / Declined201 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, 0503) 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 (if SERVER_ADDR is :8090)

The server sets the Swagger host from SERVER_ADDR (e.g. :8090localhost: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).