Integration Guide
Account + OTP Flow
Two variants — OnePay bank account and PayNow wallet — both validate, send an OTP, then settle.
When the customer chooses the Account tab they enter an account number (or a PayNow wallet ID) and get an OTP. The flow has two variants that share the same screens but route to different OnePay endpoints.
Variant 1: OnePay bank account
The customer enters a bank account number and picks an institution.
Browser Gateway SSR OnePay
│ │ │
│ submit account │ │
│────────────────▶│ POST /web-payment/initiate-payment-request
│ │─────────────────────────▶
│ │ ◀── { otp sent, dphReference, customerName, ... }
│ ◀── OTP screen │ │
│ │ │
│ submit OTP │ │
│────────────────▶│ POST /payment-request │
│ │─────────────────────────▶
│ │ ◀── { success: true, data: "Payment requested." }
│ ◀── waiting screen + status poll active │
│ │ │
│ POST /check-status (every 3s, then 10s) │
│────────────────▶│ POST /check-status │
│ │─────────────────────────▶
│ │ ◀── { paymentStatus: SUCCESS, transactionId, ... }
│ ◀── receipt │ │
The key thing to know: /payment-request is acknowledgement-only. It returns { success: true, data: "Payment requested." } and the actual debit-and-credit happens asynchronously on the OnePay switch. The gateway's status poller chases the real terminal state.
Variant 2: PayNow wallet
Same screens, different endpoints. The institution code is PayNow (or paynow-wallet, etc).
| Step | OnePay account | PayNow wallet |
|---|---|---|
| Validate account | /web-payment/initiate-payment-request |
/web-payment/paynow/initiate-payment-request |
| Submit OTP | /payment-request (ack only) |
/paynow/process-payment-request (may return terminal state) |
PayNow wallet's process-payment-request can return a terminal success or failed state in the OTP response itself, in which case the gateway short-circuits to the receipt without further polling.
State transitions
pending → otpRequired → waitingPayment → success for OnePay.
pending → otpRequired → authorized → success for PayNow wallet (with the authorized → success hop covered by a one-shot /check-status call after OTP).
Both variants accept the fast-path otpRequired → success if the backend settles immediately.
Polling stops during OTP entry
While the customer is on the OTP screen the status poller is off — there's nothing to chase, the user is typing. Polling re-activates the moment the OTP submission returns waitingPayment. See Status Polling.
Validation that fires server-side
validateAccount calls /web-payment/initiate-payment-request, which validates the account on OnePay's side and triggers the OTP send. If the account is invalid, the response is a 4xx with a code like INVALID_ACCOUNT — the SDK turns this into a typed PaymentApiException you can surface to the user.
What the customer sees
- Account number input + institution dropdown.
- After submit: "OTP sent to +218 ●●●●●●●89" and a 6-digit OTP input.
- "Awaiting confirmation" panel while the switch settles.
- Receipt with transaction ID, debited account (masked), and amount.