Skip to content

Proposed Checkout FlowsΒΆ

Design Status

This document contains all proposed sequence diagrams for the new checkout flow. See Overview for the business rationale and Proposed Technical Specification for database schema and state machines.

LegendΒΆ

Sequence Diagram Legend

Highlight Color Meaning
TODO Green Task that still needs to be completed
ROUGH Fuchsia Part that might not be complete or accurate
Go Back to -> Orange Reference to return to a previous step
πŸ“‹ Link Blue Clickable link to another section or flow
πŸ“Š MT-X - Metric tracked at this step - click to view details in metrics tables

Flow Icons

  • πŸ“‹ Main flow - Primary payment flows and major checkout steps
  • πŸ”„ Sub-flow - Nested flows within a payment method (e.g., retry, method switching)
  • ℹ️ Optional - Optional flows that can be skipped
  • ⚠️ Incomplete - Flows that need implementation or are marked as TODO

Main FlowΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend U ->> B: πŸ“‹ Step 0 - Cart Review activate B U ->> B: πŸ“‹ Step 1 - Authentication U ->> B: πŸ“‹ Step 2 - Payment Selection & Order Creation note over B: Order created (status='created') alt Payment Method Flows note over U,B: iDEAL, PayPal, Klarna, Bank Transfer U ->> B: πŸ“‹ Payment method - iDEAL else note over U,B: Creditcard - requires card selection U ->> B: πŸ“‹ Step 2a - Creditcard Selection U ->> B: πŸ“‹ Payment method - Creditcard else note over U,B: Bancontact - requires payment option selection U ->> B: πŸ“‹ Step 2b - Bancontact Selection U ->> B: πŸ“‹ Payment method - Bancontact end note over B: Order locked (status='pending') U ->> B: πŸ“‹ Step 3 - Payment Validation U ->> B: πŸ“‹ Step 4 - Order Confirmation deactivate B

Happy Path FlowsΒΆ

πŸ“‹ Checkout step 0 - Cart ReviewΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend %% Pre-Checkout alt Add to cart note over U,B: Add to cart - using PDP or PLP note right of U: productId's and productAttributeId's originate from data from the PLP or PDP page U ->> B: POST request to /api/cart/items with productId and productAttributeId in the request body from the PLP or PDP note over B: πŸ“Š Track cart item add attempted B ->> B: Validate request to add product to cart (availibility etc.) note over B: πŸ“Š Track cart item add result (success/failed with reason) B -->> U: Response containing the updated cart data (data is used for the cart popup) else note over U,B: Add to cart - using My account reorder U ->> B: GET request to /my-account B -->> U: Response containing my-account page and data for the first tab U ->> U: Change to order-history tab U ->> B: GET request to /order-history B -->> U: Response containing the order-history data (Not the page itself, that was already sent in the original request) note right of U: productId's and productAttributeId's originate from data of an old order U ->> B: POST request to /api/cart/items with an array of productId and productAttributeId pairs in the request body from an order in order-history note over B: πŸ“Š Track reorder attempted (item count) B ->> B: Validate request to add product to cart (availibility etc.) note over B: πŸ“Š Track reorder result (success/partial with counts) B -->> U: Response containing the updated cart data (data is used for the cart sidebar) end U ->> U: Clicks on 'Cart' button sends user to /cart U ->> B: GET request to /cart note over B: πŸ“Š Track cart page viewed B ->> B: Use users session to get cart data B -->> U: Response containing Cart page with cart data

Cart removal metrics

When a user removes/updates items from the cart, the following metrics are tracked:

  • πŸ“Š Metric: cart_item_remove (CartController)
  • πŸ“Š Metric: cart_item_remove (My Account API)
  • πŸ“Š Metric: cart_item_update (CartController)
  • πŸ“Š Metric: cart_item_update (My Account API)

πŸ“‹ Checkout step 1 - AuthenticationΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend U ->> B: Navigate to checkout - GET /checkout/auth activate B B ->> B: Check if user is logged in alt User login status note over U,B: User already logged in note over B: πŸ“Š Track auth skip (already logged in) B -->> U: Redirect to /checkout/payment-selection else note over U,B: User not logged in B -->> U: Response containing auth page with auth options (Login/Register/Guest/Forgot Password) note over B: πŸ“Š Track auth page viewed end alt Authentication method U ->> B: πŸ”„ Login else U ->> B: πŸ”„ Register else U ->> B: πŸ”„ Continue as Guest else U ->> B: πŸ”„ Forgot Password end deactivate B

