In the tech startup ecosystem, integrating payments usually means creating a Stripe account, copying an API secret key, pasting a pre-built React checkout component, and watching credit card payments stream in. It takes an afternoon.
In Bangladesh's institutional madrasa sector, credit cards do not exist. Over 95% of parents settle their transactions through Mobile Financial Services (MFS)—predominantly bKash (with over 67 million users) and Nagad (with over 90 million accounts). If your platform cannot handle MFS reliably, your fee collection module is dead.
Integrating bKash and Nagad into Al-Maktab was one of the most demanding engineering tasks of the entire project. Here is the unvarnished story of what it takes to build a bulletproof domestic payment pipeline in Bangladesh.
The Real-World Network Conditions
The core challenge with domestic payment integration is not the initial API handshake; it is the brutal unreliability of mobile data connections during the transaction window. A mother sitting in a semi-rural union parishad initiates a bKash payment. Her phone opens the bKash webview, she enters her PIN, presses confirm—and right at that exact microsecond, her phone transitions from a 4G tower to an edge 3G cell. The connection drops.
Did the payment succeed? Did bKash deduct the ৳৩,৫০০ from her wallet? Did our Laravel backend receive the callback webhook? Did the invoice get marked as paid?
If your system handles this naively, one of two catastrophes occurs: either the madrasa credits the fee without receiving money, or worse, the mother loses ৳৩,৫০০ from her wallet while the madrasa database still flags her child as overdue. In an institutional community, a single dispute like that destroys parental trust for months.
Architecting the bKash Checkout Pipeline
bKash uses a tokenized checkout flow involving three primary endpoints: Create Payment, Execute Payment, and Query Payment. We structured our implementation around strict database idempotency:
// Transaction Flow State Machine
[User Taps Pay]
└──> Generate Unique Idempotency Key (INV-2026-0892-ATTEMPT-1)
└──> Create Local Payment Record with status: 'INITIATED'
└──> Call bKash Create Payment API -> Obtain paymentID
└──> Redirect Guardian to bKash Gateway
[User Confirms PIN on bKash]
└──> bKash redirects to Callback URL with paymentID & status
├──> IF status === 'success':
│ └──> Atomically acquire DB Lock for invoice
│ └──> Call bKash Execute Payment API
│ └──> Verify execute response trxID & amount match DB record
│ └──> Transition status to 'COMPLETED'
│ └──> Trigger Post-Payment Pipeline (Receipt, SMS, Ledger)
└──> IF network drops / timeout:
└──> Enqueue Background Job: VerifyPaymentStatusJob (Query API)
└──> Retries with exponential backoff before marking 'FAILED'By enforcing a strict database lock during callback execution, we completely eliminated race conditions where an impatient guardian double-taps the confirmation button and triggers duplicate deductions.
The Nagad Encryption Scheme: A Unique Beast
If bKash follows a conventional REST token pattern, Nagad marches to a very different beat. The Nagad merchant gateway uses public-private RSA keypair encryption combined with AES-128-CBC for payload exchange. Every single outbound request from our Laravel server must be cryptographically signed with our private key, and incoming payloads must be decrypted using Nagad's public certificate.
Getting this running cleanly in PHP 8.4 required writing custom OpenSSL wrapper classes. Furthermore, Nagad's staging sandbox has an undocumented session lifecycle quirk where authentication tokens occasionally invalidate on the first call of a new session. We engineered an automatic retry interceptor that catches the signature validation mismatch, invalidates the local Redis token cache, re-authenticates, and replays the original request seamlessly.
The Three Inviolable Steps After Every Payment
When a payment completes successfully—whether through bKash, Nagad, or manual cash entry at the office counter—Al-Maktab executes three automated procedures within 800 milliseconds:
1. Automated PDF Receipt Generation
Using a lightweight DomPDF pipeline, the system generates an official, print-ready voucher in Bengali. The receipt contains the madrasa's official seal, the student's roll and registration number, an itemized breakdown (Tuition, Hostel, Food, Exam fee), the MFS transaction ID (TrxID), and a tamper-proof QR code linking to an online verification URL.
2. Instant Bengali SMS Confirmation
An instant SMS is dispatched to the guardian's mobile number: আলহামদুলিল্লাহ! আপনার সন্তান আব্দুল্লাহর ফেব্রুয়ারি মাসের বেতন ৳৩,৫০০ সফলভাবে জমা হয়েছে। রশিদ নম্বর: INV-0892। ধন্যবাদ। A mother hearing her phone beep with an official confirmation three seconds after entering her PIN feels total peace of mind.
3. Double-Entry General Ledger Posting
Al-Maktab does not treat fees as simple balance increments. Every transaction posts a strict GAAP-compliant double-entry journal voucher into the accounting engine:
- Debit: Asset: bKash Merchant Account (৳৩,৫০০)
- Credit: Revenue: Student Tuition Fees (৳৩,৫০০)
When the madrasa's managing committee requests an audit at the end of the year, the accountant does not spend days adding up ledger columns. He clicks one button and exports a fully reconciled Trial Balance, Profit & Loss, and Balance Sheet.
