QRPayBD-র সাইন-আপ পেজ খুলবে

কাস্টম ওয়েবসাইটে পেমেন্ট কনফার্মেশন: অর্ডার তৈরি, webhook ও HMAC সিগনেচার যাচাই

নিজের তৈরি ওয়েবসাইটে ওয়ালেট পেমেন্ট কনফার্মেশন যোগ করতে হলে প্রবাহটা এমন: সার্ভার থেকে REST API দিয়ে একটা অর্ডার বানান, গ্রাহককে রেসপন্সের paymentUrl-এ পাঠান, তারপর পেমেন্ট হলে QRPayBD যে সাইন করা webhook পাঠায় সেটা গ্রহণ করুন। webhook-এর HMAC সিগনেচার raw বডির ওপর যাচাই না করে অর্ডার পেইড মার্ক করবেন না। এখানে QRPayBD কীভাবে পেমেন্ট নিশ্চিত করে এবং আপনার সার্ভারে কী করতে হবে, সংক্ষেপে দেখানো হলো।

ধাপ ১: অর্ডার তৈরি করুন

আপনার সার্ভার থেকে POST /orders পাঠান। amount হলো টাকার অঙ্ক, আর storeOrderId হলো আপনার নিজের অনন্য অর্ডার নম্বর। ঐচ্ছিকভাবে returnUrl দিতে পারেন, যাতে পেমেন্টের পর গ্রাহক দোকানে ফিরতে পারেন। অথেনটিকেশন ও রিকোয়েস্টের বাকি খুঁটিনাটি গাইডে আছে। এখানে আমরা শুধু মূল প্রবাহটা দেখাচ্ছি।

curl -X POST https://qrpaybd.com/orders \
  -H 'Authorization: Bearer YOUR_STORE_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"amount": 1250.50, "storeOrderId": "ORDER-1001"}'
curl

রেসপন্সে paymentUrl পাবেন। API key শুধু আপনার সার্ভারে রাখুন, ব্রাউজারে বা মোবাইল অ্যাপে কখনো নয়।

ধাপ ২: গ্রাহককে paymentUrl-এ পাঠান

গ্রাহকের ব্রাউজারকে paymentUrl-এ রিডাইরেক্ট করুন। পেজে আপনার ওয়ালেট নম্বর, ঠিক কত টাকা দিতে হবে, অর্ডারের রেফারেন্স (QP-XXXX) আর TrxID লেখার ঘর থাকে। গ্রাহক নিজের ওয়ালেট অ্যাপে সেন্ড মানি করেন। অ্যাপে রেফারেন্স ঘর থাকলে সেখানে QP-XXXX লেখেন, নইলে পেজে TrxID লেখেন। আপনার দোকানের ফোনের Collector অ্যাপ পেমেন্টের এসএমএস পাঠালে QRPayBD মিলিয়ে দেখে।

গ্রাহক আপনার সাইটে ফিরে এসেছেন বলেই অর্ডার পেইড ধরবেন না। শুধু সাইন করা webhook, অথবা আপনার সার্ভার থেকে করা স্ট্যাটাস যাচাই পেমেন্ট নিশ্চিত করে।

ধাপ ৩: webhook-এর হেডার ও পেলোড

অর্ডার পেইড হলে QRPayBD আপনার webhook ঠিকানায় JSON বডিসহ POST পাঠায়। হেডারগুলো হলো:

বডিতে এই ঘরগুলো থাকে:

HMAC সিগনেচার কীভাবে যাচাই করবেন

সবচেয়ে বড় ভুল হলো JSON পার্স করে আবার স্ট্রিং বানিয়ে HMAC বের করা। তাতে বাইট বদলে যেতে পারে। সিগনেচার হয় যে বাইটগুলো আপনি পেয়েছেন ঠিক সেগুলোর ওপর, তাই raw বডি দিয়ে হিসাব করুন। তারপর constant-time তুলনা ব্যবহার করুন, সাধারণ == নয়। নিচে Node.js ও Express-এর একটা সাধারণ নমুনা। এটা শুধু ধারণা বোঝানোর জন্য, নিজের প্রজেক্টে ঢোকানোর আগে পরীক্ষা করে নিন।

const crypto = require('node:crypto');
const express = require('express');

const app = express();

// raw বডি লাগবে: সিগনেচার হুবহু পাঠানো বাইটের ওপর
app.post('/webhooks/qrpaybd', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.QRPAYBD_WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
  const received = String(req.get('X-QRPayBD-Signature') || '');

  const a = Buffer.from(received);
  const b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.status(401).end();
  }

  const event = JSON.parse(req.body.toString('utf8'));
  // দ্রুত 200 দিন, ধীর কাজ পরে করুন
  res.status(200).end();
  handlePaid(event).catch(console.error);
});
Node.js (Express): raw বডিতে HMAC যাচাই

timingSafeEqual দুই বাফারের দৈর্ঘ্য সমান না হলে এরর দেয়, তাই আগে দৈর্ঘ্য মিলিয়ে নেওয়া হয়েছে। handlePaid আপনার নিজের ফাংশন। সেখানে কী করবেন, তা পরের অংশে।

হ্যান্ডলারে কী কী করবেন

webhook হারালে কী হবে? রিকনসাইল করুন

ব্যর্থ webhook ডেলিভারি QRPayBD এখনো আবার চেষ্টা করে না। আপনার সার্ভার তখন বন্ধ বা ধীর থাকলে নোটিফিকেশন হারিয়ে যেতে পারে। তাই কয়েক মিনিট পরপর একটা জব চালিয়ে আপনার পেন্ডিং অর্ডারগুলোর জন্য GET /orders/:id ডাকুন। status paid হলে সেটাকে webhook-এর মতোই সামলান। webhook ঠিকানা অবশ্যই পাবলিক https:// ঠিকানা হতে হবে।

মনে রাখার মতো সীমা

রিকোয়েস্ট ও রেসপন্সের পুরো বিবরণ, PHP উদাহরণ, ত্রুটির কোড আর লঞ্চের আগের চেকলিস্ট ইন্টিগ্রেশন গাইডে আছে।

ইন্টিগ্রেশন গাইড পড়ুন

ম্যানুয়াল বনাম অটো পেমেন্ট ভেরিফিকেশনের তুলনা