The Problem We Were Actually Solving
We built a tiered content app that sold monthly subscriptions for local creators. The plan was to ship on both Android and iOS, collect payments, and split revenue 70/30 like every other store promises. In our first beta, users in Lagos, Karachi, and Accra signed up without issues. Then the Dhaka users tried. Their credit cards failed on Google Play, and Apple said the same EMI we used in Nigeria was not on their approved list. I opened the Play Console and saw Bangladesh listed under Restricted Countries. The same restriction did not apply to Pakistan. The inconsistency was not technical—it was regulatory paperwork that lived in spreadsheets most engineers never touch.
I dug into the compliance documents and found the problem: Bangladesh Banks 2024 directive required all digital payment aggregators to hold a specific license called PA-DSS Tier 2. Our provider, Flutterwave, had Tier 1 for Nigeria and Kenya but did not list Tier 2 for Bangladesh. Every transaction from Dhaka was silently failing because the backend adapter sent the request to a Tier 1 endpoint. The error code in logs was 403-PG-REG, but the real cause was a missing compliance certificate that nobody had budgeted for.
What We Tried First (And Why It Failed)
Our first fix was to switch payment providers. I spun up a new Stripe account with an Indian entity, assuming Stripes local presence would cover Bangladesh. Two days later, Stripes compliance team replied that Bangladesh was also restricted unless we onboarded through their Singapore entity, which required a local GST registration we did not have. We tried Razorpays alternative flow for cross-border merchants; it accepted Bangladeshi cards but withheld payouts for 30 days and charged 2.9% + 22 INR per transaction. At that rate, our $5 subscription margin disappeared.
The finance team balked at the foreign exchange spread and asked if we could use a local bank directly. I assumed we could integrate bKash or Nagad APIs since both had published SDKs. When I opened the Nagad API documentation, I saw a requirement: every merchant must have a valid VAT certificate and a business account with a scheduled commercial bank. Our Dhaka agent did not have a VAT certificate because the agency operated as a sole proprietorship. The alternative was to register a subsidiary in Bangladesh, which would cost $5,000 in legal fees and six weeks of paperwork.
We tried one last shortcut: a hybrid checkout where users paid via mobile money outside the app and we sent them a one-time license key. On paper it worked. In practice, every key leak became a revenue leak, and support tickets exploded from users who could not distinguish between real keys and scam ones. The leakage rate hit 11% in the first week and forced us to disable the workaround.
The Architecture Decision
After the hybrid experiment collapsed, we chose a two-part solution. First, we onboarded with bKashs merchant services through a local partner bank in Dhaka. The partner provided a PA-DSS Tier 2 license and handled the Bangladesh Bank compliance filings. Second, we moved the payment orchestration layer to Adyen, which already maintained Tier 2 licenses in Bangladesh and could route transactions through bKashs API without exposing us to foreign exchange penalties. The switch added 1.5 milliseconds of latency per transaction but eliminated the 403-PG-REG errors.
Technically, we had to refactor our billing microservice. We replaced the single Stripe adapter with a pluggable provider interface that could select bKash, Nagad, or Adyen based on country code. The interface exposed a /v2/confirm endpoint that returned either a payment_intent_id or a redirect_url depending on the provider. For Bangladesh, the endpoint always returned redirect_url to bKashs checkout page. We also added a caching layer for payment confirmation status so if bKashs webhook was delayed, we would not retry the same transaction.
The biggest tradeoff was operational: we now depended on bKashs uptime and API versioning. bKash had scheduled maintenance windows every first Sunday of the month from 02:00 to 04:00 UTC. During those windows, our subscription churn spiked because users could not renew. We mitigated by sending an email 48 hours before the window with an offer to prepay for the next month at a 5% discount. The discount cost us margin but kept churn under 2%.
What The Numbers Said After
After the bKash integration went live, Dhaka revenue jumped from $0 to $87K in the first month and stabilized at $112K monthly. User conversion rose from 0% to 3.2% in Bangladesh, which matched our median global conversion. The latency increase from 1.5 ms to 3 ms did not affect conversion, but it did add 800 ms to the first-time payment flow. We observed that users who experienced the slower flow were 12% more likely to abandon during the redirect to bKashs page. To compensate, we introduced a loading skeleton that displayed a spinning bKash logo and the message Processing your local payment. The skeleton reduced abandonment by 7%.
On the compliance side, the bKash partner handled all Bangladesh Bank filings, and we passed the annual PCI-DSS audit without findings. The only recurring cost was the bKash transaction fee at 1.85% per sale, which ate into our margin. To offset, we introduced a surcharge toggle for users in Bangladesh that added 5% to the subscription price but was framed as a local regulatory fee. User complaints about the surcharge were 0.4% of total support tickets, so we kept it.
The Nagad integration remained blocked because their API still required a VAT certificate. We evaluated using MCA (Merchant Cash Advance) via bKash, but the revenue share was too high for our unit economics. So we left
Top comments (0)