Developer Documentation

NICTBD.COM Payment Gateway API Documentation

Build secure payment integration for your website, ecommerce store, Laravel application, PHP project, mobile app or custom platform using NICTBD.COM hosted checkout, PHP SDK, bKash payment gateway, Nagad payment gateway, HMAC signature verification, webhook/IPN and real-time payment verification.

Overview

NICTBD.COM provides an online payment gateway API for Bangladesh merchants who need secure payment collection through hosted checkout. Merchants can create payment sessions using API or PHP SDK, redirect customers to NICTBD.COM checkout, receive payment through supported payment methods, and update orders using webhook/IPN or payment verification API.

Best practice: Create payment only from your server-side backend. Never expose your Secret Key in frontend JavaScript, Android APK, iOS app source code, Flutter app, React Native app or public Git repository.

Core Features

This documentation covers the main features required for production-level payment gateway integration.

Hosted Checkout Secure payment page hosted by NICTBD.COM.
bKash & Nagad Ready Support for Bangladesh MFS payment methods.
HMAC Signature Request tampering protection using Secret Key.
Webhook/IPN Server-to-server payment notification.
PHP SDK Composer based SDK for PHP and Laravel projects.
Merchant Wallet Net amount can be added after gateway charge deduction.
Transaction Logs Gateway trx ID, charge, gross amount, net amount and status.
Multi Platform PHP, Laravel, Node.js, Python, Java, C#, Go and mobile app examples.
Status Verify Verify payment status before order delivery or service activation.

Payment Flow

NICTBD.COM follows a hosted checkout payment flow for secure and simple merchant integration.

1. Create Payment Merchant server sends amount, tran_id, customer info and HMAC signature or uses the PHP SDK.
2. Redirect Customer Customer opens NICTBD.COM hosted checkout and chooses available payment method.
3. Payment Complete NICTBD.COM verifies payment, saves transaction, updates status and sends webhook.

API Credentials

After merchant approval, you will receive API credentials from the NICTBD.COM merchant dashboard.

Credential Example Visibility Usage
Store ID STORE-2-FRXECLKM Public Identifies your merchant store.
API Key pk_live_xxxxxxxxx Public server-side Used with Store ID for API authentication.
Secret Key sk_live_xxxxxxxxx Private Used to generate and verify HMAC SHA256 signature. Never expose it publicly.
Do not put Secret Key inside frontend JavaScript, public mobile app source code, HTML source, GitHub public repository, browser local storage or public configuration file.

Create Payment API

Use this endpoint to create a new hosted checkout payment session.

POST https://www.nictbd.com/api/payment/create

Headers

Headers
Content-Type: application/json
Accept: application/json

Request Parameters

Field Required Type Description
store_idRequiredstringYour NICTBD.COM Store ID.
api_keyRequiredstringYour public API key.
amountRequireddecimalPayment amount with two decimals. Example: 100.00
tran_idRequiredstringUnique order or transaction ID from merchant website.
currencyOptionalstringDefault: BDT
customer_nameOptionalstringCustomer full name.
customer_mobileOptionalstringCustomer mobile number.
customer_emailOptionalemailCustomer email address.
success_urlRequiredurlCustomer redirect URL after successful payment.
failed_urlRequiredurlCustomer redirect URL after failed payment.
cancel_urlRequiredurlCustomer redirect URL after cancelled or timeout payment.
webhook_urlOptionalurlServer-to-server IPN URL for payment notification.
signatureRequiredstringHMAC SHA256 signature. SDK users do not need to generate this manually.

JSON Request Example

JSON
{
  "store_id": "STORE-2-FRXECLKM",
  "api_key": "pk_live_xxxxxxxxx",
  "amount": "100.00",
  "tran_id": "INV20260614010101",
  "currency": "BDT",
  "customer_name": "Rahim Uddin",
  "customer_mobile": "01700000000",
  "customer_email": "rahim@example.com",
  "success_url": "https://merchant.com/payment/success",
  "failed_url": "https://merchant.com/payment/failed",
  "cancel_url": "https://merchant.com/payment/cancel",
  "webhook_url": "https://merchant.com/api/payment/webhook",
  "signature": "generated_hmac_signature"
}

