API ডকুমেন্টেশন
Base URL: https://epay.nagad.top/api/v1 · সব রিকোয়েস্ট ও রেসপন্স JSON · অ্যামাউন্ট BDT (টাকা), যেমন "500" বা "499.50"।
অথেনটিকেশন
ড্যাশবোর্ডের API ও ওয়েবহুক পেজ থেকে key নিন (cpk_…) এবং প্রতি রিকোয়েস্টে পাঠান:
Authorization: Bearer cpk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Key কেবল সার্ভার-সাইডে ব্যবহার করুন।
১. পেমেন্ট তৈরি
POST /api/v1/payments
| ফিল্ড | বিবরণ |
|---|---|
amount * | পরিমাণ (কমপক্ষে 1.00) |
order_id | আপনার সিস্টেমের অর্ডার নম্বর |
description | চেকআউটে দেখানো বিবরণ |
customer_name / customer_email / customer_phone | গ্রাহকের তথ্য |
success_url / cancel_url | পেমেন্ট শেষে গ্রাহক যেখানে ফিরবে (?payment_id=&order_id=&status= যুক্ত হয়ে) |
webhook_url | এই পেমেন্টের জন্য আলাদা ওয়েবহুক URL (ঐচ্ছিক) |
expires_in | মিনিটে মেয়াদ, ৫–১৪৪০ (ডিফল্ট ৩০) |
metadata | আপনার নিজস্ব JSON অবজেক্ট (সর্বোচ্চ ২ কেবি) |
Header Idempotency-Key | একই কী দিয়ে আবার কল করলে নতুন পেমেন্ট না হয়ে আগেরটি ফেরত আসে |
curl -X POST https://epay.nagad.top/api/v1/payments \
-H "Authorization: Bearer cpk_..." \
-H "Content-Type: application/json" \
-d '{"amount":"500","order_id":"INV-1001","description":"Premium plan",
"success_url":"https://yoursite.com/thanks","cancel_url":"https://yoursite.com/cart",
"customer_phone":"01700000000"}'রেসপন্স 201:
{
"id": "pay_9f2c4e8a1b7d3c6f0a5e2d41",
"order_id": "INV-1001",
"status": "pending",
"amount": "500.00",
"currency": "BDT",
"pay_url": "https://epay.nagad.top/pay.php?id=pay_9f2c4e8a1b7d3c6f0a5e2d41",
"expires_at": "2026-10-19 12:00:00",
...
}গ্রাহককে pay_url-এ রিডাইরেক্ট করুন।
২. পেমেন্ট দেখা / তালিকা / বাতিল
GET /api/v1/payments/{id}
GET /api/v1/payments?status=paid&limit=20&order_id=INV-1001
POST /api/v1/payments/{id}/cancelstatus: pending · paid · expired · cancelled
৩. ওয়েবহুক
পেমেন্টের অবস্থা বদলালে আপনার Webhook URL-এ POST যায়। ইভেন্ট: payment.succeeded, payment.expired, payment.cancelled। আপনার সার্ভার 2xx দিলে সফল; নইলে ১ মি, ৫ মি, ৩০ মি, ২ ঘণ্টা, ৬ ঘণ্টা, ১২ ঘণ্টা, ২৪ ঘণ্টা পরে আবার চেষ্টা হয় (মোট ৮ বার)।
POST /your-webhook
X-EPAY-Event: payment.succeeded
X-EPAY-Signature: t=1760851200,v1=5b1c…(hex HMAC-SHA256)
{"event":"payment.succeeded","created_at":"2026-10-19 11:30:02",
"data":{"id":"pay_…","order_id":"INV-1001","status":"paid","amount":"500.00",
"received_amount":"500.00","method":"bKash","trx_id":"8N7A6D5E4C", ...}}সিগনেচার যাচাই করুন (সিক্রেট ড্যাশবোর্ডে পাবেন): HMAC_SHA256(secret, t + "." + rawBody) — এবং t ৫ মিনিটের বেশি পুরোনো হলে বাতিল করুন। একই ইভেন্ট একাধিকবার আসতে পারে, তাই অর্ডার আপডেট idempotent রাখুন।
PHP
$raw = file_get_contents("php://input");
parse_str(str_replace(",", "&", $_SERVER["HTTP_X_EPAY_SIGNATURE"] ?? ""), $s); // t, v1
$ok = isset($s["t"], $s["v1"]) && abs(time() - (int)$s["t"]) < 300
&& hash_equals(hash_hmac("sha256", $s["t"] . "." . $raw, $WEBHOOK_SECRET), $s["v1"]);
if (!$ok) { http_response_code(400); exit; }
$e = json_decode($raw, true);
if ($e["event"] === "payment.succeeded") { /* অর্ডার পেইড করুন: $e["data"]["order_id"] */ }
http_response_code(200);Node.js (Express)
const crypto = require("crypto");
app.post("/cp-webhook", express.raw({type: "application/json"}), (req, res) => {
const [t, v1] = req.get("X-EPAY-Signature").split(",").map(x => x.split("=")[1]);
const mac = crypto.createHmac("sha256", process.env.CP_SECRET).update(t + "." + req.body).digest("hex");
if (Math.abs(Date.now()/1000 - t) > 300 || !crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(v1))) return res.sendStatus(400);
const e = JSON.parse(req.body);
// handle e.event / e.data
res.sendStatus(200);
});Python (Flask)
import hmac, hashlib, time, json
@app.post("/cp-webhook")
def hook():
raw = request.get_data()
p = dict(x.split("=", 1) for x in request.headers["X-EPAY-Signature"].split(","))
mac = hmac.new(SECRET.encode(), (p["t"] + ".").encode() + raw, hashlib.sha256).hexdigest()
if abs(time.time() - int(p["t"])) > 300 or not hmac.compare_digest(mac, p["v1"]): return "", 400
e = json.loads(raw)
return "", 200
৪. সম্পূর্ণ ফ্লো (সংক্ষেপে)
- আপনার সার্ভার →
POST /payments→pay_url - গ্রাহককে
pay_url-এ পাঠান; সে নম্বরে টাকা পাঠিয়ে TrxID দেয় - SMS মিললে ওয়েবহুক
payment.succeededআসে - গ্রাহক
success_url-এ ফেরে — শুধু এই রিডাইরেক্টের ভরসায় অর্ডার দেবেন না; ওয়েবহুক বাGET /payments/{id}দিয়ে নিশ্চিত হোন
এরর
{"error":{"type":"invalid_amount","message":"..."}}401 key ভুল · 404 পাওয়া যায়নি · 409 অবস্থা/সেটআপ সমস্যা · 422 ইনপুট ভুল · 429 রেট-লিমিট