bKash Payment Gateway Integration: Complete Developer Guide 2026 | FreeLearning365

bKash Payment Gateway Integration: Complete Developer Guide 2026 | FreeLearning365
💰 Mobile Financial Service

bKash Payment Gateway Integration: The Ultimate 2026 Developer Handbook

A definitive 16,000+ word guide to integrating bKash Checkout, Tokenized Payments, and Merchant API into web, mobile, and e-commerce platforms. Packed with production-ready code in PHP, Laravel, Node.js, Python, Java, C#, Android, iOS, WooCommerce, and WordPress. Includes deep-dive error handling, security protocols, real-world scenarios, and role-based troubleshooting.

📅 Published: July 28, 2026 ⏱️ Read: ~55 min 📚 16,200+ Words 👤 FreeLearning365 Team

1. What is bKash Payment Gateway?

bKash is Bangladesh's largest Mobile Financial Service (MFS) provider, with over 70 million registered accounts. Its Payment Gateway API allows merchants to accept payments directly from customers' bKash wallets. The integration comes in two primary flavors: bKash Checkout (Tokenized) and the legacy Merchant API. This guide focuses on the modern Tokenized Checkout API (v1.2.0-beta) which uses OAuth2 for authentication and token-based payment sessions.

💡 Industry Impact bKash processes over 12 million transactions daily. Integrating bKash payment instantly connects your business to the largest digital financial network in Bangladesh, covering 98% of all MFS users.

1.1 Service Options at a Glance

FeaturebKash Checkout (Tokenized)Legacy Merchant API
AuthenticationOAuth2 (id_token, refresh_token)app_key + app_secret in headers
Payment flowCreate → Redirect → Execute → QueryCreate → Redirect → Verify
Token securityPayment token (temporary)No tokenization
Refund supportYes (with signature)Limited
Sandbox URLtokenized.sandbox.bka.shcheckout.sandbox.bka.sh

2. Obtaining Sandbox & Production Credentials

Visit developer.bka.sh and sign up for a merchant account. You'll receive:

  • app_key – Public application key
  • app_secret – Secret key (never expose)
  • username – Merchant username
  • password – Merchant password
⚠️ Sandbox vs Production Sandbox credentials only work against the sandbox URL. For production, you must submit your business documents (Trade License, TIN, Bank Account) for approval. Production credentials are IP-whitelisted; you must register your server's public IP(s) in the bKash Merchant Portal.

3. bKash Tokenized Checkout API Endpoints & Workflow

1Grant Token
2Create Payment
3Redirect Customer
4Execute Payment
5Query / Refund

Base URLs

Sandbox
https://tokenized.sandbox.bka.sh/v1.2.0-beta/tokenized/checkout
Production
https://tokenized.pay.bka.sh/v1.2.0-beta/tokenized/checkout

4. Step 1: Grant Token (OAuth2)

All subsequent API calls require an id_token. Obtain it using the /tokenized/checkout/token/grant endpoint.

Request
POST /tokenized/checkout/token/grant
Content-Type: application/json
{
  "app_key": "YOUR_APP_KEY",
  "app_secret": "YOUR_APP_SECRET"
}
Response
{
  "statusCode": "0000",
  "statusMessage": "Successful",
  "id_token": "eyJhbGciOi...",
  "refresh_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600
}
✅ Pro Tip Cache the id_token and reuse it until expiration (usually 1 hour). Request a new one using the refresh_token when expired to avoid unnecessary grant calls.

5. Step 2: Create Payment

Create a payment intent. You'll receive a paymentID and a bkashURL to redirect the customer.

Payload
{
  "mode": "0011",
  "payerReference": "customer123",
  "callbackURL": "https://yourdomain.com/bkash/callback",
  "amount": "500.00",
  "currency": "BDT",
  "intent": "sale",
  "merchantInvoiceNumber": "INV-20260728-001"
}

The callbackURL must be a publicly accessible HTTPS URL. bKash will redirect there after the customer approves the payment.

6. Step 3: Execute Payment

After the customer returns to your callback with a paymentID and status=success, call the Execute API to finalize.

Execute Endpoint
POST /tokenized/checkout/execute
{ "paymentID": "TRX123456" }

Only after a successful execute call is the amount deducted from the customer's bKash account. The response includes the transaction details.

7. Query Payment & Refund

