Payment — Common cases
Method missing at checkout
Check master toggle, BU/provider setting, category availability, site scope, and payment option rule.
Real-world example: A parent at site A does not see Direct Debit at checkout. → Determine whether the method is hidden by configuration or by a bug. → The provider is not enabled for site A's BU, so the method is correctly hidden and checkout flow should not be changed.
PayNow succeeds but UI does not update
Read provider result/webhook, batch/payment status, and checkout success method resolution. Webhook can arrive after redirect, so the UI must tolerate short pending windows.
Real-world example: A customer pays by card, returns to a "processing" screen for a few seconds, then sees success. → The UI must not mark the payment failed too early. → Webhook arrives after redirect, so keep a short pending state and update when the webhook lands.
Direct Debit customer created in the wrong BU
AccountPaymentCustomer must be unique/active by (AccountId, BusinessUnitId, PaymentProvider). Missing BU scope is a boundary/security issue.
Real-world example: An account belongs to two BUs; setting Direct Debit in BU2 points to BU1's customer. → Prevent payment leakage across organizations. → Query is missing the BU filter, so treat it as a boundary bug and include
BusinessUnitIdin the unique condition.
Deposit double submit
Check order lock, callback idempotency, and batch state. Deposit must not create multiple transaction slots for the same locked order.
Real-world example: A customer clicks the deposit button twice because the network is slow. → Avoid charging deposit twice for one order. → Order lock + callback idempotency block the second slot while the lock is active.
Success message shows the wrong method
Compare payment-success-message-by-method, checkout confirmation type guard, and method resolution. Copy should reflect the resolved method, not route assumptions.
Real-world example: A customer pays by Direct Debit but the success screen shows PayNow copy. → The message must match the actual method so the customer is not misled. → Resolve copy from the transaction's real method, not from the checkout route.