πŸ”„ Authentication method - LoginΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend U ->> U: Navigate to /checkout/auth?mode=login (client-side) U ->> U: Enter email and password in login form U ->> B: Submit login - POST /checkout/auth?mode=login note over B: πŸ“Š Track login attempted alt Login result note right of U: Login successful note over B: πŸ“Š Track login success note over B: TODO - Merge guest cart + logged-in cart
TODO (handle 'created' orders attached to either cart) B ->> B: Update customer session B -->> U: Redirect to /checkout/payment-selection else note right of U: Login failed note over B: πŸ“Š Track login failed (reason) B -->> U: Response with error message, stay on /checkout/auth end

πŸ”„ Authentication method - RegisterΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend U ->> U: Navigate to /checkout/auth?mode=register (client-side) U ->> U: Fill in registration form with password field note over U: Form includes: email, password, name,
address, phone, country selector (NL/FR/LU only) U ->> B: Submit registration - POST /checkout/auth?mode=register note over B: πŸ“Š Track register attempted alt Registration result note right of U: Registration successful note over B: πŸ“Š Track register success B ->> B: Create customer account (is_guest=false) B ->> B: Associate cart with new customer B ->> B: Update customer session B -->> U: Redirect to /checkout/payment-selection else note right of U: Registration failed note over B: πŸ“Š Track register failed (reason: email exists, validation, etc.) B -->> U: Response with error message, stay on /checkout/auth end

πŸ”„ Authentication method - GuestΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend U ->> U: Navigate to /checkout/auth?mode=guest (client-side) U ->> U: Fill in guest registration form (no password field) note over U: Form includes: email, name, address,
phone, country selector (FR/LU only) U ->> B: Submit guest registration - POST /checkout/auth?mode=guest note over B: πŸ“Š Track guest register attempted alt Guest registration result note right of U: Guest registration successful note over B: πŸ“Š Track guest register success B ->> B: Create guest customer account (is_guest=true) B ->> B: Associate cart with guest customer B ->> B: Update customer session B -->> U: Redirect to /checkout/payment-selection else note right of U: Guest registration failed note over B: πŸ“Š Track guest register failed (reason) B -->> U: Response with error message, stay on /checkout/auth end

πŸ”„ Authentication method - Forgot PasswordΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend participant E as Email System U ->> B: Click "Forgot Password" link - GET /password-recovery B -->> U: Response containing password recovery page note over B: πŸ“Š Track password recovery page viewed U ->> U: Enter email address U ->> B: Submit password reset - POST /password-recovery note over B: πŸ“Š Track password reset requested alt Password reset note right of U: Email exists B ->> E: Send password reset email note over B: πŸ“Š Track password reset email sent E -->> U: Password reset email delivered B -->> U: Response with "Check your email" message U ->> U: Open email, click reset link U ->> B: Open reset link - GET /password-recovery?reset_token=X&id_customer=Y B -->> U: Response containing new password form U ->> U: Enter new password twice U ->> B: Submit new password - POST /password-recovery note over B: πŸ“Š Track password reset completed B -->> U: Response with "Password changed" message U ->> U: Clicks on 'Cart' button sends user to /cart U ->> B: GET request to /cart B ->> B: Use users session to get cart data B -->> U: Response containing Cart page with cart data note over U,B: Go Back to -> Checkout step 1 - Authentication else note right of U: Email not found note over B: πŸ“Š Track password reset failed (email not found) B -->> U: Response with error message end

