Integration Guide
Browser Handoff
Query params the gateway expects, how the return URL is validated, and what happens on cancel.
After the merchant server returns { redirectUrl, paymentId }, the browser navigates to the gateway. The redirect URL carries everything the gateway needs to bootstrap the checkout session.
Query parameters
| Param | Required | Example | Notes |
|---|---|---|---|
merchant_id |
yes | ivv_demo_001 |
Display + audit. |
reference |
yes | inv_demo_001 |
Your order ID. |
amount_minor |
yes | 25900 |
Smallest currency unit. |
currency |
yes | LYD |
ISO-4217. |
payment_id |
yes | wpr_42 |
Returned by /web-payment/initiate. |
token |
yes | eyJhbGciOi… |
Bearer JWT for downstream endpoints. |
locale |
no | en / ne |
Defaults to en. |
return_url |
no | https://shop.example/cart |
Where to send the customer on cancel / completion. |
selected_method |
no | qr / account |
Pre-select a tab. |
selected_qr_provider |
no | OnePay / PayNow |
Pre-select a QR rail. |
Currency minor units
The amount is always in the smallest unit. PayNow's primary market currencies use 3 fraction digits, not the more common 2:
LYD,BHD,KWD,OMR,TND→ 3 digits (25900=25.900 LYD)- Most others (
USD,EUR, …) → 2 digits (25900=259.00 USD) JPY,KRW→ 0 digits
The helper currencyFractionDigits(currency) and formatCurrencyAmount(amountMinor, currency) in paynow_core handle this for you.
Return URL safety
The gateway runs validateReturnUrl(url) from paynow_core. It rejects:
- relative paths (
/cart) - non-HTTP(S) schemes (
ftp://…,javascript:…) - bare hostnames (
shop— must contain a.or be a loopback host)
When validation fails the gateway falls back to https://www.fawri.ly/. This protects against open-redirect bugs where a malicious return URL could phish your customer.
Locale
Two locales ship today:
en— English (default)ne— Nepali
The gateway picks up ?locale= and applies the matching translation set from paynow_core/checkout_localization.dart. Adding a locale is a single map entry plus translated strings — see the source.
What if the customer hits "Back"?
The gateway exposes a "Back to store" link (visible on the receipt and on bootstrap-error screens) pointing at the validated return_url. There's no separate "cancel" callback — your server should treat any paymentId that never reaches a terminal state (within your business timeout) as abandoned.