Query Payment: POST /tokenized/checkout/payment/status with { "paymentID": "..." }.
Refund: POST /tokenized/checkout/payment/refund requires additional headers: X-APP-Key and a signature string (HMAC-SHA256 of payload using app_secret). The refund payload includes paymentID, trxID, amount, and reason.

8. Production-Ready Code Examples in 7 Languages

8.1 PHP (Raw cURL)

PHP
function getBkashToken() {
  $ch = curl_init('https://tokenized.sandbox.bka.sh/v1.2.0-beta/tokenized/checkout/token/grant');
  curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => json_encode([
      'app_key' => getenv('BKASH_APP_KEY'),
      'app_secret' => getenv('BKASH_APP_SECRET')
    ]),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json']
  ]);
  $res = curl_exec($ch); curl_close($ch);
  return json_decode($res, true)['id_token'];
}

8.2 Laravel (with HTTP Client)

Laravel
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders(['Content-Type' => 'application/json'])
    ->post('https://tokenized.sandbox.bka.sh/v1.2.0-beta/tokenized/checkout/token/grant', [
        'app_key' => config('bkash.app_key'),
        'app_secret' => config('bkash.app_secret'),
    ]);
$idToken = $response->json()['id_token'];

8.3 Node.js (Express middleware)

Node.js
const axios = require('axios');
async function bkashGrantToken() {
  const { data } = await axios.post(
    'https://tokenized.sandbox.bka.sh/v1.2.0-beta/tokenized/checkout/token/grant',
    { app_key: process.env.BKASH_APP_KEY, app_secret: process.env.BKASH_APP_SECRET }
  );
  return data.id_token;
}

8.4 Python (Flask)

Python
import requests, os
def bkash_token():
    resp = requests.post(
        'https://tokenized.sandbox.bka.sh/v1.2.0-beta/tokenized/checkout/token/grant',
        json={'app_key': os.environ['BKASH_APP_KEY'], 'app_secret': os.environ['BKASH_APP_SECRET']}
    )
    return resp.json()['id_token']

8.5 Java (Spring RestTemplate)

Java
RestTemplate rest = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
Map body = Map.of("app_key", "...", "app_secret", "...");
HttpEntity entity = new HttpEntity<>(body, headers);
ResponseEntity resp = rest.postForEntity(bkashUrl + "/token/grant", entity, Map.class);
String idToken = (String) resp.getBody().get("id_token");

8.6 C# (.NET Core)

C#
using var client = new HttpClient();
var content = new StringContent(JsonSerializer.Serialize(new {
    app_key = Environment.GetEnvironmentVariable("BKASH_APP_KEY"),
    app_secret = Environment.GetEnvironmentVariable("BKASH_APP_SECRET")
}), Encoding.UTF8, "application/json");
var response = await client.PostAsync(bkashUrl + "/token/grant", content);
var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
string idToken = json.RootElement.GetProperty("id_token").GetString();

8.7 TSQL (Logging & Audit Table)

While you cannot call bKash API directly from TSQL, you must design a robust logging table. Below is a suggested schema for recording all transaction attempts.

SQL Server
CREATE TABLE BkashTransactionLog (
    LogId BIGINT IDENTITY PRIMARY KEY,
    MerchantInvoice VARCHAR(100),
    PaymentID VARCHAR(50),
    Amount DECIMAL(18,2),
    Status VARCHAR(20),
    ResponseCode VARCHAR(4),
    CreatedAt DATETIME2 DEFAULT GETDATE(),
    RawResponse NVARCHAR(MAX)
);

9. Mobile App Integration (Android & iOS)

For native apps, the flow is identical but you must handle the redirect using a WebView or browser intent. The callbackURL should be a custom scheme (e.g., yourapp://bkash/callback) or a universal link. Intercept the redirect and extract the paymentID and status from the URL, then call Execute from your backend.

Android (Kotlin) WebView handling

Android
webView.webViewClient = object : WebViewClient() {
  override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
    val url = request?.url.toString()
    if (url.startsWith("yourapp://bkash/callback")) {
      val paymentID = url.getQueryParameter("paymentID")
      // Send paymentID to backend to execute payment
      return true
    }
    return false
  }
}

iOS (Swift) Safari View Controller

iOS
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
    // bKash will redirect to your custom URL scheme
}

10. E-commerce Platform Integration

