cURL
Node.js
PHP
Laravel
Python
Java
curl -X POST "http://sandbox.mynagad.com:10080/remote-payment-gateway-1.0/api/dfs/check-out/initialize/687450000031324/ORD123456?locale=BN" \
-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 '{
"accountNumber": "01745000003",
"dateTime": "20260909120000",
"sensitiveData": "G58zmiHNIT+CM74fQyL6+w0WdPXioW6oZy1piRABi1ssj3vt89LZoLPh/...",
"signature": "AlhsvF6ZdEUbDqXeeHeS6Ab9e+/W8U4pxZjMr5+qx5aGIDj21R6qGiYFiHm9..."
}'
const crypto = require('crypto');
async function initializeNagadPayment({ orderId, clientIp, merchantId, nagadPublicKey, merchantPrivateKey, baseUrl }) {
// 1. Generate 40-char random challenge hex
const challenge = crypto.randomBytes(20).toString('hex');
// 2. Format dateTime (yyyyMMddHHmmss)
const now = new Date();
const pad = (n) => String(n).padStart(2, '0');
const dateTime = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
// 3. Prepare sensitive JSON payload
const sensitivePayload = JSON.stringify({
merchantId,
datetime: dateTime,
orderId,
challenge,
});
// 4. Encrypt sensitive data with Nagad Public Key (PKCS1 Padding)
const sensitiveData = crypto.publicEncrypt(
{ key: nagadPublicKey, padding: crypto.constants.RSA_PKCS1_PADDING },
Buffer.from(sensitivePayload)
).toString('base64');
// 5. Sign sensitive payload with Merchant Private Key (SHA1withRSA)
const signer = crypto.createSign('RSA-SHA1');
signer.update(sensitivePayload);
signer.end();
const signature = signer.sign(merchantPrivateKey, 'base64');
// 6. Make HTTP POST Request
const endpoint = `${baseUrl}/remote-payment-gateway-1.0/api/dfs/check-out/initialize/${merchantId}/${orderId}?locale=BN`;
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({
dateTime,
sensitiveData,
signature,
}),
});
const resJson = await response.json();
// 7. Decrypt Nagad Response sensitiveData using Merchant Private Key
const decryptedBuffer = crypto.privateDecrypt(
{ key: merchantPrivateKey, padding: crypto.constants.RSA_PKCS1_PADDING },
Buffer.from(resJson.sensitiveData, 'base64')
);
const decryptedData = JSON.parse(decryptedBuffer.toString('utf8'));
return {
paymentReferenceId: decryptedData.paymentReferenceId,
challenge: decryptedData.challenge || decryptedData.random,
};
}
<?php
function initializeNagadOrder($orderId, $clientIp, $merchantId, $nagadPubKey, $merchantPrivKey, $baseUrl) {
// 1. Generate challenge & timestamp
$challenge = bin2hex(random_bytes(20));
$dateTime = date("YmdHis");
// 2. Sensitive Payload
$sensitivePayload = json_encode([
'merchantId' => $merchantId,
'datetime' => $dateTime,
'orderId' => $orderId,
'challenge' => $challenge
]);
// 3. Encrypt sensitive payload
$publicKey = openssl_pkey_get_public($nagadPubKey);
openssl_public_encrypt($sensitivePayload, $encryptedData, $publicKey, OPENSSL_PKCS1_PADDING);
$sensitiveData = base64_encode($encryptedData);
// 4. Sign sensitive payload
$privateKey = openssl_pkey_get_private($merchantPrivKey);
openssl_sign($sensitivePayload, $sig, $privateKey, OPENSSL_ALGO_SHA1);
$signature = base64_encode($sig);
// 5. Send POST Request via cURL
$url = "{$baseUrl}/remote-payment-gateway-1.0/api/dfs/check-out/initialize/{$merchantId}/{$orderId}?locale=BN";
$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([
'dateTime' => $dateTime,
'sensitiveData' => $sensitiveData,
'signature' => $signature
])
]);
$response = curl_exec($ch);
curl_close($ch);
$resJson = json_decode($response, true);
// 6. Decrypt response sensitiveData
openssl_private_decrypt(base64_decode($resJson['sensitiveData']), $decryptedData, $privateKey, OPENSSL_PKCS1_PADDING);
$plainResponse = json_decode($decryptedData, true);
return [
'paymentReferenceId' => $plainResponse['paymentReferenceId'],
'challenge' => $plainResponse['challenge'] ?? $plainResponse['random']
];
}
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class NagadPaymentService {
public function initializeSession(string $orderId, string $clientIp): array {
$merchantId = config('nagad.merchant_id');
$baseUrl = config('nagad.base_url');
$dateTime = now()->format('YmdHis');
$challenge = Str::random(40);
$sensitivePayload = json_encode([
'merchantId' => $merchantId,
'datetime' => $dateTime,
'orderId' => $orderId,
'challenge' => $challenge,
]);
// Encrypt with Nagad Public Key
$publicKey = openssl_pkey_get_public(config('nagad.nagad_public_key'));
openssl_public_encrypt($sensitivePayload, $encryptedData, $publicKey, OPENSSL_PKCS1_PADDING);
$sensitiveData = base64_encode($encryptedData);
// Sign with Merchant Private Key
$privateKey = openssl_pkey_get_private(config('nagad.merchant_private_key'));
openssl_sign($sensitivePayload, $signatureRaw, $privateKey, OPENSSL_ALGO_SHA1);
$signature = base64_encode($signatureRaw);
// Call Nagad API
$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/initialize/{$merchantId}/{$orderId}?locale=BN", [
'dateTime' => $dateTime,
'sensitiveData' => $sensitiveData,
'signature' => $signature,
]);
if ($response->failed()) {
throw new \Exception('Nagad Init Failed: ' . $response->body());
}
// Decrypt response
openssl_private_decrypt(base64_decode($response->json('sensitiveData')), $decrypted, $privateKey, OPENSSL_PKCS1_PADDING);
$res = json_decode($decrypted, true);
return [
'paymentRefId' => $res['paymentReferenceId'],
'challenge' => $res['challenge'] ?? $res['random'],
];
}
}
import datetime
import secrets
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 initialize_nagad_payment(order_id, client_ip, merchant_id, nagad_pub_pem, merchant_priv_pem, base_url):
# 1. Timestamp & 40-char challenge
now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
challenge = secrets.token_hex(20)
# 2. Sensitive JSON
sensitive_dict = {
"merchantId": merchant_id,
"datetime": now_str,
"orderId": order_id,
"challenge": challenge
}
sensitive_json = json.dumps(sensitive_dict)
# 3. 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')
# 4. 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')
# 5. Send POST
url = f"{base_url}/remote-payment-gateway-1.0/api/dfs/check-out/initialize/{merchant_id}/{order_id}?locale=BN"
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 = {
"dateTime": now_str,
"sensitiveData": sensitive_data_b64,
"signature": signature_b64
}
res = requests.post(url, headers=headers, json=payload)
res_data = res.json()
# 6. Decrypt Response
ms_cipher = Cipher_PKCS1_v1_5.new(ms_key)
decrypted_bytes = ms_cipher.decrypt(base64.b64decode(res_data["sensitiveData"]), None)
decrypted_dict = json.loads(decrypted_bytes.decode('utf-8'))
return {
"paymentReferenceId": decrypted_dict["paymentReferenceId"],
"challenge": decrypted_dict.get("challenge") or decrypted_dict.get("random")
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import org.json.JSONObject;
public class NagadInitService {
public static JSONObject initializePayment(String orderId, String clientIp, String merchantId, String nagadPubPem, String merchantPrivPem, String baseUrl) throws Exception {
String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
String challenge = UUID.randomUUID().toString().replace("-", "") + "00000000"; // 40 chars
JSONObject sensitiveObj = new JSONObject();
sensitiveObj.put("merchantId", merchantId);
sensitiveObj.put("datetime", dateTime);
sensitiveObj.put("orderId", orderId);
sensitiveObj.put("challenge", challenge);
String sensitiveData = NagadCrypto.encrypt(sensitiveObj.toString(), nagadPubPem);
String signature = NagadCrypto.sign(sensitiveObj.toString(), merchantPrivPem);
JSONObject requestBody = new JSONObject();
requestBody.put("dateTime", dateTime);
requestBody.put("sensitiveData", sensitiveData);
requestBody.put("signature", signature);
String endpoint = baseUrl + "/remote-payment-gateway-1.0/api/dfs/check-out/initialize/" + merchantId + "/" + orderId + "?locale=BN";
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());
String decryptedData = NagadCrypto.decrypt(resObj.getString("sensitiveData"), merchantPrivPem);
return new JSONObject(decryptedData);
}
}