Templates
Types
EN

Payment Flow Diagram Guide

How to draw a payment flow diagram that survives contact with production — where the money actually moves, why the redirect back is not the answer, and three editable examples.

Published on ·9 min read
paymentscheckoutsequence-diagramtemplate

What is a payment flow diagram?

A payment flow diagram shows how one order turns into money in your account — and, more usefully, every point on the way where it stops being a straight line.

Most people draw this diagram once, get five boxes, and conclude it was not worth drawing: the customer pays, the provider approves, the order ships. That version is not wrong so much as it is a description of the two percent of the flow that never causes an incident. What causes incidents is that a payment is not one event. It is at least two — authorization, where the issuer agrees to hold the money, and capture, where the money actually moves — and they can be days apart. In between, the customer's bank may put a challenge screen in front of them, on a page you do not control, from which they may simply never return.

The other thing the five-box version hides is that "paid" is not the end. Money moves backwards, and it does so on a timescale set by card networks rather than by you: a refund next week, a partial refund when one item comes back, a chargeback filed up to 120 days after the sale. A payment state machine that ends at Paid is a state machine that will be edited under pressure, in production, by whoever is on call.

So the honest subject of this diagram is not the checkout. It is the gap between "the customer thinks they paid" and "we know we were paid" — and everything that can happen inside it.

What a payment flow diagram has to show

Six things. Miss the second one and the diagram will describe a system you do not have.

  • Authorization and capture as two separate steps. Even if you capture immediately, draw both — because the day someone asks "can we only charge when it ships?", the answer is a change to one arrow rather than a redesign. Label what each one means in plain words: authorization is a hold with an expiry, capture is the transfer. An authorization that is never captured does not fail loudly; it lapses after about a week, silently.
  • Where the result actually arrives. The browser coming back to your return page means the customer's session ended, nothing more. The authoritative answer arrives out-of-band from the provider, asynchronously, and it arrives whether or not the customer's browser survived. Draw both arrows, and mark which one you are allowed to believe. Treating the redirect as the answer is the single most common way a checkout ships with a hole in it.
  • The step that leaves your process. 3-D Secure, a bank app switch, a wallet sheet — the customer goes somewhere you do not own and may not come back. Draw it as a branch with three outcomes, not two: approved, rejected, and abandoned. The third one has no arrow pointing back at you at all, which is exactly why it needs to be on the page.
  • One idempotency key, chosen from something stable. A double-clicked button, a retried request and a refreshed tab are all the same charge to your customer and three charges to their card. The key has to come from the order, not from a timestamp or a random value generated per attempt — a key that changes on retry is not a key. Draw where it is created, and it will be obvious whether it survives a retry.
  • Everything after "paid". Full refund, partial refund, dispute, chargeback, and the chargeback you win. This is where the money goes backwards, and it is the half of the state machine that gets left out because nobody is thinking about it during checkout week. A useful test: if your diagram has no state a payment can enter three months after the sale, it is missing one.
  • The amount, at each point it can differ. Authorized, captured, refunded and settled are four numbers, and they are not always the same one. Partial capture, partial refund, currency conversion and provider fees each pull them apart. You do not need all of this on the main diagram, but you do need to know which number your orders.total column is holding — and the diagram is where that question gets asked out loud.

Here is the skeleton almost everyone draws first, and it contains the bug. Every arrow is individually correct. The problem is that the whole thing is one synchronous request: the order is marked paid inside the same call that charged the card.

That shape only describes a payment where the issuer approves instantly with no challenge and nothing goes wrong on the way back — a minority of real outcomes, and in Europe not even a legal default for most transactions. It has no place to put a bank challenge screen, and nowhere for an answer that arrives four seconds after the customer closed the tab.

View the Mermaid source
sequenceDiagram
    participant U as Customer
    participant App as Your App
    participant PSP as Payment Provider

    U->>App: submit the payment form
    App->>PSP: charge the card
    PSP-->>App: approved
    App->>App: mark the order as paid
    App-->>U: redirect to the success page
A minimal payment flow diagram where the app charges the card and marks the order paid inside a single synchronous request.

How to draw a payment flow diagram

Three steps. The first one decides what the diagram is about, and it is easy to get wrong in a way that feels productive.

Step 1 · Draw the money, not the screens

The tempting first move is to walk through the checkout as a user sees it: cart, address, payment method, review, confirm. Four of those five screens have nothing to do with whether you get paid, and putting them on the diagram pushes the part that matters into a corner.

