Payment — Architecture & data
Shared checkout flow
Method-specific flows
| Method | Flow |
|---|---|
| PayLater | Validate availability, persist pending/selected option, let the booking/subscription flow continue. |
| PayNow/Windcave | Init checkout, redirect the customer, receive result/webhook, prevent duplicate retry. |
| Direct Debit/Kiwi | Create or read the payment customer by account+BU+provider, create a debit batch, process provider status. |
| Deposit | Check whole-batch eligibility, snapshot amount/percentage, lock the order, provider checkout, webhook confirm. |
Zero-amount checkout
- Bypass the provider for every method when total =
0; no session/hpp/redirect is created. - Auto-confirm intent must come from authoritative payment state, not from display text/payable amount.
Windcave integration mode
- Mode
XML(legacy/PxPay) vsREST; stored per business unit payment setting. - Null/missing value or the BU already has Windcave → resolve
XML; no operational intervention needed. - Every Windcave operation (init checkout, callback/result parsing, verification/query, scheduler recovery, test connection) branches on the stored mode.
- Test Connection only validates the active protocol; it does not depend on account/payer setup.
- REST (
/api/v1/sessions) is only used when mode isREST; useIHttpClientFactoryfor all outbound REST. - REST mode: a session with no transaction yet (
processing) → log clearly + mark the batchDeclined, do not mapUnknown.
Real-world example: A BU has just enabled Windcave but not chosen a mode. → Existing checkout is not broken. → Mode resolves to XML and checkout continues through PxPay as before.
Guardrails
- Every access to
AccountPaymentCustomermust be BU-scoped; cross-BU is a security error. - Provider webhook/result must be idempotent because the provider may call back multiple times.
- Master toggle/payment settings must be checked before exposing a method in the UI.
- Deposit eligibility must fail the whole batch if one booking is ineligible.
- Controllers only orchestrate; business logic lives at the service/domain boundary.
Main data
| Group | Data |
|---|---|
| Customer token | AccountPaymentCustomer by account, BU, provider. |
| Payment batch | DirectPaymentBatch, DirectPayment, status/error/provider reference. |
| Checkout lock | Booking/order lock or deposit snapshot to prevent double submit. |
| Settings | BU/provider settings, method toggle, category availability. |
| Provider callbacks | Result URL, notification URL, webhook payload/error. |