Callback Lifecycle
Every payment button share the same lifecycle. The four callbacks in CallbackHandlers map to distinct stages.
Flow Diagram
sequenceDiagram
participant User
participant SDK
participant Merchant Backend
participant Provider SDK
User->>SDK: Click payment button
SDK->>Merchant Backend: onClick(identity, paymentMethodData)
Merchant Backend-->>SDK: OrderResult { orderId }
SDK->>Provider SDK: Process payment with orderId
Provider SDK->>User: Show payment sheet
User->>Provider SDK: Authorize payment
Provider SDK-->>SDK: Payment approved
SDK->>Merchant Backend: onApprove(ApprovalData)Stage 1 — onClick
onClick: (identity: ProviderIdentity, paymentMethodData?: unknown) => Promise<OrderResult>Triggered when the user clicks a payment button.
| Parameter | Description |
|---|---|
identity | Contains providerProtocolType and paymentMethodType — identifies which button was clicked |
paymentMethodData | Provider-specific payment data (e.g. Adyen state.data, nonce). Shape varies by provider. |
What to do here: Call your backend to create or reserve an order. Return an OrderResult with at minimum { orderId: string }.
For providers that need a gateway-specific payload (e.g. Adyen), also populate checkoutData.id with the gateway order/payment ID.
See the Backend API docs for the expected request and response shapes when creating an order server-side.
If onClick throws or returns a rejected promise, the payment flow is aborted. The onError callback will fire.
Stage 2 — Provider SDK Processes Payment
After onClick resolves, the SDK passes orderId (and any checkoutData) to the provider SDK. The provider SDK takes over: it shows the wallet payment sheet, handles authentication, consent forms, 3DS challenges, etc.
This stage is entirely managed by the third-party provider SDK — no CollanaPay callbacks fire during this step.
Stage 3 — onApprove
onApprove: (data: ApprovalData) => voidFired when the provider SDK confirms the payment was approved by the user. The ApprovalData object contains:
| Field | Type | Description |
|---|---|---|
providerProtocolType | string | The protocol that processed the payment |
paymentMethodType | string | The payment method used |
orderId | string | The order ID from your onClick result |
transactionId | string? | Transaction ID, if available |
payerInfo | unknown? | Provider-specific payer data |
returnUrl | string? | Redirect URL, if applicable |
Recommended actions: Redirect to a success page, or trigger a server-side capture if you used intent: 'authorize'.
Stage 4 — onCancel
onCancel: (identity: ProviderIdentity) => voidFired when the user dismisses the payment dialog without completing the payment.
Recommended actions: Restore any reserved inventory, show a user-friendly "payment was cancelled" message, and allow the user to try again.
Stage 5 — onError
onError: (error: PaymentError) => voidFired for provider SDK errors, network failures, or when onClick rejects. The PaymentError object contains:
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
message | string | Human-readable description |
providerProtocolType | string | Protocol where the error occurred |
paymentMethodType | string | Payment method where the error occurred |
Recommended actions: Log the error for monitoring, show a user-friendly error message, and allow the user to retry.
Because providers render via
Promise.allSettled, one provider'sonErrordoes not prevent other providers from rendering. Each failure triggers a separateonErrorcall.
