Payment methods
The payment_method field on
/payments/collect
selects how the customer pays. The fields each method requires on
/payments/submit
differ; this page is the reference table.
payment_method | Required submit fields | Async? | OTP? | SDK widget |
|---|---|---|---|---|
wallet | ewallet_number, ewallet_pin | Sync | Sometimes | Yes |
mobile_money | mobile_money_phone_number | Async (poll) | No | Yes |
card (Mastercard hosted) | mastercard_payment_method: "HOSTED_SESSION", session_id, card_data | Async (3DS) | Possible (3DS) | Yes |
flash | flash_number, flash_pin | Sync | Sometimes | Yes |
bank_transfer | bank_account_id and friends | Async | No | Partial — bank list via SDK |
google_pay | native_pay_token (set on /collect) | Sync | No | Roadmap |
apple_pay | native_pay_token (set on /collect) | Sync | No | Roadmap |
none | (defer choice) | — | — | Yes |
Choosing one
Section titled “Choosing one”none— pass this on/collectwhen you want the SDK or the customer to pick later. You’ll then callGET /payments/transaction/{encrypted_payment_id}to fetch the available options for this transaction (computed from the merchant’s enabled methods plus the customer country).wallet— Pdirect’s e-wallet. Fastest path to a successful test.mobile_money— Onafriq-backed mobile money rails. Always asynchronous; pollGET /payments/mobile-money/status/{payment_id}or wait for a webhook.card— Mastercard. CurrentlyHOSTED_SESSIONonly;DIRECT_CAPTUREis on the roadmap. The hosted flow requires a WebView to handle the 3DS challenge — both SDKs ship one.flash— Voucher-based payments. Treat the same as wallet from the integrator’s perspective.bank_transfer— Customer scans a list of supported banks (fetched viaGET /payments/get-config-bank) and uploads proof. Settles asynchronously.google_pay/apple_pay— Native pay tokens passed at/collecttime. The SDKs do not yet expose a public method to produce these; for now, the host app is responsible.
Sync vs async settlement
Section titled “Sync vs async settlement”A synchronous flow lands in approved or declined within the
same /submit call. Wallet and flash paths typically resolve this
way unless an OTP step kicks in.
An asynchronous flow returns pending or processing from
/submit and settles later. Mobile money, card 3DS, and bank
transfer always go this route. Use webhooks for production; poll if
you must.
Sync /submit → 200 status:approvedAsync /submit → 200 status:processing ↓ (seconds to minutes later) ↓ webhook → POST notify_url status:approved OR GET /payments/status/{txn} → status:approvedField-level details
Section titled “Field-level details”wallet and flash
Section titled “wallet and flash”Both require a number and a PIN. Format constraints are loose at the gateway level — your SDK or UI is responsible for input validation.
{ "payment_method_id": "pm_wallet_001", "ewallet_number": "3005710720108954", "ewallet_pin": "048698"}Some wallet flows trigger an OTP after /submit — the response will
include status: "pending_otp_verification" and you should call
/payments/verify-otp.
mobile_money
Section titled “mobile_money”Requires only the customer’s phone number in E.164 format. The processor pushes the customer a USSD or app-prompt; once they authorise, the gateway updates and dispatches the webhook.
{ "payment_method_id": "pm_mobile_money_001", "mobile_money_phone_number": "+243998857000"}See Mobile money status polling.
card (Mastercard Hosted Session)
Section titled “card (Mastercard Hosted Session)”Three-step:
/payments/collectwithpayment_method: "card"andmastercard_payment_method: "HOSTED_SESSION". The response includes apayment_urlor session id you’ll hand to the hosted form.- Customer enters card details directly in Mastercard’s hosted form. Their card data never touches your servers — that’s the point.
/payments/submitwithsession_idandcard_datafrom the hosted session. The gateway then drives the 3DS challenge if the issuer requires one.
bank_transfer
Section titled “bank_transfer”Two-step:
/payments/get-config-bank— fetch the supported bank list, render the picker./payments/submitwithbank_account_id(the customer’s chosen bank entity),bank_account_number, andbank_account_label.
The customer then receives instructions to wire funds to a generated
beneficiary account. Status starts at pending_bank_proof_upload,
moves to bank_payment_validated once the operator confirms the
incoming wire, and eventually approved.
Native pay (google_pay, apple_pay)
Section titled “Native pay (google_pay, apple_pay)”The token lives on
/payments/collect
itself, not on /submit:
{ "payment_method": "google_pay", "native_pay_token": "<opaque token from Google Pay button>", "native_pay_token_type": "PAYMENT_GATEWAY"}/submit is then a no-op (the token already authorised the
amount). The status is approved synchronously when the token
validates.
Currency overrides per method
Section titled “Currency overrides per method”If a customer pays with a wallet denominated in a different currency
than the merchant priced in, set transactional_currency on
/payments/collect:
{ "amount": "12.50", "currency": "usd", "payment_method": "wallet", "transactional_currency": "cdf"}The gateway converts at the rate active at session-mint time and
debits in transactional_currency. The merchant settles in
currency.
See also
Section titled “See also”- Quickstart — wallet end-to-end
- Mobile money status polling
- Card payments with 3DS
- API reference: Payments