Pick participants by a single test: can this box hold the money, or refuse to release it? For a card payment that gives you the customer, your application, your payment provider, and the issuing bank. The bank is the one people leave out, and it is the one that says no, asks for a challenge, or reverses the transfer three months later. Without it on the page, every decline is an unexplained arrow coming out of the provider.

Everything upstream of the payment method — cart, shipping, tax — belongs on a different diagram, if it belongs on one at all. This diagram starts at the moment an amount is fixed and someone is about to be charged it.

Step 2 · Mark the arrow you are allowed to believe

On the finished diagram there will be two arrows that both look like "the payment succeeded". One is the customer's browser landing on your return page. The other is the provider telling your server, out of band, that the intent succeeded. Only the second one is evidence. Mark it on the diagram, in words, so that nobody has to work it out from the arrow directions.

The reason is not subtlety, it is that the browser is not a participant in the payment. It is a bystander that happened to be present for part of it. It can be closed at the challenge screen, lose signal in a lift, be a mobile app that was killed by the OS, or arrive at your return page having been given the URL by someone who never paid at all. In every one of those cases the money still moved, and the only thing that knows it is the provider's asynchronous message.

The practical consequence is a shape most first drafts do not have: the return page reads current state and says "we are confirming your payment" if it does not yet see a result, while fulfilment hangs off the out-of-band message. Those are two arrows on the diagram and about fifteen lines of code, and the version without them fails in the way that is hardest to reproduce and most expensive to discover — money taken, order never created, and nobody knows until the customer writes in.

That out-of-band message is a webhook, so the usual rules apply to it — verify the signature on the raw body, deduplicate on the event id, acknowledge before doing the work. On this diagram it is one arrow; its internals are a diagram of their own, linked at the bottom of this page.

Step 3 · Draw it

Describe it in sentences and let text2diagram lay it out — "the customer places an order, we create a payment intent with the order id as the idempotency key, the customer enters card details with the provider, the issuing bank may ask for a 3-D Secure challenge, then the provider notifies our server and we mark the order paid" comes back as an editable sequenceDiagram with the branch already nested.

Or open one of the three below and change the participant names. The branch structure is the part worth keeping.

Payment flow diagram examples

Three diagrams: one checkout drawn correctly, the whole life of a payment including the parts that happen months later, and the decision tree for a charge that did not go through.

1 · Card checkout, with the challenge and the confirmation in the right places

The Note at the bottom is the whole point of the diagram. Two arrows arrive near the end and both look like success; only one of them is one.

Three details are worth copying exactly. The idempotency key is the order id, created before anything is sent — so a double-click, a retried request and a refreshed tab all resolve to the same intent instead of three charges. A key generated per attempt would look identical on the diagram and protect against nothing.

The card details go from the customer straight to the provider and never touch your server, which is what keeps your compliance scope small. On the diagram this is visible as an arrow that skips a participant, and it is worth drawing precisely because the wrong version — details posted to your backend, forwarded on — also looks perfectly reasonable as a sequence.

And the order is marked paid on the arrow from the provider to your server, not on the redirect above it. Those two arrows are the difference between a checkout that survives a closed tab and one that quietly loses orders it was paid for.

View the Mermaid source
sequenceDiagram
    autonumber
    participant U as Customer
    participant App as Your App
    participant PSP as Payment Provider
    participant Bank as Issuing Bank

    U->>App: place the order
    App->>App: create the order, status awaiting_payment
    App->>PSP: create a payment intent, idempotency key is the order id
    PSP-->>App: intent id plus a client secret
    App-->>U: payment form bound to that intent
    U->>PSP: card details, they never reach our server
    PSP->>Bank: authorization request
    alt the issuer wants a challenge
        Bank-->>PSP: 3-D Secure required
        PSP-->>U: challenge screen hosted by the bank
        U->>Bank: approve in the banking app
        Bank-->>PSP: authenticated
    else no challenge needed
        Bank-->>PSP: authorized
    end
    PSP-->>U: send the browser back to our return page
    PSP->>App: payment_intent.succeeded
    App->>App: mark the order paid, then fulfil it
    Note over PSP,App: this arrow is the truth - the redirect above is only a hint
A card checkout sequence diagram: a payment intent keyed by the order id, card details sent straight to the provider, an optional 3-D Secure challenge at the issuing bank, and the order marked paid on the provider's asynchronous confirmation rather than the browser redirect.

2 · The whole life of one payment

A state diagram, because a payment is an object that ages rather than a conversation. This is the version to put in front of anyone who thinks the work ends at checkout — roughly half the diagram describes things that happen after the customer has forgotten about the order.

