Chuyển tới nội dung chính

Payment Flow

The store service owns the shopping cart and the payment checkout session for a booking. A client never calls a single "pay" endpoint — it walks an ordered sequence that resets any stale state, builds a cart, opens a checkout session, flags whether the booking is corporate, and only then executes the payment.

This page documents the order those calls must happen in and what each one is responsible for.

Scope of this page

This page currently specifies the call sequence and the branch conditions. Per-operation request/response payloads, per-step error codes, and the transport details are not documented yet — see Still to document. For the errors any call in the sequence can return, see Middleware Errors.

The sequence​

Step 3 is not a store-service call — the cart line item is created by the service that owns the product being booked. Everything else in the chain is the store service.

Step by step​

#OperationOwnerWhy it's here
1clear_shopping_itemsStore serviceEmpties the cart so items left over from an abandoned checkout can't be paid for by accident.
2cancel_payment_checkout_sessionStore serviceCloses any checkout session still open from a previous attempt. Steps 1–2 together are the reset preamble — they make the sequence safe to re-enter.
3create shopping_itemOther serviceThe product service (flight, hotel, …) writes the line item into the now-empty cart.
4begin_payment_checkout_sessionStore serviceOpens a fresh checkout session over the cart's contents. Everything downstream operates on this session.
5update_corporate_paymentStore serviceToggles the corporate flag on the session. Defaults to false, so this is only required for corporate bookings — see The corporate branch.
6update_booking_noteStore serviceAttaches the booking note to the session.
7confirm_paymentStore serviceConfirms the session and locks it for payment.
8pay_with_corporate / pay_with_wallet / …Store serviceExecutes the payment against the chosen funding source.

The corporate branch​

update_corporate_payment sets one toggle on the checkout session. A session opened at step 4 starts with enable = false — the call is a switch, not a one-shot, so it can flip the session between corporate and non-corporate as many times as the user changes their mind before payment.

StateenableHow it's reached
DefaultfalseSet when begin_payment_checkout_session opens the session — no call needed
Corporate bookingtrueupdate_corporate_payment with enable = true
Switched back offfalseupdate_corporate_payment with enable = false

So step 5 is a branch in value, not in control flow — but only the true path actually changes anything on a fresh session. Step 5b is redundant on a first pass, since false is already the default. It's worth calling anyway for two reasons:

  • The client keeps a single unconditional code path instead of a conditional call.
  • It's the call you need when the user turns corporate payment off after having turned it on — the same operation, reused to switch back.

Payment methods​

Step 8 picks one terminal operation, one per funding source:

OperationFunds from
pay_with_corporateCorporate payment (the path enabled at step 5)
pay_with_walletUser / company wallet
pay_with_…Additional methods follow the same pay_with_* naming

pay_with_corporate is the natural pair for a session where step 5 set enable = true.

Ordering rules​

  • Steps 1–2 come before step 3. The cart is cleared first, then filled — reversing them wipes the item that was just created.
  • Step 4 comes after step 3. The checkout session is opened over a cart that already holds its items.
  • Steps 5–7 all operate on the session opened at step 4. They fail without it.
  • Step 5 is repeatable. It's a toggle on the live session, so it can be called more than once to flip the corporate flag before the session is confirmed.
  • Step 7 precedes step 8. Payment executes against a confirmed session.

Error reference​

Operation-specific errors are documented on the operation's own page under APIs — so far pay_with_corporate.

Errors that aren't tied to one step live under Errors:

  • Middleware Errors — authentication, authorization, delegation, and OTP failures raised before any call reaches the store service.
  • Trip-Related Errors — budget, guest, and traveller validation failures on trip bookings.

Still to document​

The following need input from the backend team before this page is a complete API reference:

  • Transport and path for each operation. pay_with_corporate is confirmed as a GraphQL mutation; the rest are presumed to be too, unconfirmed.
  • Request and response shapes, with a field table per operation.
  • Authentication — presumably the standard Authorization user token, unconfirmed.
  • Error responses per step, and what recovery looks like when a step fails mid-sequence (does the client restart at step 1?).
  • The full list of pay_with_* methods, each of which needs its own page under APIs.
  • Whether update_corporate_payment is still accepted after confirm_payment, or whether confirming locks the flag.
  • Idempotency behaviour — whether re-running the sequence with the same cart is safe.

Once those land, this page should also get matching Bruno requests under api-tests/backend/store-service/, each carrying a - Doc: `docs/backend-service/store-service/payment-flow.mdx` line so the results surface in this page's API & Tests panel.