Success Response

Response
{
  "status": "success",
  "message": "Payment session created successfully.",
  "session_id": "PS20260614010101XQBTDXM3J98E",
  "payment_url": "https://nictbd.com/pay/PS20260614010101XQBTDXM3J98E"
}

Signature Generation

Signature confirms that the payment request was created from your real merchant server. NICTBD.COM checks this signature before creating a payment session.

Raw string format:
store_id|tran_id|amount
Raw String
STORE-2-FRXECLKM|INV20260614010101|100.00

PHP Signature

PHP
$signature = hash_hmac(
    "sha256",
    $storeId . "|" . $tranId . "|" . $amount,
    $secretKey
);
Amount must match exactly. If signature uses 100.00, request amount must also be 100.00.

Hosted Checkout

After successful payment session creation, redirect the customer to the returned payment_url. Customer will complete payment on the NICTBD.COM hosted checkout page.

Redirect
header("Location: " . $result["payment_url"]);
exit;

Customer Redirect After Payment

Success URL
https://merchant.com/payment/success?status=success&tran_id=INV20260614010101&session_id=PS20260614010101XQBTDXM3J98E&message=Payment+completed+successfully.
Customer redirect is useful for showing payment result, but final order update should be done through verified webhook/IPN or Payment Verify API.

Official PHP SDK Installation

NICTBD.COM PHP SDK is available for PHP and Laravel projects. Merchants can install it through Composer, create hosted checkout payments, verify payment status and keep Secret Key safely on the backend. Direct REST API is also available for any platform.

Install with Composer
Terminal
composer require nictbd/php-sdk

Basic PHP SDK Usage

PHP SDK
<?php

require_once __DIR__ . '/vendor/autoload.php';

use Nictbd\Client;

$client = new Client([
    'base_url' => 'https://nictbd.com',
    'store_id' => 'STORE-2-FRXECLKM',
    'api_key' => 'pk_live_xxxxxxxxx',
    'secret_key' => 'sk_live_xxxxxxxxx',
]);

$response = $client->createPayment([
    'amount' => 100,
    'tran_id' => 'INV' . date('YmdHis'),
    'currency' => 'BDT',
    'customer_name' => 'Rahim Uddin',
    'customer_mobile' => '01700000000',
    'customer_email' => 'rahim@example.com',
    'success_url' => 'https://merchant.com/payment/success',
    'failed_url' => 'https://merchant.com/payment/failed',
    'cancel_url' => 'https://merchant.com/payment/cancel',
    'webhook_url' => 'https://merchant.com/api/payment/webhook',
]);

if (($response['status'] ?? null) === 'success') {
    header('Location: ' . $response['payment_url']);
    exit;
}

echo $response['message'] ?? 'Payment create failed';

Laravel SDK Configuration

.env Configuration
.env
NICTBD_BASE_URL=https://nictbd.com
NICTBD_STORE_ID=STORE-2-FRXECLKM
NICTBD_API_KEY=pk_live_xxxxxxxxx
NICTBD_SECRET_KEY=sk_live_xxxxxxxxx
config/services.php
'nictbd' => [
    'base_url' => env('NICTBD_BASE_URL', 'https://nictbd.com'),
    'store_id' => env('NICTBD_STORE_ID'),
    'api_key' => env('NICTBD_API_KEY'),
    'secret_key' => env('NICTBD_SECRET_KEY'),
],

Laravel SDK Usage

Laravel Controller
use Illuminate\Http\Request;
use Nictbd\Client;

public function pay(Request $request)
{
    $client = new Client([
        'base_url' => config('services.nictbd.base_url'),
        'store_id' => config('services.nictbd.store_id'),
        'api_key' => config('services.nictbd.api_key'),
        'secret_key' => config('services.nictbd.secret_key'),
    ]);

    $response = $client->createPayment([
        'amount' => 100,
        'tran_id' => 'INV' . now()->format('YmdHis'),
        'currency' => 'BDT',
        'customer_name' => 'Rahim Uddin',
        'customer_mobile' => '01700000000',
        'customer_email' => 'rahim@example.com',
        'success_url' => route('payment.success'),
        'failed_url' => route('payment.failed'),
        'cancel_url' => route('payment.cancel'),
        'webhook_url' => route('payment.webhook'),
    ]);

    if (($response['status'] ?? null) === 'success') {
        return redirect()->away($response['payment_url']);
    }

    return back()->with('error', $response['message'] ?? 'Payment create failed');
}
PHP SDK

