Welcome to DrutoPay Documentation

v1.0 RESTful API

DrutoPay Automation Bridge is an automated payment infrastructure service that connects personal and merchant MFS accounts (bKash, Nagad, Rocket, and Upay) directly with online software, webstores, and mobile applications through real-time SMS verification.

How the Automation Bridge Works:

1. Your website creates a payment order via REST API.
2. Customer sends money directly to your personal MFS number using bKash/Nagad/Rocket app or USSD.
3. The DrutoPay Android Daemon syncs incoming bank SMS to server in real-time.
4. DrutoPay automatically matches transaction details, marks the order paid, and notifies your webhook.

REST API Overview

JSON / HTTPS

REST APIs are available for both Sandbox and Live production environments. To test without real money, toggle your credentials to Sandbox mode. When ready, switch to your Live API credentials to accept real customer payments.

API Endpoints

POST https://pay.drutopay.com/api/payment/create
POST https://pay.drutopay.com/api/payment/verify

Authentication Headers

Header Auth

Authenticate your API requests by including the API-KEY HTTP header in every request.

Header Key Requirement Value Description
Content-Type Required Must be set to application/json
API-KEY Required Your Brand Secret Key obtained from Merchant Dashboard › Brands (/user/brands).
Where to find your API-KEY?

Log in to your DrutoPay merchant account, navigate to Brand Identity & Websites (Brands), and copy the 50-character Brand Secret Key assigned to your website. You only need to send this key under the API-KEY header (or as api_key in your request payload). No secondary secret keys are required.

Create Payment Request Parameters

Variables to send in the JSON body when calling POST /api/payment/create.

Field Name Description Requirement Example Value
cus_name Full name of the customer initiating the order. Required John Doe
cus_email Email address of the customer for notifications. Required [email protected]
amount Total amount payable in BDT. Integer or decimal. Required 10.00
success_url Redirect URL where customer returns after payment approval. Required https://yoursite.com/success
cancel_url Redirect URL where customer returns if payment is canceled. Required https://yoursite.com/cancel
webhook_url Merchant server-to-server webhook endpoint. DrutoPay automatically posts transaction status & details to this URL upon payment confirmation. Security: The domain must match your registered brand domain or any of its subdomains (e.g. subdomain.yoursite.com or yoursite.com). Recommended https://yoursite.com/api/drutopay-webhook
meta_data Optional custom JSON payload passed back in callback. Optional {"order_id": 1024}

Payment Verification Parameters

Variables to send in the JSON body when calling POST /api/payment/verify.

Field Name Description Requirement Example Value
transaction_id Transaction identifier received as query parameter upon callback. Required OVKPXW165414

Webhook & Instant Payment Notification (IPN)

Server-to-Server POST

Webhooks provide real-time, asynchronous transaction notifications directly to your application backend. Unlike browser redirects (which can fail if a customer closes their tab or loses internet), webhooks guarantee that your system fulfills customer orders instantly upon SMS payment detection.

How the Webhook Notification Flow Operates:
  1. Send Webhook URL: When initiating a payment session via POST /api/payment/create, pass your endpoint in the webhook_url parameter.
  2. Customer Pays: The customer completes payment to your bKash, Nagad, Rocket, or Upay account.
  3. SMS Verification: DrutoPay Connect daemon syncs the confirmation SMS to our server, matching amount and transaction.
  4. Instant Webhook Dispatch: DrutoPay immediately sends an HTTP POST request with transaction payload to your webhook_url.
  5. Order Fulfillment: Your server receives the payload, verifies status, updates the order in your database, and returns a 200 OK response.

DrutoPay Webhook Payload Parameters

Data keys posted by the DrutoPay server to your registered webhook_url:

Parameter Key Data Type Description Example Value
paymentMethod string MFS provider used for payment (bkash, nagad, rocket, upay). bkash
transactionId string Unique DrutoPay transaction reference identifier. OVKPXW165414
paymentAmount string / float Total amount received from customer in BDT. 500.00
paymentFee string / float Gateway processing fee deducted (if applicable). 0.00
cus_name string Full name of the customer sent during payment create. John Doe
cus_email string Email address of the customer sent during payment create. [email protected]
cus_phone string Sender / customer phone number. 01700000000
metadata string / JSON Custom metadata originally passed in POST /api/payment/create (e.g. order_id, user_id). {"order_id": 1024}
status string Payment outcome status. Always completed for successful transactions. completed
application/x-www-form-urlencoded / JSON POST Body
{
  "paymentMethod": "bkash",
  "transactionId": "OVKPXW165414",
  "paymentAmount": "500.00",
  "paymentFee": "0.00",
  "cus_name": "John Doe",
  "cus_email": "[email protected]",
  "cus_phone": "01700000000",
  "metadata": "{\"order_id\": 1024}",
  "status": "completed"
}

