PPayNow Docs
Menu — Account + OTP Flow

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

  1. Account number input + institution dropdown.
  2. After submit: "OTP sent to +218 ●●●●●●●89" and a 6-digit OTP input.
  3. "Awaiting confirmation" panel while the switch settles.
  4. Receipt with transaction ID, debited account (masked), and amount.