Official Composer package for PHP projects.

Available Now
Laravel Ready

Use the PHP SDK from Laravel controller, service class or payment module.

Supported
Mobile App Flow

Mobile app calls merchant backend. Backend uses SDK or REST API and returns payment_url.

Supported
REST API

Any backend language can integrate through JSON REST API and HMAC signature.

Available Now
SDK must run on your server-side backend only. Do not use Secret Key directly inside browser JavaScript, Android APK, iOS app, Flutter app or React Native app.

Platform Integration Examples

Choose SDK or REST API examples below. PHP and Laravel merchants should use the official PHP SDK when possible. Other platforms can use the REST API examples with backend-side HMAC signature.

Swipe tabs horizontally to view more examples.

PHP SDK Integration

PHP SDK
<?php

require_once __DIR__ . '/vendor/autoload.php';

use Nictbd\Client;

$client = new Client([
    'base_url' => 'https://nictbd.com',
    'store_id' => 'STORE-2-FRXECLKM',
    'api_key' => 'pk_live_xxxxxxxxx',
    'secret_key' => 'sk_live_xxxxxxxxx',
]);

$response = $client->createPayment([
    'amount' => 100,
    'tran_id' => 'INV' . date('YmdHis'),
    'currency' => 'BDT',
    'customer_name' => 'Rahim Uddin',
    'customer_mobile' => '01700000000',
    'customer_email' => 'rahim@example.com',
    'success_url' => 'https://merchant.com/payment/success',
    'failed_url' => 'https://merchant.com/payment/failed',
    'cancel_url' => 'https://merchant.com/payment/cancel',
    'webhook_url' => 'https://merchant.com/api/payment/webhook',
]);

if (($response['status'] ?? null) === 'success') {
    header('Location: ' . $response['payment_url']);
    exit;
}

echo $response['message'] ?? 'Payment create failed';

PHP REST Integration

PHP REST
$storeId = "STORE-2-FRXECLKM";
$apiKey = "pk_live_xxxxxxxxx";
$secret = "sk_live_xxxxxxxxx";

$tranId = "INV" . date("YmdHis");
$amount = "100.00";

$signature = hash_hmac(
    "sha256",
    $storeId . "|" . $tranId . "|" . $amount,
    $secret
);

$payload = [
    "store_id" => $storeId,
    "api_key" => $apiKey,
    "amount" => $amount,
    "tran_id" => $tranId,
    "currency" => "BDT",
    "customer_name" => "Rahim Uddin",
    "customer_mobile" => "01700000000",
    "customer_email" => "rahim@example.com",
    "success_url" => "https://merchant.com/payment/success",
    "failed_url" => "https://merchant.com/payment/failed",
    "cancel_url" => "https://merchant.com/payment/cancel",
    "webhook_url" => "https://merchant.com/api/payment/webhook",
    "signature" => $signature
];

$ch = curl_init("https://nictbd.com/api/payment/create");

curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "Accept: application/json"
    ],
    CURLOPT_POSTFIELDS => json_encode($payload)
]);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

if (($result["status"] ?? null) === "success") {
    header("Location: " . $result["payment_url"]);
    exit;
}

echo $result["message"] ?? "Payment create failed";

Laravel REST Integration

Laravel Controller
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