Code Integration

Multi-Language

1. Create Payment Request

Choose your programming language below to see complete integration code.

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://pay.drutopay.com/api/payment/create',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS => json_encode(array(
    "cus_name"    => "John Doe",
    "cus_email"   => "[email protected]",
    "success_url" => "https://yourdomain.com/success",
    "cancel_url"  => "https://yourdomain.com/cancel",
    "webhook_url" => "https://yourdomain.com/webhook",
    "amount"      => "10",
    "metadata"    => array("order_id" => "1024")
  )),
  CURLOPT_HTTPHEADER => array(
    'API-KEY: YOUR_BRAND_KEY',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;

$client = new Client();
$headers = [
  'API-KEY'      => 'YOUR_BRAND_KEY',
  'Content-Type' => 'application/json'
];
$body = json_encode([
  'cus_name'    => 'John Doe',
  'cus_email'   => '[email protected]',
  'success_url' => 'https://yourdomain.com/success',
  'cancel_url'  => 'https://yourdomain.com/cancel',
  'webhook_url' => 'https://yourdomain.com/webhook',
  'amount'      => '10',
  'metadata'    => ['order_id' => '1024']
]);

$request = new Request('POST', 'https://pay.drutopay.com/api/payment/create', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
?>
const axios = require('axios');

const data = JSON.stringify({
  cus_name: "John Doe",
  cus_email: "[email protected]",
  success_url: "https://yourdomain.com/success",
  cancel_url: "https://yourdomain.com/cancel",
  webhook_url: "https://yourdomain.com/webhook",
  amount: "10",
  metadata: { order_id: "1024" }
});

const config = {
  method: 'post',
  url: 'https://pay.drutopay.com/api/payment/create',
  headers: { 
    'API-KEY': 'YOUR_BRAND_KEY',
    'Content-Type': 'application/json'
  },
  data: data
};

axios(config)
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error(error);
  });
import requests
import json

url = "https://pay.drutopay.com/api/payment/create"

payload = json.dumps({
  "cus_name": "John Doe",
  "cus_email": "[email protected]",
  "success_url": "https://yourdomain.com/success",
  "cancel_url": "https://yourdomain.com/cancel",
  "webhook_url": "https://yourdomain.com/webhook",
  "amount": "10",
  "metadata": {"order_id": "1024"}
})

headers = {
  'API-KEY': 'YOUR_BRAND_KEY',
  'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, data=payload)
print(response.json())
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io"
)

func main() {
  url := "https://pay.drutopay.com/api/payment/create"
  payload := strings.NewReader(`{"cus_name":"John Doe","cus_email":"[email protected]","success_url":"https://yourdomain.com/success","cancel_url":"https://yourdomain.com/cancel","webhook_url":"https://yourdomain.com/webhook","amount":"10","metadata":{"order_id":"1024"}}`)

  req, _ := http.NewRequest("POST", url, payload)
  req.Header.Add("API-KEY", "YOUR_BRAND_KEY")
  req.Header.Add("Content-Type", "application/json")

  res, err := http.DefaultClient.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, _ := io.ReadAll(res.Body)
  fmt.Println(string(body))
}

Response Schema

Field Name Type Description
Success Response (HTTP 200)
status boolean Returns true when payment session is generated successfully.
message string Status message describing the result.
payment_url string (url) Redirect link where the customer completes MFS verification.
Error Response (HTTP 400 / 401)
status boolean Returns false upon validation or auth failure.
message string Detailed explanation of the error (e.g. Invalid API credentials, Missing fields).
Callback Redirection: After completion, customer returns to your success_url or cancel_url with query params:
?transactionId=******&paymentMethod=bkash&paymentAmount=10.00&status=success

2. Verify Payment Request

Execute a verification check on your callback page or webhook listener.

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://pay.drutopay.com/api/payment/verify',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS => json_encode(array(
    "transaction_id" => "TRX12345678"
  )),
  CURLOPT_HTTPHEADER => array(
    'API-KEY: YOUR_BRAND_KEY',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;

$client = new Client();
$headers = [
  'API-KEY'      => 'YOUR_BRAND_KEY',
  'Content-Type' => 'application/json'
];
$body = json_encode([
  'transaction_id' => 'TRX12345678'
]);

$request = new Request('POST', 'https://pay.drutopay.com/api/payment/verify', $headers, $body);
$res = $client->sendAsync($request)->wait();
echo $res->getBody();
?>
const axios = require('axios');

const data = JSON.stringify({
  transaction_id: "TRX12345678"
});

const config = {
  method: 'post',
  url: 'https://pay.drutopay.com/api/payment/verify',
  headers: { 
    'API-KEY': 'YOUR_BRAND_KEY',
    'Content-Type': 'application/json'
  },
  data: data
};

axios(config)
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error(error);
  });