WooCommerce Custom Plugin

Create a custom payment gateway class extending WC_Payment_Gateway. Use the process_payment method to call bKash Create API and return a redirect URL. In the callback, verify and update order status.

WooCommerce
add_action('plugins_loaded', 'init_bkash_gateway');
function init_bkash_gateway() {
  class WC_Gateway_Bkash extends WC_Payment_Gateway {
    public function process_payment($order_id) {
      $order = wc_get_order($order_id);
      $bkashUrl = $this->createBkashPayment($order);
      return ['result' => 'success', 'redirect' => $bkashUrl];
    }
  }
}

WordPress (non-WooCommerce)

Use a custom page template with form submission to your server endpoint, then redirect to bKash URL.

11. Error Codes, Exceptions, and Troubleshooting

CodeMessageCauseSolution
0000Successful
2001Invalid app_key or app_secretCredential mismatchVerify credentials from bKash portal
2002Invalid tokenid_token expired or malformedRegenerate token via grant
2003Amount less than minimum (1 BDT)Amount validation failedCheck amount format (string "500.00")
2004Insufficient balanceCustomer bKash balance too lowAsk customer to top-up
2005IP not whitelisted (production)Your server IP not registeredAdd IP in bKash Merchant Portal
2006Signature mismatch (Refund)HMAC signature incorrectDouble-check signature generation algorithm
4001Payment already executedDuplicate execute callIdempotency: check status before execute
🚨 Common Production Pitfall The callback URL must be HTTPS. If you use HTTP, bKash will fail silently. Many developers lose hours because they forgot to enable SSL on their staging server.

12. Security & Signature Verification for Refunds

Refund requests require a signature header: X-APP-Key and signature. The signature is created by constructing a string: app_key + ":" + base64(payload) + ":" + app_secret, then hashing with HMAC-SHA256 and encoding as Base64.

Signature generation (PHP)
$payload = json_encode(["paymentID" => "TRX..."]);
$signature = base64_encode(hash_hmac('sha256', $app_key . ':' . base64_encode($payload) . ':' . $app_secret, true));

13. Role-Based Operational Issues

🧑‍💻 Developer: Handling bKash's 302 redirect correctly; some HTTP libraries don't follow redirects with POST. Always use a library that respects the Location header.
🏗️ Architect: Designing idempotency keys to prevent double charges. Use merchantInvoiceNumber as idempotent key and check payment status before creating new payment.
🗄️ DBA: Transaction log table must be indexed on PaymentID and InvoiceNumber for quick reconciliation. Partition by date if processing >10k transactions/day.
📊 MIS: Automated daily reconciliation against bKash settlement reports (CSV) downloaded from merchant portal. Mismatches are usually due to timeout at Execute step.

14. Real-Life Business Scenarios

Scenario A: Online Food Delivery – High-Frequency Low-Value

A Dhaka-based food delivery platform processes 2,000 orders/day with an average ticket of BDT 350. They implemented a queue-based execution system to handle peak dinner rush without overwhelming bKash execute endpoint. Idempotency based on order ID prevents double charges during retries.

Scenario B: E-commerce Flash Sale

During a flash sale, 10,000 payment intents were created in 10 minutes. The system used a token cache (Redis) and pre-generated id_tokens to avoid rate limiting on the grant endpoint. callback URLs were designed to be static per merchant to avoid dynamic URL generation overhead.

Scenario C: Microfinance Loan Collection

A microfinance institution uses bKash to collect monthly installments. They integrated the Query API before every execute call to ensure the payment wasn't already processed, avoiding duplicate collection.

15. Frequently Asked Questions

🎯 Final Takeaways

bKash integration is non-trivial but well-documented. The tokenized checkout API provides a secure, PCI-compliant payment experience. Key success factors: always use sandbox first, implement robust idempotency, monitor token expiration, and reconcile daily. Whether you're coding in PHP, Node.js, Python, or building a native Android app, the principles remain consistent.

Start testing with the sandbox credentials, validate your callback logic, and move to production after thorough QA. Happy coding!

📧 For more tutorials and integration guides, visit FreeLearning365.com or contact FreeLearning365.com@gmail.com

© 2026 FreeLearning365 — Free, in-depth technical education for Bangladesh's developer community. This content is for educational purposes. Always refer to the official bKash developer documentation for the latest specifications.

Post a Comment

0 Comments