public function pay(Request $request)
{
    $storeId = config('services.nictbd.store_id');
    $apiKey = config('services.nictbd.api_key');
    $secretKey = config('services.nictbd.secret_key');

    $tranId = 'INV' . now()->format('YmdHis');
    $amount = number_format(100, 2, '.', '');

    $signature = hash_hmac(
        'sha256',
        $storeId . '|' . $tranId . '|' . $amount,
        $secretKey
    );

    $payload = [
        'store_id' => $storeId,
        'api_key' => $apiKey,
        'amount' => $amount,
        'tran_id' => $tranId,
        'currency' => 'BDT',
        'customer_name' => 'Rahim Uddin',
        'customer_mobile' => '01700000000',
        'customer_email' => 'rahim@example.com',
        'success_url' => route('payment.success'),
        'failed_url' => route('payment.failed'),
        'cancel_url' => route('payment.cancel'),
        'webhook_url' => route('payment.webhook'),
        'signature' => $signature,
    ];

    $response = Http::acceptJson()
        ->asJson()
        ->post(config('services.nictbd.base_url') . '/api/payment/create', $payload);

    $result = $response->json();

    if (($result['status'] ?? null) === 'success') {
        return redirect()->away($result['payment_url']);
    }

    return back()->with('error', $result['message'] ?? 'Payment create failed.');
}

cURL Integration

cURL
curl -X POST "https://nictbd.com/api/payment/create" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "store_id": "STORE-2-FRXECLKM",
    "api_key": "pk_live_xxxxxxxxx",
    "amount": "100.00",
    "tran_id": "INV20260614010101",
    "currency": "BDT",
    "customer_name": "Rahim Uddin",
    "customer_mobile": "01700000000",
    "customer_email": "rahim@example.com",
    "success_url": "https://merchant.com/payment/success",
    "failed_url": "https://merchant.com/payment/failed",
    "cancel_url": "https://merchant.com/payment/cancel",
    "webhook_url": "https://merchant.com/api/payment/webhook",
    "signature": "generated_hmac_signature"
  }'

PowerShell Integration

PowerShell
$storeId = "STORE-2-FRXECLKM"
$apiKey = "pk_live_xxxxxxxxx"
$tranId = "INV" + (Get-Date -Format "yyyyMMddHHmmss")
$amount = "100.00"
$secret = "sk_live_xxxxxxxxx"

$raw = "$storeId|$tranId|$amount"

$hmac = New-Object System.Security.Cryptography.HMACSHA256
$hmac.Key = [Text.Encoding]::UTF8.GetBytes($secret)

$signature = ([BitConverter]::ToString(
    $hmac.ComputeHash(
        [Text.Encoding]::UTF8.GetBytes($raw)
    )
)).Replace("-", "").ToLower()

$body = @{
    store_id = $storeId
    api_key = $apiKey
    amount = $amount
    tran_id = $tranId
    currency = "BDT"
    customer_name = "Rahim Uddin"
    customer_mobile = "01700000000"
    customer_email = "rahim@example.com"
    success_url = "https://merchant.com/payment/success"
    failed_url = "https://merchant.com/payment/failed"
    cancel_url = "https://merchant.com/payment/cancel"
    webhook_url = "https://merchant.com/api/payment/webhook"
    signature = $signature
} | ConvertTo-Json -Depth 5

Invoke-RestMethod `
    -Uri "https://nictbd.com/api/payment/create" `
    -Method POST `
    -Body $body `
    -ContentType "application/json"

Node.js Integration

Node.js
const crypto = require("crypto");

const storeId = "STORE-2-FRXECLKM";
const apiKey = "pk_live_xxxxxxxxx";
const secret = "sk_live_xxxxxxxxx";

const tranId = "INV" + new Date().toISOString().replace(/\D/g, "").slice(0, 14);
const amount = "100.00";

const raw = `${storeId}|${tranId}|${amount}`;

const signature = crypto
  .createHmac("sha256", secret)
  .update(raw)
  .digest("hex");

const payload = {
  store_id: storeId,
  api_key: apiKey,
  amount: amount,
  tran_id: tranId,
  currency: "BDT",
  customer_name: "Rahim Uddin",
  customer_mobile: "01700000000",
  customer_email: "rahim@example.com",
  success_url: "https://merchant.com/payment/success",
  failed_url: "https://merchant.com/payment/failed",
  cancel_url: "https://merchant.com/payment/cancel",
  webhook_url: "https://merchant.com/api/payment/webhook",
  signature: signature
};

const response = await fetch("https://nictbd.com/api/payment/create", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json"
  },
  body: JSON.stringify(payload)
});

const result = await response.json();