πŸ“‹ Checkout step 2 - Payment Selection & Order CreationΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend U ->> B: View payment selection page - GET /checkout/payment-selection activate B note over B: πŸ“Š Track payment selection page viewed note over B: See: πŸ”„ Order Handling flow B ->> B: Get available payment methods for this customer B -->> U: Response containing payment methods page U ->> U: Select payment method from list U ->> B: Submit payment method selection - POST /checkout/payment-selection note over B: πŸ“Š Track payment method selected alt Payment method routing note over U,B: Creditcard selected B -->> U: Redirect to ⚠️ Step 2a - Creditcard Selection else note over U,B: Bancontact selected B -->> U: Redirect to ⚠️ Step 2b - Bancontact Selection else note over U,B: iDEAL, PayPal, Klarna, or Bank Transfer selected B -->> U: Redirect to /checkout/payment?method=METHOD_NAME note over U,B: See payment method flows:
πŸ“‹ iDEAL, ⚠️ PayPal, ⚠️ Klarna, ⚠️ Bank Transfer end deactivate B

Payment Method FlowsΒΆ

⚠️ Checkout step 2a - Creditcard Selection¢

Status: ⚠️ To be detailed

Flow characteristics:

  • Select existing saved card OR enter new card details
  • Optional: Save card for future use
  • Card tokenization via CM.com
  • Redirect to /checkout/payment after selection

⚠️ Checkout step 2b - Bancontact Selection¢

Status: ⚠️ To be detailed

Flow characteristics:

  • Choose payment option: QR Code, Mobile App, or Card
  • If Card selected: Card selection/entry (similar to creditcard flow)
  • QR code generation for desktop users
  • Redirect to /checkout/payment after selection

πŸ“‹ iDEAL FlowΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend participant CM as CM.com REST API participant Bank as iDEAL Bank note over U,B: Coming from πŸ“‹ Step 2 - Payment Selection
User selected iDEAL as payment method U ->> B: Initiate payment - GET /checkout/payment?method=ideal activate B note over B: πŸ“Š Track payment page viewed (method=ideal) B ->> B: Load order from cart (via session) B ->> B: Create payment attempt (status='initiated') note over B: Payment Attempt ID: 67890
Order ID: 12345
Method: ideal
Status: initiated B ->> B: Update order status to 'pending' (lock cart/prices) note over B: Order is now LOCKED - no more changes allowed B ->> CM: Create iDEAL transaction - POST /paymentmethods/ideal/v1/transactions activate CM note over CM: Request includes:
- amount
- returnUrls (success, cancelled, expired, failed)
- consumer info
- order reference CM -->> B: Response with transaction (status=OPEN)
+ redirect URL note over B: CM Transaction ID: abc123
Status: OPEN deactivate CM B ->> B: Store CM transaction ID in payment attempt note over B: πŸ“Š Track payment initiated (cm_transaction_id) B -->> U: Redirect to iDEAL (via CM.com) deactivate B U ->> Bank: User completes payment at iDEAL activate Bank note over U,Bank: User selects bank, authenticates, and confirms payment via mobile app Bank ->> CM: Payment result (SUCCESS/CANCELLED/EXPIRED/FAILURE) CM ->> B: Webhook notification with status Bank -->> U: Redirect to returnUrl: /checkout/validate?attempt_id=67890 deactivate Bank note over U,B: Go to -> πŸ“‹ Checkout step 4 - Payment Validation
Backend will check webhook data to determine actual status

⚠️ PayPal Flow¢

Status: ⚠️ To be detailed

Flow characteristics:

  • REST-based payment method
  • Redirect to PayPal login
  • External authentication
  • Return callback

⚠️ Creditcard Flow¢

Status: ⚠️ To be detailed

Flow characteristics:

  • Uses selected/entered card from step 2a
  • 3D Secure authentication
  • SOAP to REST migration needed

⚠️ Bancontact Flow¢

Status: ⚠️ To be detailed

Flow characteristics:

  • Multiple sub-flows based on selection from step 2b
  • QR code scanning (desktop)
  • Mobile app redirect
  • Card payment with 3D Secure
  • SOAP to REST migration needed

⚠️ Klarna Flow¢

Status: ⚠️ To be detailed

Flow characteristics:

  • Phone number requirement
  • External redirect
  • SOAP to REST migration needed

⚠️ Bank Transfer Flow¢

Status: ⚠️ To be detailed

Flow characteristics:

  • No immediate payment
  • Display payment instructions
  • Manual confirmation
  • SOAP to REST migration needed

