Merchant Integration Guide

PayChek ডকুমেন্টেশন

Session create → কাস্টমার চেকআউট → webhook/IPN → status verify — জনপ্রিয় পেমেন্ট গেটওয়ের মতো একই ধাপ, PayChek-এর Purpose ও settlement লজিকসহ।

১. Overview — পেমেন্ট লাইফসাইকেল

SSLCommerz / Stripe-এর মতো তিন ধাপ: SessionCustomer checkoutServer confirmation। ক্লায়েন্ট রিডাইরেক্টকে কখনোই সত্যের একমাত্র উৎস ধরবেন না।

1
Init

আপনার সার্ভার POST /api/v1/pay/init (HMAC)

2
Redirect

কাস্টমারকে checkoutUrl-এ পাঠান

3
Pay

bKash / Nagad ইত্যাদি দিয়ে টাকা পাঠায় + Trx

4
Webhook

PayChek আপনার URL-এ signed JSON পাঠায়

5
Verify

ঐচ্ছিক: GET …/status দিয়ে কনফার্ম

সত্যের উৎস: Webhook + Status API। Success পেজের query string শুধু UX — অর্ডার ফাইনাল করতে নয়।

২. Quick start

ইন্টিগ্রেশন সবসময় সার্ভার-টু-সার্ভার। Secret কখনো ব্রাউজার/মোবাইল অ্যাপে রাখবেন না।

1

অ্যাপে ওয়েবসাইট তৈরি

PayChek Android → API ট্যাব → নতুন ওয়েবসাইট। Domain + Purpose সিলেক্ট করে লক করুন। API Key ও Secret একবার দেখা যাবে — সেভ করুন।

2

Callback / Webhook URL

ওয়েবসাইট সেটিংসে success_url, cancel_url, callback_url / webhook_url সেট করুন (HTTPS বাধ্যতামূলক প্রোডাকশনে)।

3

Init → Redirect → Webhook

HMAC দিয়ে init → কাস্টমারকে checkoutUrl → webhook-এ অর্ডার আপডেট।

4

Test Experience

লাইভ চেষ্টা: /test — ছোট অ্যামাউন্টে ফ্লো দেখুন।

৩. Website Purpose

প্রতিটি সাইট একবার Purpose বেছে লক হয়। পরে চেঞ্জ শুধু Super Admin।

Add Balance

ওয়ালেট টপ-আপ। কাস্টমার চেকআউট অ্যামাউন্টই পাঠায়। Callback-এ walletCredit — মার্চেন্ট নিজে ক্রেডিট করে।

Payment

অর্ডার কমপ্লিট। চার্জ/কমিশন অনুযায়ী expectedPayable পাঠাতে হবে। কম দিলে multi-Trx settlement।

Both

একই API। Add Balance বাটন → purpose=add_balance। Buy/Pay → purpose=payment। খালি/ভুল → Hard Error।

লক নীতি: Confirm এর পর মার্চেন্ট UI থেকে চেঞ্জ বন্ধ। জরুরি হলে PayChek অ্যাডমিন আনলক করবে।

৪. Base URL & Environment

একই REST বেস — API Key দিয়ে অ্যাকাউন্ট আলাদা হয়।

আইটেমমান
Base URLhttps://paychek.online
InitPOST /api/v1/pay/init
StatusGET /api/v1/pay/:sessionToken/status
Currencyডিফল্ট BDT
Content-Typeapplication/json
টেস্ট: অফিসিয়াল /test এক্সপেরিয়েন্স + ছোট অ্যামাউন্ট। প্রোডাকশন Key/Secret আলাদা রাখুন; Secret কখনো গিটে কমিট করবেন না।

৫. Authentication & Credentials

প্রতি ওয়েবসাইটের আলাদা API Key + Secret (Stripe-এর publishable/secret ধারণার মতো)।

আইটেমকোথায় ব্যবহারনোট
Merchant IDওয়েবসাইট সেটিংস / callback payloadপাবলিক আইডেন্টিফায়ার
API Keyহেডার X-Api-KeyInit + Status
API SecretHMAC সাইন / webhook verifyশুধু সার্ভার — তৈরির সময় একবার দেখা যায়
ঘোরানো: Secret লিক হলে অ্যাপে Regenerate Secret করুন এবং সব সার্ভার env আপডেট করুন।

৬. API — pay/init

POST https://paychek.online/api/v1/pay/init — বডির উপর HMAC-SHA256 → X-Signature

Headers

HeaderRequiredবিবরণ
Content-TypeYesapplication/json
X-Api-KeyYesওয়েবসাইট API Key
X-SignatureYesHMAC-SHA256(hex) of raw JSON body

Request body