if (result.status === "success") {
  console.log("Redirect customer to:", result.payment_url);
} else {
  console.log("Payment create failed:", result);
}

Python Integration

Python
import time
import hmac
import hashlib
import requests

store_id = "STORE-2-FRXECLKM"
api_key = "pk_live_xxxxxxxxx"
secret = "sk_live_xxxxxxxxx"

tran_id = "INV" + time.strftime("%Y%m%d%H%M%S")
amount = "100.00"

raw = f"{store_id}|{tran_id}|{amount}"

signature = hmac.new(
    secret.encode("utf-8"),
    raw.encode("utf-8"),
    hashlib.sha256
).hexdigest()

payload = {
    "store_id": store_id,
    "api_key": api_key,
    "amount": amount,
    "tran_id": tran_id,
    "currency": "BDT",
    "customer_name": "Rahim Uddin",
    "customer_mobile": "01700000000",
    "customer_email": "rahim@example.com",
    "success_url": "https://merchant.com/payment/success",
    "failed_url": "https://merchant.com/payment/failed",
    "cancel_url": "https://merchant.com/payment/cancel",
    "webhook_url": "https://merchant.com/api/payment/webhook",
    "signature": signature
}

response = requests.post(
    "https://nictbd.com/api/payment/create",
    json=payload,
    headers={"Accept": "application/json"}
)

result = response.json()

if result.get("status") == "success":
    print("Redirect customer to:", result["payment_url"])
else:
    print("Payment create failed:", result)

Ruby Integration

Ruby
require "net/http"
require "json"
require "openssl"
require "time"

store_id = "STORE-2-FRXECLKM"
api_key = "pk_live_xxxxxxxxx"
secret = "sk_live_xxxxxxxxx"

tran_id = "INV" + Time.now.strftime("%Y%m%d%H%M%S")
amount = "100.00"

raw = "#{store_id}|#{tran_id}|#{amount}"

signature = OpenSSL::HMAC.hexdigest(
  "SHA256",
  secret,
  raw
)

payload = {
  store_id: store_id,
  api_key: api_key,
  amount: amount,
  tran_id: tran_id,
  currency: "BDT",
  customer_name: "Rahim Uddin",
  customer_mobile: "01700000000",
  customer_email: "rahim@example.com",
  success_url: "https://merchant.com/payment/success",
  failed_url: "https://merchant.com/payment/failed",
  cancel_url: "https://merchant.com/payment/cancel",
  webhook_url: "https://merchant.com/api/payment/webhook",
  signature: signature
}

uri = URI("https://nictbd.com/api/payment/create")

request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["Accept"] = "application/json"
request.body = payload.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

result = JSON.parse(response.body)

if result["status"] == "success"
  puts "Redirect customer to: #{result["payment_url"]}"
else
  puts result
end

Java Integration

Java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class NictbdPayment {
    public static String hmacSha256(String data, String secret) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec key = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        mac.init(key);

        byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));

        StringBuilder hex = new StringBuilder();

        for (byte b : hash) {
            hex.append(String.format("%02x", b));
        }

        return hex.toString();
    }

    public static void main(String[] args) throws Exception {
        String storeId = "STORE-2-FRXECLKM";
        String apiKey = "pk_live_xxxxxxxxx";
        String secret = "sk_live_xxxxxxxxx";

        String tranId = "INV" + System.currentTimeMillis();
        String amount = "100.00";

        String raw = storeId + "|" + tranId + "|" + amount;
        String signature = hmacSha256(raw, secret);

        String json = """
        {
          "store_id": "%s",
          "api_key": "%s",
          "amount": "%s",
          "tran_id": "%s",
          "currency": "BDT",
          "customer_name": "Rahim Uddin",
          "customer_mobile": "01700000000",
          "customer_email": "rahim@example.com",
          "success_url": "https://merchant.com/payment/success",
          "failed_url": "https://merchant.com/payment/failed",
          "cancel_url": "https://merchant.com/payment/cancel",
          "webhook_url": "https://merchant.com/api/payment/webhook",
          "signature": "%s"
        }
        """.formatted(storeId, apiKey, amount, tranId, signature);

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://nictbd.com/api/payment/create"))
            .header("Content-Type", "application/json")
            .header("Accept", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .build();

        HttpClient client = HttpClient.newHttpClient();

        HttpResponse response = client.send(
            request,
            HttpResponse.BodyHandlers.ofString()
        );

        System.out.println(response.body());
    }
}