πŸ“‹ Checkout step 4 - Payment ValidationΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend participant CM as CM.com REST API Note over U,CM: User returns from payment provider U ->> B: Validate payment - GET /checkout/validate?attempt_id=67890 activate B B ->> CM: Check payment status - GET /payments/{transaction_id} activate CM CM -->> B: Response: {status, reason} deactivate CM alt Payment Success B ->> B: Update payment attempt (status='success') B ->> B: Update order (status='confirmed') note over B: πŸ“Š Track payment success B -->> U: Redirect to /checkout/confirmation?order_id=12345 else Payment Failed B ->> B: Update payment attempt (status='failed', error_code) note over B: Order remains status='pending' note over B: πŸ“Š Track payment failed (with reason) B -->> U: Redirect to /checkout/payment-selection?error=payment_failed note right of U: See: πŸ”„ Failed Payment Retry flow
Modal opens with error message else Payment Cancelled B ->> B: Update payment attempt (status='cancelled') note over B: Order remains status='pending' note over B: πŸ“Š Track payment cancelled B -->> U: Redirect to /checkout/payment-selection?cancelled=true note right of U: See: πŸ”„ Payment Method Switch flow
Modal opens with cancellation message end deactivate B

πŸ“‹ Checkout step 5 - Order ConfirmationΒΆ

Flow - click to expand
sequenceDiagram autonumber participant U as User participant B as Backend U ->> B: View confirmation - GET /checkout/confirmation?order_id=12345 activate B B ->> B: Load order details B -->> U: Display order confirmation note over B: πŸ“Š Track order confirmation viewed deactivate B

Unhappy Path FlowsΒΆ

πŸ”„ Unhappy Path - Failed Payment RetryΒΆ

Failed Payment with Retry - click to expand

Modal-based Retry

When payment fails, user is redirected to /checkout/payment-selection?error=payment_failed. A modal opens showing the error message with two options:

  • "Try Again" - Retry with the same payment method
  • "Close" - Close modal and select a different method
sequenceDiagram autonumber participant U as User participant B as Backend note over U,B: Go Back to -> Checkout step 3 - Payment Validation
Payment failed, redirected to /checkout/payment-selection?error=payment_failed Note over U: Modal opens: "Payment failed: insufficient funds"
Options: "Try Again" | "Close" alt User clicks "Try Again" U ->> B: Click "Try Again" - POST /checkout/payment-selection activate B B ->> B: Create new payment attempt
(order_id=12345, retry_count=1, status='initiated') note over B: Payment Attempt ID: 2
Same method as attempt 1 note over B: πŸ“Š Track payment retry B -->> U: Redirect to /checkout/payment?attempt_id=2 deactivate B note over U,B: Go Back to -> Payment method flow
Process attempt 2 (succeeds) note over U,B: Go Back to -> Checkout step 3 - Payment Validation note over U,B: Go Back to -> Checkout step 4 - Order Confirmation else User clicks "Close" (switch method) U -->> U: Close modal, stay on /checkout/payment-selection note over U: User can now select different payment method note over U,B: See: πŸ”„ Payment Method Switch flow end note over B: πŸ’‘ Result: Order 12345 has 2 payment attempts:
Attempt 1: failed | Attempt 2: success (or cancelled if switched)

πŸ”„ Unhappy Path - Payment Method SwitchΒΆ

Payment Method Switching - click to expand

Modal-based Method Switch

When payment is cancelled, user is redirected to /checkout/payment-selection?cancelled=true. A modal opens showing cancellation message with options to retry or switch.

sequenceDiagram autonumber participant U as User participant B as Backend note over U,B: Go Back to -> Checkout step 3 - Payment Validation
Payment cancelled, redirected to /checkout/payment-selection?cancelled=true Note over U: Modal opens: "Payment cancelled"
Options: "Try Again" | "Close" U -->> U: Close modal (switching method) Note over U: User stays on /checkout/payment-selection U ->> B: Select different method (PayPal) - POST /checkout/payment-selection activate B B ->> B: Create new payment attempt
(order_id=12345, method='paypal', status='initiated') note over B: Payment Attempt ID: 2 note over B: πŸ“Š Track payment method switch (from=ideal, to=paypal) B -->> U: Redirect to /checkout/payment?attempt_id=2 deactivate B note over U,B: Go Back to -> New payment method flow (e.g., PayPal)
Process attempt 2 note over U,B: Go Back to -> Checkout step 3 - Payment Validation
Validate attempt 2 (succeeds) note over U,B: Go Back to -> Checkout step 4 - Order Confirmation note over B: πŸ’‘ Result: Order 12345 has 2 attempts:
Attempt 1: iDEAL, cancelled
Attempt 2: PayPal, success

