Payment Checkout & Ledger Service  ·  View 04 of 24  ·  People and journeys

Journey — The Buyer Pays

Six phases, three of which cannot be recovered in the same session, and one trough that is the architecture.

Editable source SVG draw.io All views
Buyer at checkout mobile web, patchy network Goal — Pay once and be told it worked Trigger — Pressing Pay now on a basket they already decided to buy Done when — An order confirmation, and exactly one line on their bank statement 1 · Press Pay intent created 2 · Choose how card or UPI 3 · Prove it is them ◆ moment of truth 4 · Wait for the rail ◆ moment of truth 5 · See the outcome ◆ moment of truth 6 · Ask for it back days later What they do Taps Pay now Picks a method Enters details Approves in bank app Waits on a spinner Reads the result Requests a refund What the platform does Create intent Idempotency key Tokenise card Route to provider Step-up orchestration 8 s provider deadline Poll on unknown Post to ledger Webhook merchant Refund object How it feels Confident Fine Anxious Where it hurts Redirect loses the basket Spinner with no deadline Double tap on timeout "Pending" means nothing Refund invisible for days What answers it Server-created intent No card data on merchant Intent survives redirect Idempotency key on retap Honest processing state Refund shown pending Journey — The Buyer Pays The trough is the unknown outcome: the rail has not answered, and the buyer's instinct is to press again. Views 13, 14 and 23 answer it. v 1.0 · owner Payments Platform Architecture · date 2026-10

The trough

  • The sentiment line bottoms at 'See the outcome' because the phase before it is a spinner with no deadline, and a buyer's response to a spinner is to press again.
  • That is not a UX complaint. It is the unknown provider outcome (view 14), and it is why `processing` is a first-class state and the idempotency key is at the API edge (ADR-03, ADR-04).

What answers each phase

  • Press Pay → server-created intent, so the amount is never client-controlled.
  • Prove it is them → the intent survives the redirect, because state lives on the server and not in the session.
  • Wait → an 8-second hard deadline and an honest `processing`, rather than an optimistic success.
  • Ask for it back → a refund object with its own pending state, shown as pending.

Assumptions

  • A few unknown outcomes per thousand attempts, concentrated in one rail.
  • Double-charge tolerance ≤ 1 per 1,000,000 attempts — the number that makes 'never retry after unknown' non-negotiable.