Payment architecture
The checkout service orchestrates payment processing by coordinating between payment provider services (Stripe, Adyen, Mollie, PayNL, etc.) and commercetools. Each payment provider is a standalone service that handles communication with its PSP. The provider only updates the Payment object and its transactions. Order-level actions (confirming an order, handling cancellations) are handled by the checkout service through event subscriptions.
Sequence diagram
Section titled “Sequence diagram”sequenceDiagram
actor CU as Customer
participant WE as Website
participant CO as Checkout
participant PS as PSP service
participant CT as commercetools
participant PSP as PSP
participant BANK as Bank
Note over CU,BANK: Start payment flow
CU->>WE: Start payment step
activate WE
WE ->> CO: createPayment
activate CO
CO ->> CT: get order
activate CT
CT -->> CO: order data
CO ->> CT: create Payment on order
activate CT
CO ->> PS: create transaction
activate PS
PS ->> PSP: create transaction
activate PSP
PSP -->> PS: transaction object
deactivate PSP
PS ->> CT: create Transaction on payment
deactivate CT
deactivate CT
PS -->> CO: transaction result
deactivate PS
CO -->> WE: return payment redirect URL
deactivate CO
WE-->>CU: Redirect customer to PSP
activate PSP
CU->>PSP: Pay order at PSP
PSP->>BANK: redirect to bank
activate BANK
BANK ->> BANK: pay/cancel/else
BANK-->>PSP: return payment result
deactivate BANK
PSP-->>WE: Return to returnURL
deactivate PSP
WE->>CO: Update order payment status
activate CO
CO->>CT: Fetch order by transaction ID
activate CT
CT-->>CO: Return order
deactivate CT
CO->>PS: Fetch transaction status for order
activate PS
PS->>PSP: Fetch transaction status
activate PSP
PSP-->>PS: Return transaction status
deactivate PSP
PS->>CT: Update transaction status
activate CT
PS-->>CO: Return transaction status
deactivate PS
deactivate CT
CO->>CT: Fetch update order
activate CT
CT-->>CO: Return updated order
deactivate CT
CO-->>WE: Return order with payment status
deactivate CO
WE->>CU: Show confirmation page
deactivate WE
Creating a payment
Section titled “Creating a payment”When a payment is needed, the frontend calls the createPayment
mutation. The checkout service then:
- Fetches the order from commercetools
- Creates a Payment object on the order with the selected method and payment interface
- Delegates to the appropriate PSP service to start a transaction
- Returns a redirect URL so the customer can complete payment
The Payment object stores the selected method in
paymentMethodInfo.method and the provider identifier in
paymentMethodInfo.paymentInterface.
Payment states
Section titled “Payment states”The checkout service manages payment state transitions through commercetools state machines. Payment providers transition the Payment to one of these states:
| State | Key | Environment variable override |
|---|---|---|
| Initial | PaymentInitial |
PAYMENT_STATE_KEY_INITIAL |
| Pending | PaymentPending |
PAYMENT_STATE_KEY_PENDING |
| Success | PaymentSuccess |
PAYMENT_STATE_KEY_SUCCESS |
| Cancelled | PaymentCancelled |
PAYMENT_STATE_KEY_CANCELLED |
| Failure | PaymentFailure |
PAYMENT_STATE_KEY_FAILURE |
These state objects are defined in the checkout service’s Terraform configuration and looked up by key at runtime. You can override the default keys through environment variables if your project uses different naming.
Event-driven order updates
Section titled “Event-driven order updates”When a payment state changes, commercetools emits a
PaymentStatusStateTransition message. The checkout service
subscribes to these messages and updates the order accordingly. For
example, when all payments on an order reach PaymentSuccess, the
checkout service transitions the order’s payment state to paid.
This event-driven approach means the checkout service reacts to payment outcomes asynchronously rather than polling for status changes. See Messaging & events for how event subscriptions work across all services.
REST endpoints
Section titled “REST endpoints”A payment provider exposes the following API endpoints:
POST /payment-methods: return the payment methods available for the given cart. The cart ID and other context are passed in the request body.
POST /create: create a payment transaction. This starts the payment flow and returns a redirect URL for the customer to complete payment at the PSP.
POST /push (webhook): receive asynchronous payment status updates from the PSP. This endpoint handles webhook callbacks and updates the transaction status in commercetools. See REST endpoints & webhooks for how each provider verifies webhook authenticity.
A payment provider may also expose:
GET /redirect: handle customer redirects back from the PSP after completing payment.
POST /validate-apple-pay-session: validate an Apple Pay merchant session for Apple Pay payments.
API contract
Section titled “API contract”The payment API contract is defined as TypeBox schemas in the
@evolve-framework/commercetools package
(packages/commercetools/src/payments/schema.ts). The two primary
endpoints and their types are documented below.
POST /create
Section titled “POST /create”Starts a payment transaction and returns a redirect URL for the customer to complete payment at the PSP.
Request body: TransactionRequest
| Field | Type | Required | Description |
|---|---|---|---|
amount |
Price |
yes | Transaction amount |
customer |
object | yes | { ipAddress: string } - IPv4 or IPv6 |
locale |
string | yes | e.g. en-GB, nl-NL |
targetId |
string (UUID) | yes | commercetools cart or order ID |
targetType |
string | yes | cart or order |
paymentId |
string (UUID) | yes | commercetools payment ID |
paymentMethod |
string | yes | Payment method code |
paymentMethodArgs |
object | yes | Provider-specific arguments |
successUrl |
string (URL) | yes | Redirect after successful payment |
failureUrl |
string (URL) | yes | Redirect after failed payment |
Response body: TransactionResponse
| Field | Type | Description |
|---|---|---|
status |
string | Transaction status |
payload.id |
string (UUID) | Transaction identifier |
payload.redirectURL |
string (URL) | Customer redirect URL |
POST /payment-methods
Section titled “POST /payment-methods”Returns the payment methods available for the given context (cart, locale, country).
Request body: PaymentMethodArgs
| Field | Type | Required | Description |
|---|---|---|---|
targetId |
string (UUID) | no | Cart or order to check methods for |
targetType |
string | yes | cart or order |
currency |
string | yes | e.g. EUR, USD |
country |
string | yes | e.g. NL, DE |
locale |
string | yes | e.g. en-GB, nl-NL |
device |
string | yes | web, ios, or android |
Response body: PaymentMethod[]
| Field | Type | Description |
|---|---|---|
id |
string | Method identifier |
localizedName |
string | Display name for the requested locale |
provider |
string | PSP provider key |
issuers |
array | Sub-options (e.g. iDEAL banks), each with id and name |
Shared types
Section titled “Shared types”Price
| Field | Type | Description |
|---|---|---|
currency |
string | ISO 4217 currency code |
centAmount |
number (integer format) | Amount in the smallest currency unit |

