What an interviewer expects you to nail down before drawing a single box.
POST /v1/payments { buyer, checkout_id, payment_orders[], idempotency_key } → { payment_id, status }GET /v1/payments/{id} → { status }POST /v1/refunds { payment_order_id, amount? } → { refund_id, status }(internal) reconcile(settlement_file) → { matched, mismatches[] }You click 'Pay' on a checkout page, the page hangs, and you panic for a second: did it go through, and if I click again, will I be charged twice? A payment system's entire reason for existing is to make sure the answer to that second question is always no. Of all the systems people study, this is the one where being merely 'mostly correct' is unacceptable, because every mistake is somebody's real money.
Here is the whole thing in plain terms. After a customer places an order, the e-commerce backend sends a payment event to the Payment Service. The payment service runs a risk check, then breaks the event into one or more payment orders and hands each to the Payment Executor. The executor talks to a Payment Service Provider (PSP) such as Stripe or Adyen, and the PSP is the one that actually moves money by talking to the card schemes, Visa and Mastercard. Most companies do not connect to the card schemes directly. They let a PSP handle the cardholder data and the rails.
When a payment succeeds, two internal books are updated. The Wallet records how much each seller is owed, and the Ledger records every movement using double-entry bookkeeping, so debits always equal credits. If those two sides ever disagree, that is a bug, not a missing dollar.
The idempotency key is the idea worth getting straight, and a coat check makes it concrete. When you hand over your coat you get a numbered ticket. Show that same ticket twice and you get the same coat back, not a second one. Exactly-once is just two simpler guarantees stacked together: at-least-once, because the executor retries failed calls, and at-most-once, because the idempotency key (passed all the way to the PSP) makes a retry return the original result instead of charging again. Retries that keep failing land in a dead letter queue for a human to look at.
The last line of defense is reconciliation. Every night the PSP and the banks send a settlement file listing what actually cleared. A reconciliation job compares that file against the ledger and flags any mismatch, because asynchronous systems drift and you cannot assume your own records are right. This system teaches the payment-service-and-executor split, why a PSP sits between you and the card schemes, double-entry ledgers and wallets, idempotency for exactly-once side effects, and reconciliation as the safety net under all of it.