C# Integration

C#
using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static string HmacSha256(string raw, string secret)
    {
        var key = Encoding.UTF8.GetBytes(secret);

        using var hmac = new HMACSHA256(key);

        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(raw));

        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }

    static async Task Main()
    {
        string storeId = "STORE-2-FRXECLKM";
        string apiKey = "pk_live_xxxxxxxxx";
        string secret = "sk_live_xxxxxxxxx";

        string tranId = "INV" + DateTime.Now.ToString("yyyyMMddHHmmss");
        string amount = "100.00";

        string raw = $"{storeId}|{tranId}|{amount}";
        string signature = HmacSha256(raw, secret);

        string json = $@"
        {{
            ""store_id"": ""{storeId}"",
            ""api_key"": ""{apiKey}"",
            ""amount"": ""{amount}"",
            ""tran_id"": ""{tranId}"",
            ""currency"": ""BDT"",
            ""customer_name"": ""Rahim Uddin"",
            ""customer_mobile"": ""01700000000"",
            ""customer_email"": ""rahim@example.com"",
            ""success_url"": ""https://merchant.com/payment/success"",
            ""failed_url"": ""https://merchant.com/payment/failed"",
            ""cancel_url"": ""https://merchant.com/payment/cancel"",
            ""webhook_url"": ""https://merchant.com/api/payment/webhook"",
            ""signature"": ""{signature}""
        }}";

        using var client = new HttpClient();

        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await client.PostAsync("https://nictbd.com/api/payment/create", content);

        var result = await response.Content.ReadAsStringAsync();

        Console.WriteLine(result);
    }
}

Go Integration

Go
package main

import (
    "bytes"
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "net/http"
    "time"
)

func hmacSha256(raw string, secret string) string {
    h := hmac.New(sha256.New, []byte(secret))
    h.Write([]byte(raw))
    return hex.EncodeToString(h.Sum(nil))
}

func main() {
    storeId := "STORE-2-FRXECLKM"
    apiKey := "pk_live_xxxxxxxxx"
    secret := "sk_live_xxxxxxxxx"

    tranId := "INV" + time.Now().Format("20060102150405")
    amount := "100.00"

    raw := storeId + "|" + tranId + "|" + amount
    signature := hmacSha256(raw, secret)

    jsonBody := fmt.Sprintf(`{
        "store_id": "%s",
        "api_key": "%s",
        "amount": "%s",
        "tran_id": "%s",
        "currency": "BDT",
        "customer_name": "Rahim Uddin",
        "customer_mobile": "01700000000",
        "customer_email": "rahim@example.com",
        "success_url": "https://merchant.com/payment/success",
        "failed_url": "https://merchant.com/payment/failed",
        "cancel_url": "https://merchant.com/payment/cancel",
        "webhook_url": "https://merchant.com/api/payment/webhook",
        "signature": "%s"
    }`, storeId, apiKey, amount, tranId, signature)

    req, _ := http.NewRequest(
        "POST",
        "https://nictbd.com/api/payment/create",
        bytes.NewBuffer([]byte(jsonBody)),
    )

    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Accept", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)

    if err != nil {
        panic(err)
    }

    defer resp.Body.Close()

    fmt.Println("Payment create request sent.")
}

Webhook / IPN Notification

After successful payment, NICTBD.COM sends a server-to-server webhook notification to your webhook_url. Use this webhook/IPN to update your order status automatically.

Customer redirect URL can be changed, delayed or interrupted by browser/network issues. For final order confirmation, always trust verified webhook or payment status verification.

Webhook Payload

JSON Payload
{
  "status": "success",
  "tran_id": "INV20260614010101",
  "transaction_uid": "TXN202606140101ABC",
  "gateway_trx_id": "BKH123456789",
  "amount": "100.00",
  "charge_amount": "2.50",
  "merchant_amount": "97.50",
  "currency": "BDT",
  "payment_method": "bkash",
  "customer_name": "Rahim Uddin",
  "customer_mobile": "01700000000",
  "customer_email": "rahim@example.com",
  "paid_at": "2026-06-14 01:10:00",
  "signature": "webhook_hmac_signature"
}

