Skip to main content

Nagad

Nagad Checkout API v0.2.0 integration with RSA encryption.

Installation

npm install @foxses/pay-nagad

How It Works

Nagad uses RSA encryption for all sensitive data exchange:

  1. Initialize — encrypt merchant info with Nagad's public key → get paymentReferenceId
  2. Complete — encrypt order details → get callBackUrl (checkout URL)
  3. Redirect user to callBackUrl to pay on Nagad
  4. Callback — Nagad calls your callbackUrl with payment_ref_id
  5. Verify — GET request to confirm payment status

createPayment() handles steps 1 and 2 automatically.

RSA Keys Setup

Nagad requires a pair of RSA keys:

KeyPurposeWho generates
Merchant Private KeySign & decrypt responsesYou (merchant)
Merchant Public KeyUploaded to Nagad portalYou (merchant)
Nagad Public KeyEncrypt sensitive dataNagad (download from portal)

Generate key pair:

# Generate private key
openssl genrsa -out merchant_private.pem 2048

# Extract public key
openssl rsa -in merchant_private.pem -pubout -out merchant_public.pem

Upload merchant_public.pem to Nagad merchant portal. Download Nagad's public key from the portal.

Configuration

gateway.use("nagad", {
merchantId: "YOUR_MERCHANT_ID", // required
merchantNumber: "01XXXXXXXXX", // required — Nagad merchant number
privateKey: "YOUR_RSA_PRIVATE_KEY", // required — base64 or PEM
nagadPublicKey: "NAGAD_RSA_PUBLIC_KEY", // required — base64 or PEM
callbackUrl: "https://yoursite.com/nagad/callback", // required
successUrl: "https://yoursite.com/payment/success", // required
failureUrl: "https://yoursite.com/payment/failure", // required
apiVersion: "v-0.2.0", // optional, default: "v-0.2.0"
sandbox: true, // optional, default: true
});

Keys can be provided as:

  • Raw base64 string (without PEM headers)
  • Full PEM string (with -----BEGIN...----- headers)

Both formats are supported automatically.

Create Payment

const payment = await gateway.createPayment("nagad", {
amount: 500,
currency: "BDT",
orderId: "ORDER-001", // must be unique
metadata: {
ip: "CLIENT_IP_ADDRESS", // required — customer's IP address
},
});

Important: Nagad requires the client IP address. Pass it via metadata.ip. For local development, use "103.100.200.100" as fallback.

Response:

{
transactionId: "NAG-REF-XXX", // paymentReferenceId — save this
provider: "nagad",
amount: 500,
currency: "BDT",
status: "pending",
checkoutUrl: "http://sandbox.mynagad.com:10080/...", // redirect user here
}

Verify Payment

Call after Nagad sends callback with payment_ref_id.

const verified = await gateway.verifyPayment("nagad", {
transactionId: paymentRefId,
});

Response:

{
transactionId: "NAG-TRX-XXX", // Nagad issuerPaymentRefNo
provider: "nagad",
amount: 500,
currency: "BDT",
status: "completed",
}

Get Payment Status

const status = await gateway.getPaymentStatus("nagad", paymentRefId);

Callback Handling

Nagad sends a GET request to your callbackUrl:

GET /nagad/callback?payment_ref_id=xxx&order_id=ORDER-001&status=Success
ParamValue
payment_ref_idUse this in verifyPayment
statusSuccess / Fail / Cancel
app.get("/nagad/callback", async (req, res) => {
const { payment_ref_id, status } = req.query;

if (status !== "Success") {
return res.redirect("/payment/failed");
}

const verified = await gateway.verifyPayment("nagad", {
transactionId: payment_ref_id as string,
});

if (verified.status === "completed") {
res.redirect("/payment/success");
}
});

Status Mapping

Nagad Statusfoxses-pay Status
Successcompleted
PENDINGpending
ABORTEDcancelled
FAILfailed

Production Endpoints

EnvironmentBase URL
Sandboxhttp://sandbox.mynagad.com:10080
Productionhttps://api.mynagad.com

Credentials

Get from Nagad Merchant Portal