ShopnoPay আপনার ফোনে আসা অফিশিয়াল মোবাইল-ওয়ালেট “টাকা পেয়েছেন” SMS থেকে শুধু trx_id, amount, sender_number সার্ভারে নেয়। কাস্টমার পেমেন্ট পেজে TrxID দিলে অথবা SMS আসলে সার্ভার সেটি ইনভয়েসের সাথে মিলিয়ে পেমেন্ট কনফার্ম করে ও আপনার ওয়েবসাইটে Webhook পাঠায়।
সব রিকোয়েস্ট ও রেসপন্স JSON। সবসময় HTTPS ব্যবহার করুন।
আপনার ওয়েবসাইট/সার্ভার থেকে প্রতিটি রিকোয়েস্টে তিনটি হেডার একসাথে দিতে হবে। একটিও ভুল বা অনুপস্থিত হলে 401 আসবে। (ShopnoPay মোবাইল অ্যাপ আলাদা — সেখানে শুধু একটি Device Key লাগে, নিচে দেখুন।)
| হেডার | কী | কোথায় রাখবেন |
|---|---|---|
X-Brand-Key | ব্র্যান্ড শনাক্তকারী (br_…) | সার্ভার — প্রকাশ্য হতে পারে |
X-API-Key | API অ্যাক্সেস কী (ak_…) | সার্ভার |
X-Secret-Key | গোপন কী (sk_…) | শুধু আপনার সার্ভারে। ব্রাউজার/ফ্রন্টএন্ডে কখনো নয় |
GET https://shopnopuron.xyz.megalifebd.com/api/v1/ping
X-Brand-Key: br_xxxxxxxxxxxx
X-API-Key: ak_xxxxxxxxxxxxxxxx
X-Secret-Key: sk_xxxxxxxxxxxxxxxxসামঞ্জস্যের জন্য Authorization: Bearer <API Key> হেডারও API Key হিসেবে গ্রহণ করা হয়, তবে Brand Key ও Secret Key তখনও বাধ্যতামূলক।
একই ক্রেডেনশিয়াল দুই মোডে চলে। স্যান্ডবক্স ডেটা লাইভ ডেটা থেকে সম্পূর্ণ আলাদা এবং প্ল্যান কোটায় গণনা হয় না।
| মোড | Base URL |
|---|---|
| Live | https://shopnopuron.xyz.megalifebd.com/api/v1 |
| Sandbox | https://shopnopuron.xyz.megalifebd.com/api/v1/sandbox |
লাইভ এন্ডপয়েন্টে সক্রিয় প্ল্যান ও অন্তত একটি রিসিভিং ওয়ালেট নম্বর প্রয়োজন; স্যান্ডবক্সে নয়।
{
"success": false,
"error": "invalid_credentials",
"message": "Brand Key, API Key and Secret Key do not match."
}| HTTP | error | অর্থ |
|---|---|---|
| 401 | missing_credentials / invalid_credentials | তিনটি কি সঠিকভাবে দেওয়া হয়নি |
| 402 | plan_required / quota_exceeded | প্ল্যান নেই/মেয়াদোত্তীর্ণ বা মাসিক লিমিট শেষ |
| 403 | brand_suspended / account_suspended / device_limit / demo_brand | অ্যাক্সেস নিষিদ্ধ |
| 404 | not_found | পেমেন্ট পাওয়া যায়নি |
| 422 | invalid_request / invalid_* | প্যারামিটার ভুল |
| 429 | rate_limited | অতিরিক্ত রিকোয়েস্ট |
pending → completed | expired | cancelled | failed
| প্যারামিটার | টাইপ | বিবরণ |
|---|---|---|
| amount * | number | ১ থেকে ১০,০০,০০০ |
| reference | string | আপনার অর্ডার আইডি (সর্বোচ্চ ১০০ অক্ষর) |
| redirect_url | url | সফল পেমেন্টের পর কাস্টমারকে এখানে পাঠানো হবে (ব্র্যান্ডের ডিফল্ট থাকলে ঐচ্ছিক) |
| cancel_url | url | বাতিল করলে |
| webhook_url | url | এই ইনভয়েসের জন্য আলাদা Webhook (ব্র্যান্ডের URL ওভাররাইড করে) |
| customer_name / customer_email / customer_phone | string | ঐচ্ছিক |
| metadata | object | আপনার নিজস্ব ডেটা (≤ ২০০০ বাইট), Webhook-এ ফেরত আসে |
curl -X POST https://shopnopuron.xyz.megalifebd.com/api/v1/payments \
-H "X-Brand-Key: br_xxxxxxxx" -H "X-API-Key: ak_xxxxxxxx" -H "X-Secret-Key: sk_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"amount": 1250, "reference": "ORDER-1001", "redirect_url": "https://shop.com/thanks"}'{
"success": true,
"payment": {
"invoice_id": "INV3F9A1C2B7D4E5",
"reference": "ORDER-1001",
"amount": 1250,
"currency": "BDT",
"status": "pending",
"expires_at": "2026-10-11 20:45:00",
"payment_url": "https://shopnopuron.xyz.megalifebd.com/pay/INV3F9A1C2B7D4E5"
}
}কাস্টমারকে payment_url-এ পাঠান।
অথবা ?reference=ORDER-1001 দিয়ে সর্বশেষ মিলে যাওয়া পেমেন্ট।
কাস্টমার রিডাইরেক্টে ফিরে আসলে সবসময় সার্ভার থেকে ভেরিফাই করুন — রিডাইরেক্ট URL-এর প্যারামিটারকে বিশ্বাস করবেন না।
// শুধু স্ট্যাটাস দেখতে
{ "invoice_id": "INV3F9A1C2B7D4E5" }
// নির্দিষ্ট TrxID এই ইনভয়েসের সাথে মেলাতে (আপনার নিজের ফর্মে TrxID নিলে)
{ "invoice_id": "INV3F9A1C2B7D4E5", "trx_id": "9GK4X2LM" }{ "success": true, "verified": true, "reason": null, "payment": { "status": "completed", "trx_id": "9GK4X2LM", ... } }verified শুধু তখনই true যখন status completed। রিসিভড অ্যামাউন্ট ইনভয়েসের চেয়ে কম হলে মেলানো হয় না।
<?php
// 1) checkout.php — ইনভয়েস বানিয়ে কাস্টমারকে পাঠান
function shopnopay($method, $path, $body = null) {
$ch = curl_init('https://shopnopuron.xyz.megalifebd.com/api/v1' . $path);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-Brand-Key: ' . BRAND_KEY, 'X-API-Key: ' . API_KEY, 'X-Secret-Key: ' . SECRET_KEY, 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => $body ? json_encode($body) : null,
]);
return json_decode(curl_exec($ch), true);
}
$r = shopnopay('POST', '/payments', ['amount' => $order['total'], 'reference' => $order['id'], 'redirect_url' => 'https://shop.com/thanks.php']);
header('Location: ' . $r['payment']['payment_url']);
// 2) thanks.php — redirect-এ ফিরলে সার্ভার থেকে নিশ্চিত হোন
$r = shopnopay('POST', '/verify', ['invoice_id' => $_GET['invoice_id']]);
if ($r['verified']) { /* অর্ডার পেইড মার্ক করুন */ }ড্যাশবোর্ডের ব্র্যান্ড সেটিংসে Webhook URL দিন (বা প্রতিটি ইনভয়েসে webhook_url)। ইভেন্ট:
payment.completed · payment.expired · payment.failed · payment.cancelled
POST /webhook HTTP/1.1
Content-Type: application/json
X-ShopnoPay-Event: payment.completed
X-ShopnoPay-Timestamp: 1760186000
X-ShopnoPay-Signature: sha256=3f1c…e9
{
"id": "evt_8f2a91c4d7e03b65",
"event": "payment.completed",
"created": 1760186000,
"data": {
"invoice_id": "INV3F9A1C2B7D4E5",
"reference": "ORDER-1001",
"amount": 1250,
"currency": "BDT",
"status": "completed",
"provider": "bkash",
"trx_id": "9GK4X2LM",
"sender_number": "01712345678",
"metadata": null,
"sandbox": false,
"paid_at": "2026-10-11 20:15:03",
"brand_key": "br_xxxxxxxx"
}
}আপনার এন্ডপয়েন্ট দ্রুত HTTP 2xx রিটার্ন করবে (৫ সেকেন্ডের মধ্যে)। একই ইভেন্ট একাধিকবার আসতে পারে — data.invoice_id দিয়ে ইডেম্পোটেন্ট রাখুন।
সিগনেচার = HMAC_SHA256(webhook_secret, timestamp + "." + raw_body)। Webhook Secret (whsec_…) ড্যাশবোর্ডে ব্র্যান্ড পেজে পাবেন — এটি Secret Key থেকে আলাদা।
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_SHOPNOPAY_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_SHOPNOPAY_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $raw, WEBHOOK_SECRET);
if (!hash_equals($expected, $sig) || abs(time() - (int)$ts) > 300) {
http_response_code(401); exit('bad signature');
}
$event = json_decode($raw, true);
if ($event['event'] === 'payment.completed') {
// $event['data']['reference'] অর্ডারটি পেইড করুন
}
http_response_code(200);const crypto = require('crypto');
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.header('X-ShopnoPay-Timestamp');
const sig = req.header('X-ShopnoPay-Signature');
const expected = 'sha256=' + crypto.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(ts + '.' + req.body.toString('utf8')).digest('hex');
const ok = sig && sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok) return res.sendStatus(401);
const event = JSON.parse(req.body);
res.sendStatus(200);
});import hmac, hashlib, time
def verify(raw: bytes, ts: str, sig: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(secret.encode(), ts.encode() + b'.' + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig) and abs(time.time() - int(ts)) < 3002xx ছাড়া অন্য রেসপন্স বা টাইমআউট হলে আমরা আবার চেষ্টা করি: ১ মিনিট → ৫ মিনিট → ৩০ মিনিট → ২ ঘণ্টা → ১২ ঘণ্টা। এরপরও ব্যর্থ হলে ইভেন্ট failed হয় — ড্যাশবোর্ডের Webhook লগ থেকে ম্যানুয়ালি রিসেন্ড করা যায়। Webhook URL অবশ্যই পাবলিক হোস্টে হতে হবে (লোকালহোস্ট/প্রাইভেট IP ব্লক করা হয়)।
অ্যাপ: শুধু X-Device-Key: dk_… হেডার (ড্যাশবোর্ড → ডিভাইস থেকে নেওয়া)। সার্ভার থেকে কল করলে ৩টি কি। অ্যাপের “Test connection” এ ব্যবহৃত হয়। ঐচ্ছিক হেডার: X-Device-Id (অ্যাপ-জেনারেটেড ইউনিক আইডি), X-Device-Name, X-App-Version — এগুলো দিলে ফোনটি ড্যাশবোর্ডের “ডিভাইস” তালিকায় দেখা যায়।
হেডার: X-Device-Key।
{
"success": true,
"total": 42, "processed": 37, "pending": 4, "failed": 1,
"amount": 52340.5,
"week": [[3,1,0],[5,0,0],[4,1,0],[6,0,1],[7,1,0],[5,0,0],[7,1,0]]
}week = শেষ ৭ দিন (পুরোনো→নতুন), প্রতিটি [processed, pending, failed]।
হেডার: X-Device-Key (অ্যাপ) অথবা ৩টি কি (সার্ভার)। ডিভাইস কি শুধু ping, stats, transactions এন্ডপয়েন্টে চলে — পেমেন্ট তৈরি/ভেরিফাই করা যায় না।
অ্যাপ প্রতিটি “টাকা পেয়েছেন” SMS থেকে TrxID, পরিমাণ, প্রেরকের নম্বর ও প্রোভাইডারের নাম পাঠায়:
{ "trx_id": "9GK4X2LM", "amount": 1250.00, "sender_number": "01712345678", "provider": "bKash" }{ "success": true, "id": 981, "status": "processed", "matched_payment": 77 }একই trx_id আবার পাঠালে 200 ও \"duplicate\": true — অ্যাপ নিরাপদে রিট্রাই করতে পারে। অপশনাল provider (bkash, nagad…) দেওয়া যায়। ইনভয়েসে মিল পেলে সাথে সাথে পেমেন্ট completed হয় ও Webhook যায়।
Base URL-এ /sandbox যোগ করুন (https://shopnopuron.xyz.megalifebd.com/api/v1/sandbox/payments)। এর পেমেন্ট URL-এ “সিমুলেট” বাটন থাকে, অথবা API দিয়ে:
{ "invoice_id": "SBX…", "provider": "bkash" }এটি একটি ফেক SMS ট্রানজ্যাকশন তৈরি করে পেমেন্ট কনফার্ম করে ও Webhook পাঠায়। পাবলিক ডেমো ক্রেডেনশিয়াল স্যান্ডবক্স পেজে আছে।
প্রতি ব্র্যান্ডে ২৪০ রিকোয়েস্ট/মিনিট। ভুল ক্রেডেনশিয়ালে প্রতি IP-তে ১০ মিনিটে ৩০ বার চেষ্টা করা যায়। মাসিক পেমেন্ট/ট্রানজ্যাকশন লিমিট প্ল্যান অনুযায়ী (আনলিমিটেড প্ল্যানে নেই)।