import requests
import json

url = "https://pay.drutopay.com/api/payment/verify"

payload = json.dumps({
  "transaction_id": "TRX12345678"
})

headers = {
  'API-KEY': 'YOUR_BRAND_KEY',
  'Content-Type': 'application/json'
}

response = requests.post(url, headers=headers, data=payload)
print(response.json())
package main

import (
  "fmt"
  "strings"
  "net/http"
  "io"
)

func main() {
  url := "https://pay.drutopay.com/api/payment/verify"
  payload := strings.NewReader(`{"transaction_id":"TRX12345678"}`)

  req, _ := http.NewRequest("POST", url, payload)
  req.Header.Add("API-KEY", "YOUR_BRAND_KEY")
  req.Header.Add("Content-Type", "application/json")

  res, err := http.DefaultClient.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }
  defer res.Body.Close()

  body, _ := io.ReadAll(res.Body)
  fmt.Println(string(body))
}

Sample Verification Response

JSON Response
{
    "status": "COMPLETED",
    "cus_name": "John Doe",
    "cus_email": "[email protected]",
    "amount": "100.00",
    "transaction_id": "OVKPXW165414",
    "payment_method": "bkash",
    "metadata": {
        "phone": "01600000000"
    }
}

Verification Response Fields

Field Name Type Description
status string COMPLETED, PENDING, or ERROR.
cus_name string Name of the customer provided at payment initiation.
cus_email string Customer email address.
amount string Verified paid transaction amount.
transaction_id string Unique transaction identifier returned by DrutoPay.
payment_method string MFS channel used (e.g. bkash, nagad, rocket, upay).
metadata object Custom JSON object passed during checkout initiation.

3. Webhook Listener Implementation

Sample code for your server endpoint to receive, verify, and handle DrutoPay webhooks securely.

<?php
// webhook.php - DrutoPay Webhook Listener

// 1. Read incoming POST data (supports both Form POST and JSON payload)
$rawBody = file_get_contents('php://input');
$data = json_decode($rawBody, true) ?: $_POST;

$paymentMethod = $data['paymentMethod'] ?? '';
$transactionId = $data['transactionId'] ?? '';
$paymentAmount = $data['paymentAmount'] ?? 0;
$paymentFee    = $data['paymentFee'] ?? 0;
$cusName       = $data['cus_name'] ?? '';
$cusEmail      = $data['cus_email'] ?? '';
$cusPhone      = $data['cus_phone'] ?? '';
$metadata      = $data['metadata'] ?? '';
$status        = $data['status'] ?? '';

// 2. Validate payload presence
if (empty($transactionId) || empty($status)) {
    http_response_code(400);
    echo json_encode(['status' => 'error', 'message' => 'Invalid webhook payload']);
    exit;
}

// 3. Process completed payment
if ($status === 'completed') {
    // (Recommended) Verify transaction directly with DrutoPay API before crediting
    $isVerified = verifyDrutoPayTransaction($transactionId);

    if ($isVerified) {
        // TODO: Check if transactionId was already processed in your DB (Prevent duplicates)
        // TODO: Update order status to PAID / credit user balance in your database
        
        http_response_code(200);
        echo json_encode(['status' => 'success', 'message' => 'Webhook received and order fulfilled']);
        exit;
    }
}

http_response_code(200);
echo json_encode(['status' => 'ignored']);

// Helper function to verify transaction via DrutoPay Verify API
function verifyDrutoPayTransaction($trxId) {
    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_URL => 'https://pay.drutopay.com/api/payment/verify',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode(['transaction_id' => $trxId]),
        CURLOPT_HTTPHEADER => [
            'API-KEY: YOUR_BRAND_KEY',
            'Content-Type: application/json'
        ]
    ]);
    $res = curl_exec($curl);
    curl_close($curl);
    $result = json_decode($res, true);
    return !empty($result['status']) && ($result['status'] === true || $result['status'] === 'success' || $result['status'] === 1 || $result['status'] === '1');
}
?>
<?php
namespace App\Http\Controllers;

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