Authorized and Captured being two states is the part to keep even if you capture immediately. The note says why: an authorization has an expiry, and it lapses without telling anyone. A warehouse that takes nine days to ship does not get a failed payment, it gets an order that was never actually charged.

Expired is worth its own state rather than an arrow into Declined, because the two need different handling — one customer needs a new card, the other needs to be asked to pay again for something they already agreed to buy.

Disputed with an edge back to Captured when you win is the branch people forget, and it is the one that makes the diagram operationally useful: a payment can leave a state you thought was final, three months after the sale, on someone else's timetable. If nothing in your model can do that, your model is wrong about what a payment is.

View the Mermaid source
stateDiagram-v2
    [*] --> RequiresPayment: order placed
    RequiresPayment --> RequiresAction: the issuer asks for 3-D Secure
    RequiresAction --> Authorizing: the customer approved it
    RequiresPayment --> Authorizing: no challenge needed
    Authorizing --> Authorized: funds held, not moved
    Authorizing --> Declined: the issuer said no
    Authorized --> Captured: we ship, or we charge straight away
    Authorized --> Expired: never captured, the hold is released
    Captured --> PartiallyRefunded: one item came back
    PartiallyRefunded --> Refunded: the rest came back
    Captured --> Refunded: refunded in full
    Captured --> Disputed: chargeback filed, up to 120 days later
    PartiallyRefunded --> Disputed: chargeback filed
    Disputed --> Won: our evidence was accepted
    Disputed --> Lost: the funds are pulled back plus a fee
    Won --> Captured: the money stays with us
    Declined --> [*]
    Expired --> [*]
    Refunded --> [*]
    Lost --> [*]
    note right of Authorized
        an authorization is a promise with an expiry
        seven days is typical and it lapses silently
    end note
A state diagram of one payment: requires payment, 3-D Secure action required, authorizing, authorized, captured, expired, partially refunded, refunded, disputed, dispute won and dispute lost.

3 · What to do when the charge does not go through

A flowchart, because this one is a decision rather than a sequence — and the decision is made by code that runs long after the customer has left.

The split between soft and hard declines is the whole diagram. Insufficient funds and a briefly unreachable issuer mean try again later, it may work. A stolen card, a closed account or a plain "do not honour" means this will fail identically next week. Retrying the second kind is not merely useless: card networks track your authorization success rate, and a stream of retries against dead cards is one of the ways a merchant account starts attracting attention.

Note that a subscription and a one-off checkout take different paths from the same decline. Nobody is watching a subscription renewal, so retrying on a schedule is the correct behaviour. Somebody is watching a checkout — silently retrying behind their back while they stare at a spinner is worse than telling them immediately and keeping the cart intact.

The branch that gets left out is the one where retries are exhausted. Cancel the subscription and email the customer is an unglamorous box, and without it the failure mode is an account that quietly keeps working for a customer who has not paid in four months.

View the Mermaid source
flowchart TD
    A[A charge attempt comes back declined] --> B{What kind of decline}
    B -->|Insufficient funds, issuer unavailable| C[Soft decline]
    B -->|Stolen card, closed account, do not honour| D[Hard decline]
    B -->|Authentication required| E[Send the customer to a challenge]
    C --> F{Is this a subscription}
    F -->|Yes| G[Retry on day 3, day 5 and day 7, then stop]
    F -->|No| H[Tell the customer now and keep the cart]
    G --> I{Did one of them go through}
    I -->|Yes| J[Captured]
    I -->|No| K[Cancel the subscription and email the customer]
    D --> L[Never retry, ask for a different card]
    E --> M{Did they finish the challenge}
    M -->|Yes| J
    M -->|No| H
A flowchart for handling a declined charge: soft declines retried on a schedule for subscriptions, hard declines never retried, and authentication-required declines sent back to a challenge.

Put your finger on the challenge screen and close the tab

Take the finished checkout diagram, find the arrow where the customer leaves for the bank's challenge screen, and put your finger there. Now decide that the customer approved it and then closed the tab — approval succeeded, the browser never came back.

Trace what your system does from that point using only the arrows on the page. If the answer is "the provider's message arrives, we mark the order paid, we fulfil, the customer gets an email", the design holds and the tab close was irrelevant, which is the correct outcome. If tracing it requires you to say the words "and then the user would come back to the success page", you have found a real hole: the money moved and no arrow on your diagram creates the order.

That is not a rare case. It is a customer on a phone, on a train, who did exactly what you asked them to do. Run the same finger test at each of the three places the flow leaves your control, and every hole that exists will be one of them.

FAQ

Continue reading

Try text2diagram now

Open the tool
← Back to all tutorials