cURL
Node.js
PHP
Laravel
Python
Java
curl -X POST "http://sandbox.mynagad.com:10080/remote-payment-gateway-1.0/api/dfs/check-out/complete/MTEwNzE2NTMxODgwNC42ODc0NTAwMDAwMzEzMjQuTkFHMTU3MzEyMzk5MzE1NzMuZDA3Mjg5YTQxNDRhNWVjYzcxYjU=" \
-H "X-KM-IP-V4: 103.100.12.34" \
-H "X-KM-Client-Type: PC_WEB" \
-H "X-KM-Api-Version: v-0.2.0" \
-H "Content-Type: application/json" \
-d '{
"merchantCallbackURL": "http://yourdomain.com/nagad/callback",
"additionalMerchantInfo": {
"serviceName": "E-Commerce Checkout",
"serviceLogoURL": "https://yourdomain.com/logo.png"
},
"sensitiveData": "PSFButymlhAlKrOjiG+RKrz4uETizC9Z0mueKMRvqi62Ctz+o4AQ3+8Z/...",
"signature": "hANZKhCwPZEbP5brZ6Nh9JnOgcrkBdOSnznPN0Mk5vS0rs3Ta/gPeCZH2X..."
}'
const crypto = require('crypto');
async function completeNagadOrder({
paymentReferenceId,
challengeFromInit,
orderId,
amount,
callbackUrl,
clientIp,
merchantId,
nagadPublicKey,
merchantPrivateKey,
baseUrl
}) {
// 1. Prepare sensitive order payload
const sensitivePayload = JSON.stringify({
merchantId,
orderId,
currencyCode: '050',
amount: Number(amount).toFixed(2),
challenge: challengeFromInit,
});
// 2. Encrypt with Nagad Public Key (PKCS1 Padding)
const sensitiveData = crypto.publicEncrypt(
{ key: nagadPublicKey, padding: crypto.constants.RSA_PKCS1_PADDING },
Buffer.from(sensitivePayload)
).toString('base64');
// 3. Sign with Merchant Private Key (SHA1withRSA)
const signer = crypto.createSign('RSA-SHA1');
signer.update(sensitivePayload);
signer.end();
const signature = signer.sign(merchantPrivateKey, 'base64');
// 4. Send POST to Complete/Place Order Endpoint
const endpoint = `${baseUrl}/remote-payment-gateway-1.0/api/dfs/check-out/complete/${paymentReferenceId}`;
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-KM-IP-V4': clientIp,
'X-KM-Client-Type': 'PC_WEB',
'X-KM-Api-Version': 'v-0.2.0',
},
body: JSON.stringify({
sensitiveData,
signature,
merchantCallbackURL: callbackUrl,
additionalMerchantInfo: {
serviceName: "Digital Store",
}
}),
});
const resJson = await response.json();
// 5. Returns { callBackUrl: "https://sandbox.mynagad.com/.../payment/..." }
return resJson.callBackUrl;
}
<?php
function placeNagadOrder($paymentRefId, $challenge, $orderId, $amount, $callbackUrl, $clientIp, $merchantId, $nagadPubKey, $merchantPrivKey, $baseUrl) {
// 1. Sensitive Data Payload
$sensitivePayload = json_encode([
'merchantId' => $merchantId,
'orderId' => $orderId,
'currencyCode' => '050',
'amount' => number_format((float)$amount, 2, '.', ''),
'challenge' => $challenge
]);
// 2. Encrypt sensitive payload
$publicKey = openssl_pkey_get_public($nagadPubKey);
openssl_public_encrypt($sensitivePayload, $encryptedData, $publicKey, OPENSSL_PKCS1_PADDING);
$sensitiveData = base64_encode($encryptedData);
// 3. Sign sensitive payload
$privateKey = openssl_pkey_get_private($merchantPrivKey);
openssl_sign($sensitivePayload, $sig, $privateKey, OPENSSL_ALGO_SHA1);
$signature = base64_encode($sig);
// 4. Send Request
$url = "{$baseUrl}/remote-payment-gateway-1.0/api/dfs/check-out/complete/{$paymentRefId}";
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-KM-IP-V4: ' . $clientIp,
'X-KM-Client-Type: PC_WEB',
'X-KM-Api-Version: v-0.2.0'
],
CURLOPT_POSTFIELDS => json_encode([
'sensitiveData' => $sensitiveData,
'signature' => $signature,
'merchantCallbackURL' => $callbackUrl,
'additionalMerchantInfo' => [
'serviceName' => 'Online Store'
]
])
]);
$response = curl_exec($ch);
curl_close($ch);
$res = json_decode($response, true);
// Redirect User to Nagad Hosted Gateway URL
return $res['callBackUrl'];
}
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
class NagadPaymentService {
public function placeOrder(string $paymentRefId, string $challenge, string $orderId, float $amount, string $clientIp): string {
$merchantId = config('nagad.merchant_id');
$baseUrl = config('nagad.base_url');
$sensitivePayload = json_encode([
'merchantId' => $merchantId,
'orderId' => $orderId,
'currencyCode' => '050',
'amount' => number_format($amount, 2, '.', ''),
'challenge' => $challenge,
]);
// Encrypt
$publicKey = openssl_pkey_get_public(config('nagad.nagad_public_key'));
openssl_public_encrypt($sensitivePayload, $encryptedData, $publicKey, OPENSSL_PKCS1_PADDING);
$sensitiveData = base64_encode($encryptedData);
// Sign
$privateKey = openssl_pkey_get_private(config('nagad.merchant_private_key'));
openssl_sign($sensitivePayload, $signatureRaw, $privateKey, OPENSSL_ALGO_SHA1);
$signature = base64_encode($signatureRaw);
// Request
$response = Http::withHeaders([
'X-KM-IP-V4' => $clientIp,
'X-KM-Client-Type' => 'PC_WEB',
'X-KM-Api-Version' => 'v-0.2.0',
'Content-Type' => 'application/json',
])->post("{$baseUrl}/remote-payment-gateway-1.0/api/dfs/check-out/complete/{$paymentRefId}", [
'sensitiveData' => $sensitiveData,
'signature' => $signature,
'merchantCallbackURL' => route('nagad.callback'),
'additionalMerchantInfo' => [
'serviceName' => config('app.name'),
]
]);
if ($response->successful() && isset($response['callBackUrl'])) {
return $response['callBackUrl'];
}
throw new \Exception('Nagad Place Order Failed: ' . $response->body());
}
}
import json
import base64
import requests
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
from Crypto.Signature import PKCS1_v1_5 as Signature_PKCS1_v1_5
from Crypto.Hash import SHA1
def place_nagad_order(payment_ref_id, challenge, order_id, amount, callback_url, client_ip, merchant_id, nagad_pub_pem, merchant_priv_pem, base_url):
# 1. Sensitive JSON
sensitive_dict = {
"merchantId": merchant_id,
"orderId": order_id,
"currencyCode": "050",
"amount": f"{amount:.2f}",
"challenge": challenge
}
sensitive_json = json.dumps(sensitive_dict)
# 2. Encrypt with Nagad Public Key
npg_key = RSA.import_key(nagad_pub_pem)
cipher = Cipher_PKCS1_v1_5.new(npg_key)
sensitive_data_b64 = base64.b64encode(cipher.encrypt(sensitive_json.encode('utf-8'))).decode('utf-8')
# 3. Sign with Merchant Private Key
ms_key = RSA.import_key(merchant_priv_pem)
signer = Signature_PKCS1_v1_5.new(ms_key)
h = SHA1.new(sensitive_json.encode('utf-8'))
signature_b64 = base64.b64encode(signer.sign(h)).decode('utf-8')
# 4. Make POST Request
url = f"{base_url}/remote-payment-gateway-1.0/api/dfs/check-out/complete/{payment_ref_id}"
headers = {
"Content-Type": "application/json",
"X-KM-IP-V4": client_ip,
"X-KM-Client-Type": "PC_WEB",
"X-KM-Api-Version": "v-0.2.0"
}
payload = {
"sensitiveData": sensitive_data_b64,
"signature": signature_b64,
"merchantCallbackURL": callback_url,
"additionalMerchantInfo": {
"serviceName": "Store Checkout"
}
}
res = requests.post(url, headers=headers, json=payload)
return res.json()["callBackUrl"]
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;
public class NagadPlaceOrderService {
public static String placeOrder(String paymentRefId, String challenge, String orderId, double amount, String callbackUrl, String clientIp, String merchantId, String nagadPubPem, String merchantPrivPem, String baseUrl) throws Exception {
JSONObject sensitiveObj = new JSONObject();
sensitiveObj.put("merchantId", merchantId);
sensitiveObj.put("orderId", orderId);
sensitiveObj.put("currencyCode", "050");
sensitiveObj.put("amount", String.format("%.2f", amount));
sensitiveObj.put("challenge", challenge);
String sensitiveData = NagadCrypto.encrypt(sensitiveObj.toString(), nagadPubPem);
String signature = NagadCrypto.sign(sensitiveObj.toString(), merchantPrivPem);
JSONObject requestBody = new JSONObject();
requestBody.put("sensitiveData", sensitiveData);
requestBody.put("signature", signature);
requestBody.put("merchantCallbackURL", callbackUrl);
String endpoint = baseUrl + "/remote-payment-gateway-1.0/api/dfs/check-out/complete/" + paymentRefId;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(endpoint))
.header("Content-Type", "application/json")
.header("X-KM-IP-V4", clientIp)
.header("X-KM-Client-Type", "PC_WEB")
.header("X-KM-Api-Version", "v-0.2.0")
.POST(HttpRequest.BodyPublishers.ofString(requestBody.toString()))
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
JSONObject resObj = new JSONObject(response.body());
return resObj.getString("callBackUrl");
}
}