Webhook Fields

Field Description
statusPayment status. Example: success
tran_idYour merchant transaction/order ID.
transaction_uidNICTBD.COM internal transaction ID.
gateway_trx_idOriginal payment gateway transaction ID from payment provider.
amountCustomer paid gross amount.
charge_amountGateway charge deducted from merchant amount.
merchant_amountNet amount credited or payable to merchant.
currencyPayment currency. Default: BDT
payment_methodPayment method code. Example: bkash, nagad
signatureWebhook HMAC signature.

Webhook Signature Verify

Before updating your order as paid, verify the webhook signature using your Secret Key. This protects your system from fake payment notifications.

Webhook raw string format:
tran_id|amount|status

PHP Webhook Verify

PHP
$payload = json_decode(file_get_contents("php://input"), true);

$tranId = $payload["tran_id"] ?? "";
$amount = $payload["amount"] ?? "";
$status = $payload["status"] ?? "";
$signature = $payload["signature"] ?? "";

$secret = "sk_live_xxxxxxxxx";

$raw = $tranId . "|" . $amount . "|" . $status;

$expectedSignature = hash_hmac("sha256", $raw, $secret);

if (!hash_equals($expectedSignature, $signature)) {
    http_response_code(401);
    echo "Invalid signature";
    exit;
}

if ($status === "success") {
    // Find your order by $tranId
    // Check amount with your order amount
    // Update order as paid
    // Save gateway_trx_id and transaction_uid
}

http_response_code(200);
echo "OK";

Laravel Webhook Verify

Laravel
// routes/api.php
Route::post('/payment/webhook', [PaymentWebhookController::class, 'handle'])
    ->name('payment.webhook');

// Controller
use Illuminate\Http\Request;

public function handle(Request $request)
{
    $secret = config('services.nictbd.secret_key');

    $tranId = $request->input('tran_id');
    $amount = $request->input('amount');
    $status = $request->input('status');
    $signature = $request->input('signature');

    $raw = $tranId . '|' . $amount . '|' . $status;

    $expectedSignature = hash_hmac('sha256', $raw, $secret);

    if (!hash_equals($expectedSignature, $signature)) {
        return response('Invalid signature', 401);
    }

    if ($status === 'success') {
        // $order = Order::where('invoice_no', $tranId)->first();

        // if ($order && number_format($order->amount, 2, '.', '') === number_format($amount, 2, '.', '')) {
        //     $order->update([
        //         'payment_status' => 'paid',
        //         'gateway_trx_id' => $request->gateway_trx_id,
        //         'transaction_uid' => $request->transaction_uid,
        //     ]);
        // }
    }

    return response('OK', 200);
}

Mobile App Integration

For Android, iOS, Flutter, React Native or any mobile app, do not call NICTBD.COM API directly from the app using Secret Key. Always call your own backend first.

1. App calls your backend Mobile app sends order ID, amount and customer information to your backend server.
2. Backend creates payment Your backend uses NICTBD.COM PHP SDK or REST API to create a payment session.
3. Open payment URL App opens payment_url in WebView, Custom Tab or external browser.

Backend Response to Mobile App

JSON
{
  "status": "success",
  "payment_url": "https://nictbd.com/pay/PS20260614010101XQBTDXM3J98E"
}

Laravel Backend API for Mobile App Using SDK

Laravel + SDK
use Illuminate\Http\Request;
use Nictbd\Client;

public function createMobilePayment(Request $request)
{
    $request->validate([
        'order_id' => 'required|string',
        'amount' => 'required|numeric|min:1',
    ]);

    $client = new Client([
        'base_url' => config('services.nictbd.base_url'),
        'store_id' => config('services.nictbd.store_id'),
        'api_key' => config('services.nictbd.api_key'),
        'secret_key' => config('services.nictbd.secret_key'),
    ]);

    $response = $client->createPayment([
        'amount' => $request->amount,
        'tran_id' => $request->order_id,
        'currency' => 'BDT',
        'customer_name' => $request->customer_name,
        'customer_mobile' => $request->customer_mobile,
        'customer_email' => $request->customer_email,
        'success_url' => route('payment.success'),
        'failed_url' => route('payment.failed'),
        'cancel_url' => route('payment.cancel'),
        'webhook_url' => route('payment.webhook'),
    ]);

    return response()->json($response);
}