FieldTypeRequiredবিবরণ
amountnumberYes> 0। Add Balance = কাস্টমার পাঠাবে; Payment = order base
orderIdstringRecommendedআপনার অর্ডার/ইনভয়েস আইডি (max ~191)
purposestringBoth মোডে Yesadd_balance | payment
successUrlstringNo*সফলের পর কাস্টমার রিডাইরেক্ট (*ওয়েবসাইট ডিফল্ট থাকলে)
cancelUrlstringNo*বাতিল/এক্সপায়ার
callbackUrlstringNo*এই সেশনের callback override
webhookUrlstringNo*এই সেশনের webhook override
currencystringNoডিফল্ট BDT
customerNumberstringNoঐচ্ছিক কাস্টমার মোবাইল
expiresInSecnumberNo১২০–৮৬৪০০; ডিফল্ট ১৮০০
metaobjectNoকাস্টম ডেটা; meta.purposeও গ্রহণযোগ্য
EXAMPLE BODY
{
  "amount": 500,
  "orderId": "ORD-1001",
  "purpose": "payment",
  "successUrl": "https://yoursite.com/ok",
  "cancelUrl": "https://yoursite.com/cancel",
  "callbackUrl": "https://yoursite.com/hook"
}

Success response 201

JSON
{
  "success": true,
  "sessionToken": "ps_…",
  "checkoutUrl": "https://paychek.online/pay/ps_…",
  "channel": "paycheck",
  "amount": 500,
  "purpose": "payment",
  "expiresAt": "2026-07-22T12:00:00.000Z"
}
গুরুত্বপূর্ণ: Signature হিসাব করতে যে raw string পাঠাবেন, ঠিক সেই বাইটই HMAC-এ দিন। JSON পরে আবার stringify করলে 401 (INVALID_SIGNATURE)।
NODE — SIGN
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

৭. Status query (Order validation)

SSLCommerz Order Validation / bKash Query-এর মতো — সেশন স্ট্যাটাস সার্ভার থেকে নিশ্চিত করুন।

GET /api/v1/pay/:sessionToken/status

Header / QueryRequiredবিবরণ
X-Api-Key বা ?apiKey=Yesসেশন যে ওয়েবসাইটের, সেই Key
RESPONSE
{
  "success": true,
  "status": "success",
  "channel": "paycheck",
  "amount": 500,
  "orderId": "ORD-1001",
  "trxId": "ABC123",
  "completedAt": "…",
  "expiresAt": "…"
}
কখন ব্যবহার: Webhook মিস হলে, success পেজ লোডে, বা অর্ডার ফাইনাল করার আগে ডাবল-চেক।

৮. Customer redirect URLs

কাস্টমার ব্রাউজার ফ্লো — অর্ডার স্টেট আপডেটের জন্য নয়।

URLকখনQuery (উদাহরণ)
successUrlপেমেন্ট সফল?trxId=…&amount=…&status=success
cancelUrlবাতিল / সেশন এক্সপায়ার
Success পেজে শুধু «ধন্যবাদ» দেখান। অর্ডার paid করতে webhook বা status API ব্যবহার করুন।

৯. Add Balance ফ্লো

কাস্টমার সবসময় checkout amount পাঠায়। কমিশন/চার্জ শুধু walletCredit তথ্য।

1

Init

purpose: "add_balance" (Both সাইটে বাধ্যতামূলক; fixed সাইটে সার্ভার সেট করে)।

2

Checkout UI

«আপনি ৳500 পাঠান» + প্রোভাইডার অনুযায়ী «ওয়ালেটে ৳502 / ৳498 যোগ হবে»।

3

Callback

JSON
{
  "purpose": "add_balance",
  "trxId": "…",
  "amount": 500,
  "checkoutAmount": 500,
  "receivedAmount": 500,
  "walletCredit": 502,
  "provider": "bkash",
  "status": "SUCCESS"
}

মার্চেন্ট: customerWallet += walletCredit। PayChek ওয়ালেট ক্রেডিট করে না।

১০. Payment ফ্লো

অর্ডার সম্পন্ন করতে expectedPayable পরিশোধ করতে হবে (চার্জ/কমিশন + ৫০ পয়সা রাউন্ড)।

1

Init

purpose: "payment", amount = order base (যেমন ৫০০)।

2

Checkout

Order ৳500 → «Please send ৳502»। Verify SMS amount = পাঠানো টাকা।

3

সফল Callback

JSON
{
  "purpose": "payment",
  "trxId": "A1",
  "amount": 502,
  "orderAmount": 500,
  "expectedPayable": 502,
  "receivedAmount": 502,
  "transactions": [{ "trxId": "A1", "amount": 502 }],
  "status": "SUCCESS"
}

১১. Both মোড

এক ওয়েবসাইট, দুই বাটন টাইপ — প্রতিটি init-এ purpose আলাদা।

PSEUDO
// Add Balance button
await initPay({ amount: bal, purpose: "add_balance", orderId });

// Buy / Pay buttons
await initPay({ amount: price, purpose: "payment", orderId });
Hard Error: PURPOSE_REQUIRED / PURPOSE_INVALID

১২. Settlement / Overpay

শুধু Payment মোডে প্রযোজ্য।

1

কম দিলে

প্রথম Trx কম → «আরও ৳X পাঠান»। সর্বোচ্চ ৫টি Trx। যোগফল ≥ expectedPayable হলে SUCCESS।

2

