Fonepay PG Web Redirect
Complete reference for the Fonepay PG web redirect gateway integration — flow, signature generation, verification, env vars, and implementation details.
Fonepay PG Web Redirect
Audience: Backend developers, QA engineers Scope: Fonepay PG web redirect integration, HMAC-SHA512 signature, XML verification, test environment
Overview
Fonepay is a major Nepali payment gateway. The PG web redirect flow uses HMAC-SHA512 to sign a GET redirect URL. The backend generates the URL; the frontend navigates to it directly (no form POST).
| Property | Value |
|---|---|
| Gateway name | fonepay |
| Initiation type | redirect |
| Signature algorithm | HMAC-SHA512 (hex) |
| Amount format | NPR rupees (string, 2 decimal places) |
| Verification response | XML |
Payment Flow
Initiation Signature
The backend computes DV as HMAC-SHA512 of the initiation parameters in a specific order:
message = `${PID},${MD},${PRN},${AMT},${CRN},${DT},${R1},${R2},${RU}`
DV = HMAC-SHA512(merchantSecret, message).hex()Redirect URL Parameters
| Param | Description | Example |
|---|---|---|
PID | Merchant code | TEST_MERCHANT |
MD | Payment mode (always P) | P |
PRN | Unique transaction reference | fonepay-42-1750464000000 |
AMT | Amount in NPR major unit | 3266.99 |
CRN | Currency (always NPR) | NPR |
DT | Date in MM/DD/YYYY format | 06/21/2026 |
R1 | Remarks 1 (reference type) | order |
R2 | Remarks 2 (reference ID) | 42 |
DV | HMAC-SHA512 signature (hex) | a1b2c3d4... |
RU | Callback URL | https://api.example.com/api/payments/redirect/1/success |
Callback Parameters
After the user completes payment, Fonepay redirects to RU with these query params:
| Param | Description | Example |
|---|---|---|
PRN | Transaction reference | fonepay-42-1750464000000 |
PID | Merchant code | TEST_MERCHANT |
PS | Payment status | completed |
RC | Response code | 00 |
UID | Unique transaction ID | uid-abc-123 |
BC | Bank code | NMB |
INI | Initiator | fonepay |
P_AMT | Paid amount | 3266.99 |
R_AMT | Refund amount | 0 |
DV | HMAC-SHA512 signature (hex, uppercase) | A1B2C3D4... |
Callback DV Validation
Before calling the verification API, the backend validates the callback DV to detect tampering:
responseString = `${PRN},${PID},${PS},${RC},${UID},${BC},${INI},${P_AMT},${R_AMT}`
expectedDV = HMAC-SHA512(merchantSecret, responseString).hex().toUpperCase()The comparison uses timingSafeEqual() to prevent timing attacks. If the DV does not match, the callback is rejected with PAYMENT_FONEPAY_CALLBACK_INVALID.
Verification Request
After validating the callback DV, the backend calls Fonepay's server-to-server verification endpoint:
dvString = `${PID},${AMT},${PRN},${BID},${UID}`
DV = HMAC-SHA512(merchantSecret, dvString).hex()GET {FONEPAY_PG_URL}/api/merchantRequest/verificationMerchant?PRN=...&PID=...&BID=...&AMT=...&UID=...&DV=...The request has a configurable timeout (default 10s) and retries up to 3 times with full-jitter exponential backoff on network errors and transient HTTP errors (502/503/504/408).
XML Verification Response
The verification endpoint returns XML:
<response>
<success>true</success>
<response_code>successful</response_code>
<txnAmount>3266.99</txnAmount>
<amount>3266.99</amount>
<bankCode>NMB</bankCode>
<initiator>fonepay</initiator>
<message>Successful</message>
<statusCode>200</statusCode>
<uniqueId>uid-abc-123</uniqueId>
</response>The payment is marked completed only when:
String(parsed.response.success).toLowerCase() === "true" &&
String(parsed.response.response_code).toLowerCase() === "successful"The amount is extracted from txnAmount and converted from major unit string to minor unit (paisa) via majorUnitStringToMinorUnit().
Configuration
Environment Variables
| Variable | Required | Description | Example |
|---|---|---|---|
FONEPAY_PG_URL | ✓ | Base URL for Fonepay PG API | https://clientapi.fonepay.com |
FONEPAY_PG_MERCHANT_CODE | ✓ | Merchant PID/code from Fonepay portal | your_merchant_code |
FONEPAY_PG_MERCHANT_SECRET | ✓ | HMAC-SHA512 signing secret | your_merchant_secret |
FONEPAY_VERIFY_TIMEOUT_MS | optional | Verification request timeout in ms | 10000 (default) |
Test / Sandbox Environment
Fonepay provides sandbox credentials from the merchant portal. There are no publicly documented test credentials for the Fonepay sandbox. Contact Fonepay to obtain test merchant credentials.
Frontend Integration
When initiationType is "redirect", the frontend navigates directly to the returned URL:
if (data.initiationType === "redirect") {
window.location.href = data.redirectUrl;
}Fonepay is a GET redirect gateway (no form POST). The redirectUrl contains all signed parameters as query string values. The gatewayPayload is empty ({}) for redirect-type gateways.
Implementation Reference
Gateway file: apps/api/src/modules/payment/gateways/fonepay.gateway.ts
Key methods:
initiate()— generatesPRN, computes HMAC-SHA512DV, builds redirect URL with all query paramsparseRedirectPayload()— validates callbackDVusingtimingSafeEqual, extractsPRNasgatewayTransactionIdverify()— builds verification requestDV, calls Fonepay verification endpoint with retry + timeout, parses XML response, returns{ success, amountNpr }retryFetch()— bounded retry helper (3 attempts, full-jitter exponential backoff)computeHmac()— HMAC-SHA512 helpersafeEqual()—timingSafeEqualwrapper with buffer length safety check
Security Checklist
- HMAC-SHA512 signature computed server-side — secret key never sent to frontend
- Callback
DVvalidated viatimingSafeEqualbefore any processing - Server-to-server verification call for independent confirmation
- Bounded retry with exponential backoff on transient verification failures
- Explicit timeout on all external HTTP calls (default 10s)
- Secret key stored in environment variable (
FONEPAY_PG_MERCHANT_SECRET), never hardcoded - No sensitive data logged (merchant secret never in log output)
- Circuit breaker noted as tech-debt (tracked in feature plan)
eSewa ePay v2
Complete reference for the eSewa ePay v2 gateway integration — flow, signature generation, verification, test credentials, and implementation details.
Cash on Delivery (COD)
COD is a pending-collection gateway — no redirect, no webhook, and no paid/completed status until admin records cash.