class DrutoPayWebhookController extends Controller
{
    public function handle(Request $request)
    {
        $transactionId = $request->input('transactionId');
        $paymentMethod = $request->input('paymentMethod');
        $paymentAmount = $request->input('paymentAmount');
        $cusName       = $request->input('cus_name');
        $cusEmail      = $request->input('cus_email');
        $metadata      = $request->input('metadata');
        $status        = $request->input('status');

        if ($status !== 'completed' || empty($transactionId)) {
            return response()->json(['status' => 'ignored'], 200);
        }

        // Verify transaction authenticity with DrutoPay API
        $verifyRes = Http::withHeaders([
            'API-KEY'      => env('DRUTOPAY_API_KEY'), // Your Brand Secret Key
            'Content-Type' => 'application/json'
        ])->post('https://pay.drutopay.com/api/payment/verify', [
            'transaction_id' => $transactionId
        ]);

        if ($verifyRes->successful() && $verifyRes->json('status')) {
            // TODO: Avoid duplicate credit by checking Order::where('trx_id', $transactionId)->exists()
            // TODO: Mark Order as Paid / credit user wallet

            return response()->json(['status' => 'success'], 200);
        }

        return response()->json(['status' => 'verification_failed'], 400);
    }
}
const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.post('/api/drutopay-webhook', async (req, res) => {
    const { paymentMethod, transactionId, paymentAmount, paymentFee, cus_name, cus_email, cus_phone, metadata, status } = req.body;

    if (status !== 'completed' || !transactionId) {
        return res.status(200).json({ status: 'ignored' });
    }

    try {
        // Verify transaction with DrutoPay server
        const verifyResponse = await axios.post('https://pay.drutopay.com/api/payment/verify', {
            transaction_id: transactionId
        }, {
            headers: {
                'API-KEY': 'YOUR_BRAND_KEY',
                'Content-Type': 'application/json'
            }
        });

        if (verifyResponse.data && verifyResponse.data.status) {
            // TODO: Check database to prevent duplicate processing
            // TODO: Update order to completed and deliver service
            return res.status(200).json({ status: 'success' });
        }
    } catch (err) {
        console.error('DrutoPay verification error:', err.message);
    }

    res.status(200).json({ status: 'received' });
});

app.listen(3000, () => console.log('Webhook server running on port 3000'));
from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route('/api/drutopay-webhook', methods=['POST'])
def drutopay_webhook():
    data = request.get_json(silent=True) or request.form.to_dict()
    
    transaction_id = data.get('transactionId')
    status = data.get('status')
    amount = data.get('paymentAmount')
    provider = data.get('paymentMethod')

    if status == 'completed' and transaction_id:
        # Verify transaction with DrutoPay API
        verify_url = "https://pay.drutopay.com/api/payment/verify"
        headers = {
            "API-KEY": "YOUR_BRAND_KEY",
            "Content-Type": "application/json"
        }
        resp = requests.post(verify_url, json={"transaction_id": transaction_id}, headers=headers)
        res_json = resp.json()

        if res_json.get('status'):
            # TODO: Update order in database to Paid
            return jsonify({"status": "success"}), 200

    return jsonify({"status": "received"}), 200

if __name__ == '__main__':
    app.run(port=5000)
Webhook Security & Best Practices:
  • Double Verification: Always call POST /api/payment/verify with the received transactionId to verify authentic status.
  • Idempotency / Anti-Replay: Record the transactionId in your database. If a webhook with an identical transactionId arrives again, ignore duplicate credits.
  • Quick 200 OK Response: Return an HTTP 200 OK status promptly once the notification is received.

Pre-built Plugins & Modules

Download ready-made integrations for popular CMS and billing systems.

100% Free Setup Service Support Group

প্লাগইন বা মডিউল সেটআপে যেকোনো সমস্যা? আমরা করে দেব সম্পূর্ণ ফ্রি!

WordPress (WooCommerce), WHMCS অথবা SMM প্যানেলে DrutoPay প্লাগইন/মডিউল সেটআপ করতে কোনো প্রকার সমস্যা বা জটিলতা মনে হলে সরাসরি আমাদের টেলিগ্রাম সাপোর্ট গ্রুপে মেসেজ দিন। আমাদের সাপোর্ট টিম সম্পূর্ণ বিনামূল্যে (Full Free) আপনার ওয়েবসাইটে সরাসরি গেটওয়ে ইন্টিগ্রেশন ও ফুল সেটআপ সম্পন্ন করে দেবে।

Need help with Plugin or Module setup? We'll do it 100% Free!

Facing any difficulty setting up DrutoPay on your WordPress (WooCommerce), WHMCS, or SMM Panel website? Simply drop a message in our Telegram Support Group. Our dedicated technical support engineers will handle the complete configuration and live verification on your site completely free of charge.

WooCommerce Payment Gateway Plugin
Plug-and-play checkout for WordPress & WooCommerce e-commerce stores.
Download ZIP
WHMCS Billing Gateway Module
Automated invoice settlement module for hosting and cloud providers.
Download ZIP
SMM Panel Deposit Gateway Module
Real-time automated user balance deposit module for SMM panels.
Download ZIP
DrutoPay Connect (Reader App)
Official Android background daemon that syncs incoming transaction SMS directly to your gateway.
Download APK

Developer Community & Support

Join our developer community to receive system announcements, plugin updates, and get technical help.