Add Balance
ওয়ালেট টপ-আপ। কাস্টমার চেকআউট অ্যামাউন্টই পাঠায়। Callback-এ walletCredit — মার্চেন্ট নিজে ক্রেডিট করে।
Session create → কাস্টমার চেকআউট → webhook/IPN → status verify — জনপ্রিয় পেমেন্ট গেটওয়ের মতো একই ধাপ, PayChek-এর Purpose ও settlement লজিকসহ।
SSLCommerz / Stripe-এর মতো তিন ধাপ: Session → Customer checkout → Server confirmation। ক্লায়েন্ট রিডাইরেক্টকে কখনোই সত্যের একমাত্র উৎস ধরবেন না।
আপনার সার্ভার POST /api/v1/pay/init (HMAC)
কাস্টমারকে checkoutUrl-এ পাঠান
bKash / Nagad ইত্যাদি দিয়ে টাকা পাঠায় + Trx
PayChek আপনার URL-এ signed JSON পাঠায়
ঐচ্ছিক: GET …/status দিয়ে কনফার্ম
ইন্টিগ্রেশন সবসময় সার্ভার-টু-সার্ভার। Secret কখনো ব্রাউজার/মোবাইল অ্যাপে রাখবেন না।
PayChek Android → API ট্যাব → নতুন ওয়েবসাইট। Domain + Purpose সিলেক্ট করে লক করুন। API Key ও Secret একবার দেখা যাবে — সেভ করুন।
ওয়েবসাইট সেটিংসে success_url, cancel_url, callback_url / webhook_url সেট করুন (HTTPS বাধ্যতামূলক প্রোডাকশনে)।
HMAC দিয়ে init → কাস্টমারকে checkoutUrl → webhook-এ অর্ডার আপডেট।
লাইভ চেষ্টা: /test — ছোট অ্যামাউন্টে ফ্লো দেখুন।
প্রতিটি সাইট একবার Purpose বেছে লক হয়। পরে চেঞ্জ শুধু Super Admin।
ওয়ালেট টপ-আপ। কাস্টমার চেকআউট অ্যামাউন্টই পাঠায়। Callback-এ walletCredit — মার্চেন্ট নিজে ক্রেডিট করে।
অর্ডার কমপ্লিট। চার্জ/কমিশন অনুযায়ী expectedPayable পাঠাতে হবে। কম দিলে multi-Trx settlement।
একই API। Add Balance বাটন → purpose=add_balance। Buy/Pay → purpose=payment। খালি/ভুল → Hard Error।
একই REST বেস — API Key দিয়ে অ্যাকাউন্ট আলাদা হয়।
| আইটেম | মান |
|---|---|
| Base URL | https://paychek.online |
| Init | POST /api/v1/pay/init |
| Status | GET /api/v1/pay/:sessionToken/status |
| Currency | ডিফল্ট BDT |
| Content-Type | application/json |
প্রতি ওয়েবসাইটের আলাদা API Key + Secret (Stripe-এর publishable/secret ধারণার মতো)।
| আইটেম | কোথায় ব্যবহার | নোট |
|---|---|---|
| Merchant ID | ওয়েবসাইট সেটিংস / callback payload | পাবলিক আইডেন্টিফায়ার |
| API Key | হেডার X-Api-Key | Init + Status |
| API Secret | HMAC সাইন / webhook verify | শুধু সার্ভার — তৈরির সময় একবার দেখা যায় |
POST https://paychek.online/api/v1/pay/init — বডির উপর HMAC-SHA256 → X-Signature।
| Header | Required | বিবরণ |
|---|---|---|
Content-Type | Yes | application/json |
X-Api-Key | Yes | ওয়েবসাইট API Key |
X-Signature | Yes | HMAC-SHA256(hex) of raw JSON body |
| Field | Type | Required | বিবরণ |
|---|---|---|---|
amount | number | Yes | > 0। Add Balance = কাস্টমার পাঠাবে; Payment = order base |
orderId | string | Recommended | আপনার অর্ডার/ইনভয়েস আইডি (max ~191) |
purpose | string | Both মোডে Yes | add_balance | payment |
successUrl | string | No* | সফলের পর কাস্টমার রিডাইরেক্ট (*ওয়েবসাইট ডিফল্ট থাকলে) |
cancelUrl | string | No* | বাতিল/এক্সপায়ার |
callbackUrl | string | No* | এই সেশনের callback override |
webhookUrl | string | No* | এই সেশনের webhook override |
currency | string | No | ডিফল্ট BDT |
customerNumber | string | No | ঐচ্ছিক কাস্টমার মোবাইল |
expiresInSec | number | No | ১২০–৮৬৪০০; ডিফল্ট ১৮০০ |
meta | object | No | কাস্টম ডেটা; meta.purposeও গ্রহণযোগ্য |
{
"amount": 500,
"orderId": "ORD-1001",
"purpose": "payment",
"successUrl": "https://yoursite.com/ok",
"cancelUrl": "https://yoursite.com/cancel",
"callbackUrl": "https://yoursite.com/hook"
}
201{
"success": true,
"sessionToken": "ps_…",
"checkoutUrl": "https://paychek.online/pay/ps_…",
"channel": "paycheck",
"amount": 500,
"purpose": "payment",
"expiresAt": "2026-07-22T12:00:00.000Z"
}
INVALID_SIGNATURE)।const crypto = require('crypto');
const raw = JSON.stringify(body);
const sig = crypto.createHmac('sha256', process.env.PAYCHEK_SECRET)
.update(raw).digest('hex');
// headers: Content-Type, X-Api-Key, X-Signature
// POST the same `raw` bytes as body
SSLCommerz Order Validation / bKash Query-এর মতো — সেশন স্ট্যাটাস সার্ভার থেকে নিশ্চিত করুন।
GET /api/v1/pay/:sessionToken/status
| Header / Query | Required | বিবরণ |
|---|---|---|
X-Api-Key বা ?apiKey= | Yes | সেশন যে ওয়েবসাইটের, সেই Key |
{
"success": true,
"status": "success",
"channel": "paycheck",
"amount": 500,
"orderId": "ORD-1001",
"trxId": "ABC123",
"completedAt": "…",
"expiresAt": "…"
}
কাস্টমার ব্রাউজার ফ্লো — অর্ডার স্টেট আপডেটের জন্য নয়।
| URL | কখন | Query (উদাহরণ) |
|---|---|---|
successUrl | পেমেন্ট সফল | ?trxId=…&amount=…&status=success |
cancelUrl | বাতিল / সেশন এক্সপায়ার | — |
paid করতে webhook বা status API ব্যবহার করুন।কাস্টমার সবসময় checkout amount পাঠায়। কমিশন/চার্জ শুধু walletCredit তথ্য।
purpose: "add_balance" (Both সাইটে বাধ্যতামূলক; fixed সাইটে সার্ভার সেট করে)।
«আপনি ৳500 পাঠান» + প্রোভাইডার অনুযায়ী «ওয়ালেটে ৳502 / ৳498 যোগ হবে»।
{
"purpose": "add_balance",
"trxId": "…",
"amount": 500,
"checkoutAmount": 500,
"receivedAmount": 500,
"walletCredit": 502,
"provider": "bkash",
"status": "SUCCESS"
}
মার্চেন্ট: customerWallet += walletCredit। PayChek ওয়ালেট ক্রেডিট করে না।
অর্ডার সম্পন্ন করতে expectedPayable পরিশোধ করতে হবে (চার্জ/কমিশন + ৫০ পয়সা রাউন্ড)।
purpose: "payment", amount = order base (যেমন ৫০০)।
Order ৳500 → «Please send ৳502»। Verify SMS amount = পাঠানো টাকা।
{
"purpose": "payment",
"trxId": "A1",
"amount": 502,
"orderAmount": 500,
"expectedPayable": 502,
"receivedAmount": 502,
"transactions": [{ "trxId": "A1", "amount": 502 }],
"status": "SUCCESS"
}
এক ওয়েবসাইট, দুই বাটন টাইপ — প্রতিটি init-এ purpose আলাদা।
// Add Balance button
await initPay({ amount: bal, purpose: "add_balance", orderId });
// Buy / Pay buttons
await initPay({ amount: price, purpose: "payment", orderId });
PURPOSE_REQUIRED / PURPOSE_INVALIDশুধু Payment মোডে প্রযোজ্য।
প্রথম Trx কম → «আরও ৳X পাঠান»। সর্বোচ্চ ৫টি Trx। যোগফল ≥ expectedPayable হলে SUCCESS।
SUCCESS + overPaid। গেটওয়ে রিফান্ড করে না — মার্চেন্ট সিদ্ধান্ত নেবে।
< ০.৫০ → floor; ≥ ০.৫০ → ceil। সব প্রোভাইডারে একই।
PayChek আপনার callback_url এবং/অথবা webhook_url-এ POST করে (SSLCommerz IPN-এর মতো)।
| আইটেম | বিবরণ |
|---|---|
| Method | POST application/json |
| Signature | X-Paychek-Signature = HMAC-SHA256(rawBody, api_secret) |
| Retry | ব্যর্থ হলে bounded exponential retry |
| Idempotency | একই trxId একাধিকবার আসতে পারে — একবারই অর্ডার আপডেট |
| Field | সবসময়? | নোট |
|---|---|---|
trxId, amount, status | Yes | লেগাসি কী — backward compatible |
provider, sender, merchantId | Yes | — |
purpose | যখন জানা | add_balance / payment |
walletCredit … | Add Balance | মার্চেন্ট ওয়ালেট ক্রেডিট |
orderAmount, expectedPayable, transactions[], overPaid | Payment | settlement সচেতন |
payment_type, commission, charge | অপশনাল | অ্যাডমিন আনলক + মার্চেন্ট টগল |
const expected = crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');
if (sig !== expected) return res.sendStatus(401);
// respond 2xx quickly, then process async if needed
res.sendStatus(200);
অতিরিক্ত ফিল্ড — ডিফল্টে অ্যাডমিন লক।
| পরিস্থিতি | কী করবেন |
|---|---|
| নিজের সিস্টেমে provider/কমিশন হিসাব করতে পারেন | লক রাখুন |
| শুধু কলব্যাকের মান দিয়ে ওয়ালেট ক্রেডিট | অ্যাডমিন আনলক → সেটিংসে টগল চালু |
*_CALLBACK_LOCKEDপ্রোডাকশনে যাওয়ার আগে এই চেকলিস্ট চালান।
| # | চেক |
|---|---|
| 1 | Website Purpose লক (Add Balance / Payment / Both) |
| 2 | Production API Key + Secret সেভ; টেস্ট ক্রেডেনশিয়াল আলাদা |
| 3 | success / cancel / callback / webhook URL লাইভ ও HTTPS |
| 4 | গেটওয়ে নাম্বার ও কমিশন রুলস অ্যাপে কনফিগার |
| 5 | Webhook এন্ডপয়েন্ট ২xx + signature + idempotency |
| 6 | Status query ফallback ইমপ্লিমেন্ট |
| 7 | ছোট রিয়েল পেমেন্ট দিয়ে E2E টেস্ট |
| 8 | ডিভাইস অনলাইন / SMS মনিটর চালু (PayChek অ্যাপ) |
প্রতিটি ভাষায় একই কন্ট্র্যাক্ট: sign → init → redirect → webhook → (status)।
| কোড / Error | অর্থ | সমাধান |
|---|---|---|
| PURPOSE_REQUIRED | Both মোডে purpose নেই | add_balance বা payment পাঠান |
| PURPOSE_INVALID | ভুল purpose | শুধু দুই মান |
| PURPOSE_LOCKED | মার্চেন্ট চেঞ্জ করতে চায় | অ্যাডমিন আনলক |
| INVALID_AMOUNT | amount ≤ 0 | পজিটিভ নাম্বার |
| INVALID_SIGNATURE | HMAC মিলেনি | raw body + secret |
| MISSING_SIGNATURE | X-Signature নেই | হেডার যোগ করুন |
| MERCHANT_SECRET_NOT_CONFIGURED | Secret নেই | Regenerate / সাপোর্ট |
| SESSION_NOT_FOUND | স্ট্যাটাস টোকেন ভুল | init-এর sessionToken |
| FORBIDDEN | Status-এ ভুল API Key | সঠিক Key |
| 429 | Rate limit | backoff + retry |