πŸ”„ Order Handling FlowΒΆ

Order Creation and Re-evaluation - click to expand

When This Flow Triggers

This flow runs every time a user navigates to /checkout/payment-selection:

  • No order exists: First time visiting β†’ create new order
  • Order in 'created' state: User returns (refresh, back from cart) β†’ re-evaluate cart changes
  • Order in 'pending' state: User returns after failed/cancelled payment β†’ retry or switch method
sequenceDiagram autonumber participant U as User participant B as Backend B ->> B: Load cart from session B ->> B: Check if order exists linked to cart alt Order status note over U,B: No order exists B ->> B: Create order (status='created') B ->> B: Link order to cart note over B: πŸ“Š Track order created note over U,B: Go to -> Continue with payment selection else note over U,B: Order exists (status='pending') note over B: Order is LOCKED - cannot modify cart
User is retrying/switching payment method B ->> B: Load existing order note over U,B: Go to -> Continue with payment selection (retry/switch) else note over U,B: Order exists (status='created') note over B: Order can still be modified - cart not locked B ->> B: Load existing order B ->> B: Compare order with current cart state end alt Cart comparison note over U,B: Cart unchanged note over U,B: Go to -> Continue with payment selection else note over U,B: Cart has changed B ->> B: Validate stock availability B ->> B: Recalculate totals (prices, tax, shipping) end alt Validation result note over U,B: Validation successful B ->> B: Update order line items and totals note over B: πŸ“Š Track order updated note over U: Notification: "Your order has been updated" note over U,B: Go to -> Continue with payment selection else note over U,B: Out of stock or validation failed note over B: πŸ“Š Track order validation failed B -->> U: Redirect to /cart with error message note over U: "Some items are no longer available" end

State machinesΒΆ

Order State MachineΒΆ

stateDiagram-v2
    [*] --> Created: Order Created (at payment-selection)

    note right of Created
        Customer can still modify cart/address
        Order gets updated when they return to payment-selection page
        ---
        Prices re-validated on return
    end note

    Created --> Pending: First Payment Attempt (at /checkout/payment)

    note right of Pending
        Order is LOCKED - no changes allowed
        Prices locked
        Can have multiple payment attempts
        ---
        30-minute timeout β†’ Abandoned
    end note

    Pending --> Confirmed: Payment Success
    Pending --> Failed: Payment Failed (max retries exceeded)
    Pending --> Cancelled: User Cancels
    Pending --> Abandoned: Timeout (30 min, lazy evaluation)

    note left of Abandoned
        Customer left during payment
        ---
        If customer returns: create new order with current prices/stock
    end note

    note left of Cancelled
        Customer actively clicked cancel during the payment process
    end note

    Confirmed --> Shipped: Order Shipped
    Confirmed --> Refunded: Refund Issued

    Shipped --> Delivered: Delivery Confirmed

    Abandoned --> [*]
    Cancelled --> [*]
    Failed --> [*]
    Refunded --> [*]
    Delivered --> [*]

Payment Attempt State MachineΒΆ

stateDiagram-v2
    [*] --> Initiated: Create Payment Attempt

    Initiated --> Cancelled: User Cancels (before processing)
    Initiated --> Processing: Sent to CM.com

    Processing --> Cancelled: Timeout/User Cancel
    Processing --> Failed: Payment Rejected
    Processing --> Success: Payment Approved

    Cancelled --> [*]: Allow Retry
    Failed --> [*]: Allow Retry
    Success --> [*]: Update Order

    note left of Cancelled
        ***Failed and Cancelled***
        Both states allow creating
        a new payment attempt
    end note