Section 4: An Authorization Is a Promise, Not Money - Payment & Order Lifecycle Deep Dive
Executive Summary: Section 3 ended with Maya's checkout returning authorized, but no money has moved yet. This section follows ord_7Q2 from that authorization to two per-seller captures at shipment, each of which triggers a ledger split. We model the PaymentIntent as an explicit state machine, defend authorize-at-checkout and capture-at-shipment (D2) along with its fallback when multicapture isn't available, put the authorization's expiry on the calendar, and then spend most of our time on the moment that separates Staff answers from Senior ones: the lamp's $80 capture call times out, and nobody knows whether the money moved.
The interviewer points at the 200 OK on the whiteboard. "Maya got a success screen. Has the marketplace been paid?" No. An authorization is the issuer's promise to hold $120 against Maya's credit line. Money moves only on capture, and in a marketplace selling physical goods, capture waits for something the payment system doesn't control: a seller shipping a box.
The Lifecycle Is a State Machine
You draw the states before any arrows between services, because every bug in this area is an illegal transition: a capture on a voided intent, or a second capture after the final one. Here is the PaymentIntent lifecycle:
Transitions are enforced in the database with a compare-and-set on (payment_id, status), never in application memory. Captures, though, aren't states of the intent. Each seller sub-order gets its own capture record, because one cart produces 1.5 captures on average, each with its own outcome:
CREATE TABLE capture (
capture_id text PRIMARY KEY,
payment_id text NOT NULL, -- pi_7Q2
sub_order_id text NOT NULL UNIQUE, -- one capture per sub-order
seller_id text NOT NULL, -- routes the ledger post to a shard
amount_minor bigint NOT NULL, -- 8000
refunded_minor bigint NOT NULL DEFAULT 0, -- running refund total, capped at amount_minor
psp_key text NOT NULL UNIQUE, -- 'cap:pi_7Q2:1'
psp_ref text UNIQUE, -- PSP capture id, set on confirmation
status text NOT NULL -- pending | unknown | succeeded | failed
);
Two unique constraints carry the invariants: a sub-order can't be captured twice, and a PSP idempotency key can't be reused for different work.
3-D Secure in one paragraph. When the issuer wants strong authentication, the PSP answers the authorization with a challenge. We return requires_action with the PSP's next-action payload, the buyer completes the challenge inside the PSP's SDK, and confirmation resumes. These round trips are part of why the numbers ledger counts 1.25 authorization attempts per order, and why the 1.5 s p99 SLO is measured per API call, not across the minutes a buyer may spend in their banking app.
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson