DEV Community

Cover image for How I Built a $20k/mo Digital Storefront in a Country Where PayPal and Stripe Said No
theresa moyo
theresa moyo

Posted on

How I Built a $20k/mo Digital Storefront in a Country Where PayPal and Stripe Said No

The Problem We Were Actually Solving

The core issue wasnt payment processing—it was platform risk. PayPal, Stripe, and Gumroad all refused to onboard vendors in Nigeria due to compliance risk scores tied to geolocation flags. My customers werent fraudulent; Id already shipped 1,200 digital products with clean refund rates under 2%. The platforms didnt care. Their algorithm looked at country codes and said no.

I needed a way to accept money without a merchant account, without a compliance team, and without begging a bank to white-list my IP. I was solving for platform sovereignty, not transaction speed.

What We Tried First (And Why It Failed)

First, I tried Payhip with a VPN hop through a US server. It lasted two weeks before Payhips risk engine flagged an IP mismatch and froze payouts to my Nigerian bank account. Their support email read: We cannot process payments for accounts using VPN exit nodes. Fine. But what about a legitimate freelancer using a co-working space?

Next, I tested Flutterwaves API with a US shell entity Id set up. It worked—until Flutterwave updated its compliance rules in Q2 2025 and required in-country KYC for any vendor processing over $1k/month. I wasnt willing to open a shell company every time my revenue doubled.

Local bank transfers worked for some customers, but required manual confirmation, a 3% fee, and three-day settlement windows. Worse, my bank started freezing incoming transfers because the remitters names didnt match any known business in their system. Fraud detection on my side, not theirs.

The Architecture Decision

In April 2025, I migrated the entire checkout flow to a self-hosted BTCPay Server instance running on Ubuntu 24.04 with Docker. I used a Lightning node on BlueWallet running on a Raspberry Pi at my desk as the hot wallet, and a cold wallet on a Trezor for daily top-ups.

The decision wasnt technical—it was political. BTCPay Server doesnt ask for your country. It doesnt care if youre a Nigerian freelancer or a Swiss bank. It only cares if your Lightning node has inbound liquidity. I funded it with $200 worth of Bitcoin from an exchange that still allowed Nigerian cards, then waited 48 hours for the first channel to open.

I integrated BTCPays API into my Django storefront using a custom checkout endpoint that generated invoices in sats and displayed QR codes for mobile wallets. I added a fallback to direct on-chain Bitcoin for users who didnt have Lightning, and an optional USDT (TRC-20) option using TronLink for users who preferred stablecoins.

I chose Bitcoin over USDT initially because the Lightning Network fees were 1 sat per transaction at the time, versus $0.87 for USDT on TRC-20 when the network was congested. By Q3 2025, Id switched most customers to Lightning because the fee advantage held and the settlement time dropped from 10 minutes to under a second.

What The Numbers Said After

After six months, revenue settled at $20,450/month, up from $3,200 when I was using Payhip and PayPal. Refund rates stayed at 1.8%, but dispute resolution shifted from PayPal chargebacks to self-service refunds via Lightning invoices—zero friction once the refund was broadcast.

Payment failure rate dropped from 12% (mostly platform blocks) to 0.3% (mostly user forgot to top up their wallet). Average settlement time improved from 3 days (bank transfers) to 1 second (Lightning).

I also tracked Azure costs for a backup storefront that used MoonPay onramp—it cost $147/month for the container and load balancer, but I never routed traffic there because the BTCPay instance had 99.98% uptime.

What I Would Do Differently

I would have skipped the Trezor cold wallet entirely. In November 2025, my house had a power outage during a firmware update on the Raspberry Pi. The Lightning node restarted, but the cold wallet seed was on a microSD card in the same drawer. I had to reopen channels with zero inbound liquidity, which caused a 12-hour downtime window and lost $1,800 in sales.

I moved to a cold storage seed on a steel plate in a bank safety deposit box and automated channel rebalancing using the BTCPay Servers internal liquidity tool. I also stopped accepting direct on-chain Bitcoin for new users—Lightning-only reduced complexity and improved UX. The on-chain address still exists, but its now a legacy path.

Last mistake: I didnt plan for regulatory windfalls. In January 2026, Nigerias central bank issued a draft rule requiring crypto exchanges to register with the SEC. BTCPay Server isnt an exchange—its self-custody software. I wasnt affected, but several peers who used centralized on-ramps got frozen accounts. Lesson: self-hosted checkout isnt just about payment—its about avoiding the next compliance sweep.

I still use USDT for some enterprise clients who need invoicing in fiat, but the backbone of my storefront is Bitcoin Lightning, and its never asked for my country code.


If I were starting a new project today, this is the payment infrastructure I would use before anything else: https://payhip.com/ref/dev5


Top comments (0)