বেশি দিলে

SUCCESS + overPaid। গেটওয়ে রিফান্ড করে না — মার্চেন্ট সিদ্ধান্ত নেবে।

3

পয়সা রাউন্ড

< ০.৫০ → floor; ≥ ০.৫০ → ceil। সব প্রোভাইডারে একই।

১৩. Webhook / IPN

PayChek আপনার callback_url এবং/অথবা webhook_url-এ POST করে (SSLCommerz IPN-এর মতো)।

আইটেমবিবরণ
MethodPOST application/json
SignatureX-Paychek-Signature = HMAC-SHA256(rawBody, api_secret)
Retryব্যর্থ হলে bounded exponential retry
Idempotencyএকই trxId একাধিকবার আসতে পারে — একবারই অর্ডার আপডেট

Common payload fields

Fieldসবসময়?নোট
trxId, amount, statusYesলেগাসি কী — backward compatible
provider, sender, merchantIdYes
purposeযখন জানাadd_balance / payment
walletCreditAdd Balanceমার্চেন্ট ওয়ালেট ক্রেডিট
orderAmount, expectedPayable, transactions[], overPaidPaymentsettlement সচেতন
payment_type, commission, chargeঅপশনালঅ্যাডমিন আনলক + মার্চেন্ট টগল
VERIFY
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);
Webhook এন্ডপয়েন্টে raw body পার্সার ব্যবহার করুন — পুনরায় stringify করলে সিগনেচার মিলবে না।

১৪. Payment Type / Commission unlock

অতিরিক্ত ফিল্ড — ডিফল্টে অ্যাডমিন লক।

পরিস্থিতিকী করবেন
নিজের সিস্টেমে provider/কমিশন হিসাব করতে পারেনলক রাখুন
শুধু কলব্যাকের মান দিয়ে ওয়ালেট ক্রেডিটঅ্যাডমিন আনলক → সেটিংসে টগল চালু
আনলক ছাড়া টগল → *_CALLBACK_LOCKED

১৫. Testing

প্রোডাকশনে যাওয়ার আগে এই চেকলিস্ট চালান।

  • /test দিয়ে checkout UX ও ছোট পেমেন্ট ফ্লো দেখুন
  • Init: valid signature → 201 + checkoutUrl
  • Init: wrong signature → 401 INVALID_SIGNATURE
  • Both মোড: purpose ছাড়া → PURPOSE_REQUIRED
  • Webhook: signature verify + idempotent trxId হ্যান্ডল
  • Status API: সফল সেশনে status/trxId মিলে
  • Add Balance vs Payment callback ফিল্ড আলাদা কিনা যাচাই

১৬. Security best practices

  • Secret শুধু সার্ভার env / secret manager-এ
  • সব init HMAC সাইন — Key একা যথেষ্ট নয়
  • Webhook signature verify (timing-safe compare পছন্দনীয়)
  • HTTPS callback/webhook URL
  • ক্লায়েন্ট রিডাইরেক্টকে trust করবেন না
  • Idempotent webhook (trxId / orderId ডুপ্লিকেট গার্ড)
  • Amount/orderId আপনার DB-র সাথে মিলিয়ে নিন
  • Rate limit (HTTP 429) হলে exponential backoff

১৭. Go-live checklist

#চেক
1Website Purpose লক (Add Balance / Payment / Both)
2Production API Key + Secret সেভ; টেস্ট ক্রেডেনশিয়াল আলাদা
3success / cancel / callback / webhook URL লাইভ ও HTTPS
4গেটওয়ে নাম্বার ও কমিশন রুলস অ্যাপে কনফিগার
5Webhook এন্ডপয়েন্ট ২xx + signature + idempotency
6Status query ফallback ইমপ্লিমেন্ট
7ছোট রিয়েল পেমেন্ট দিয়ে E2E টেস্ট
8ডিভাইস অনলাইন / SMS মনিটর চালু (PayChek অ্যাপ)

১৮. Frameworks

প্রতিটি ভাষায় একই কন্ট্র্যাক্ট: sign → init → redirect → webhook → (status)।

১৯. Errors & FAQ

কোড / Errorঅর্থসমাধান
PURPOSE_REQUIREDBoth মোডে purpose নেইadd_balance বা payment পাঠান
PURPOSE_INVALIDভুল purposeশুধু দুই মান
PURPOSE_LOCKEDমার্চেন্ট চেঞ্জ করতে চায়অ্যাডমিন আনলক
INVALID_AMOUNTamount ≤ 0পজিটিভ নাম্বার
INVALID_SIGNATUREHMAC মিলেনিraw body + secret
MISSING_SIGNATUREX-Signature নেইহেডার যোগ করুন
MERCHANT_SECRET_NOT_CONFIGUREDSecret নেইRegenerate / সাপোর্ট
SESSION_NOT_FOUNDস্ট্যাটাস টোকেন ভুলinit-এর sessionToken
FORBIDDENStatus-এ ভুল API Keyসঠিক Key
429Rate limitbackoff + retry
সাহায্য: helaldada510@gmail.com · /test