Flutter Example

Flutter
// 1. Call your backend to create payment
// 2. Backend returns payment_url
// 3. Open payment_url using url_launcher or WebView

final paymentUrl = response['payment_url'];

// url_launcher example:
// await launchUrl(
//   Uri.parse(paymentUrl),
//   mode: LaunchMode.externalApplication
// );

Android Kotlin Example

Kotlin
// Open NICTBD.COM hosted checkout URL
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(paymentUrl))
startActivity(intent)

React Native Example

React Native
import { Linking } from "react-native";

// paymentUrl returned from your backend
Linking.openURL(paymentUrl);
Never store Secret Key inside APK, IPA, Flutter app, React Native app or frontend code. Secret Key must stay on your backend server only.

Payment Verify / Status API

Merchants can verify payment status using Store ID, API Key, transaction ID and signature. This is useful for checking the final payment status before order delivery.

POST https://www.nictbd.com/api/payment/verify

Recommended Verify Signature

Verify raw string format:
store_id|tran_id

Note: This signature authenticates the merchant request. Amount is not included because transaction data is already stored and secured in the system.

Verify Request

JSON
{
  "store_id": "STORE-2-FRXECLKM",
  "api_key": "pk_live_xxxxxxxxx",
  "tran_id": "INV20260614010101",
  "signature": "generated_verify_signature"
}

PHP SDK Verify Payment

PHP SDK
use Nictbd\Client;

$client = new Client([
    'base_url' => 'https://nictbd.com',
    'store_id' => 'STORE-2-FRXECLKM',
    'api_key' => 'pk_live_xxxxxxxxx',
    'secret_key' => 'sk_live_xxxxxxxxx',
]);

$response = $client->verifyPayment([
    'tran_id' => 'INV20260614010101',
]);

if (($response['status'] ?? null) === 'success') {
    // Payment verified successfully
}

Verify Response

JSON
{
  "status": "success",
  "tran_id": "INV20260614010101",
  "transaction_uid": "TXN202606140101ABC",
  "gateway_trx_id": "BKH123456789",
  "amount": "100.00",
  "charge_amount": "2.50",
  "merchant_amount": "97.50",
  "currency": "BDT",
  "payment_method": "bkash",
  "paid_at": "2026-06-14 01:10:00"
}
Verified webhook/IPN should be your primary payment confirmation system. Payment Verify API is useful for manual check, retry and reconciliation.

Error Codes

NICTBD.COM API returns JSON error responses when a payment request is invalid.

HTTP Code Message Reason Solution
401 Invalid merchant credentials. Store ID or API Key is wrong or inactive. Check merchant dashboard API credentials.
401 Invalid signature. HMAC signature mismatch. Use exact raw string: store_id|tran_id|amount.
422 Duplicate transaction ID. Same tran_id already used. Use unique invoice/order ID for every payment.
422 Validation failed. Required field missing or invalid format. Check request parameters and URL fields.
500 Something went wrong. Temporary server or processing issue. Retry later or contact NICTBD.COM support.

Security Checklist

Follow this checklist before going live with NICTBD.COM payment gateway integration.

  • Use HTTPS on your website, webhook URL and success/failed/cancel URLs.
  • Keep Secret Key only on your backend server.
  • Never expose Secret Key in frontend JavaScript or mobile app code.
  • Always verify webhook signature before updating order status.
  • Use unique tran_id for every payment request.
  • Store gateway transaction ID for future support and reconciliation.
  • Do not deliver service only based on customer redirect. Confirm webhook or status verify first.
  • Log request, response and webhook payload for troubleshooting.
  • Handle duplicate webhook safely to avoid double order processing.
  • Do not change order status if amount does not match your order amount.
For production payment gateway integration, webhook verification, amount matching and duplicate transaction protection are mandatory.