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: <a href="checkout-step-0-cart-review">π Step 0 - Cart Review</a>
activate B
U ->> B: <a href="checkout-step-1-authentication">π Step 1 - Authentication</a>
U ->> B: <a href="checkout-step-2-payment-selection--order-creation">π Step 2 - Payment Selection & Order Creation</a>
note over B: Order created (status='created')
alt Payment Method Flows
note over U,B: iDEAL, PayPal, Klarna, Bank Transfer
U ->> B: <a href="ideal-flow">π Payment method - iDEAL</a>
else
note over U,B: Creditcard - requires card selection
U ->> B: <a href="checkout-step-2a-creditcard-selection">π Step 2a - Creditcard Selection</a>
U ->> B: <a href="creditcard-flow">π Payment method - Creditcard</a>
else
note over U,B: Bancontact - requires payment option selection
U ->> B: <a href="checkout-step-2b-bancontact-selection">π Step 2b - Bancontact Selection</a>
U ->> B: <a href="bancontact-flow">π Payment method - Bancontact</a>
end
note over B: Order locked (status='pending')
U ->> B: <a href="checkout-step-3-payment-validation">π Step 3 - Payment Validation</a>
U ->> B: <a href="checkout-step-4-order-confirmation">π Step 4 - Order Confirmation</a>
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: <a href="authentication-method-login">π Login</a>
else
U ->> B: <a href="authentication-method-register">π Register</a>
else
U ->> B: <a href="authentication-method-guest">π Continue as Guest</a>
else
U ->> B: <a href="authentication-method-forgot-password">π Forgot Password</a>
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<br/> 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,<br/>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,<br/>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: <a href="order-handling-flow">π Order Handling flow</a>
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 <a href="checkout-step-2a-creditcard-selection">β οΈ Step 2a - Creditcard Selection</a>
else
note over U,B: Bancontact selected
B -->> U: Redirect to <a href="checkout-step-2b-bancontact-selection">β οΈ Step 2b - Bancontact Selection</a>
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:<br/><a href="ideal-flow">π iDEAL</a>, <a href="paypal-flow">β οΈ PayPal</a>, <a href="klarna-flow">β οΈ Klarna</a>, <a href="bank-transfer-flow">β οΈ Bank Transfer</a>
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/paymentafter 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/paymentafter 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 <a href="checkout-step-2-payment-selection-order-creation">π Step 2 - Payment Selection</a><br/>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<br/>Order ID: 12345<br/>Method: ideal<br/>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:<br/>- amount<br/>- returnUrls (success, cancelled, expired, failed)<br/>- consumer info<br/>- order reference
CM -->> B: Response with transaction (status=OPEN)<br/>+ redirect URL
note over B: CM Transaction ID: abc123<br/>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 -> <a href="checkout-step-4-payment-validation">π Checkout step 4 - Payment Validation</a><br/>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: <a href="#unhappy-path---failed-payment-retry">π Failed Payment Retry flow</a><br/>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: <a href="#unhappy-path---payment-method-switch">π Payment Method Switch flow</a><br/>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: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> <a href="#checkout-step-3---payment-validation">Checkout step 3 - Payment Validation</a><br/>Payment failed, redirected to /checkout/payment-selection?error=payment_failed
Note over U: Modal opens: "Payment failed: insufficient funds"<br/>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<br/>(order_id=12345, retry_count=1, status='initiated')
note over B: Payment Attempt ID: 2<br/>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: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> Payment method flow<br/>Process attempt 2 (succeeds)
note over U,B: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> <a href="#checkout-step-3---payment-validation">Checkout step 3 - Payment Validation</a>
note over U,B: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> <a href="#checkout-step-4---order-confirmation">Checkout step 4 - Order Confirmation</a>
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: <a href="#unhappy-path---payment-method-switch">π Payment Method Switch flow</a>
end
note over B: π‘ Result: Order 12345 has 2 payment attempts:<br/>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: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> <a href="#checkout-step-3---payment-validation">Checkout step 3 - Payment Validation</a><br/>Payment cancelled, redirected to /checkout/payment-selection?cancelled=true
Note over U: Modal opens: "Payment cancelled"<br/>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<br/>(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: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> New payment method flow (e.g., <a href="#paypal-flow">PayPal</a>)<br/>Process attempt 2
note over U,B: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> <a href="#checkout-step-3---payment-validation">Checkout step 3 - Payment Validation</a><br/>Validate attempt 2 (succeeds)
note over U,B: <span style="color:#FF9800; font-weight:bold;">Go Back to -></span> <a href="#checkout-step-4---order-confirmation">Checkout step 4 - Order Confirmation</a>
note over B: π‘ Result: Order 12345 has 2 attempts:<br/>Attempt 1: iDEAL, cancelled<br/>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<br/>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