Payment integration is where most Nigerian apps quietly fail. Orders marked unpaid when the customer actually paid. Double charges on retry. Money collected but no record of it. Refunds that don't match. A checkout button is easy. A payment system you can trust with real revenue is not.
A payment flow has more moving parts than it looks. When one of them is missing or wrong, the app appears to work — until real money is involved. These are the failures I see most often.
The app marks an order as paid when the browser redirects back from checkout — without verifying the transaction server-side. Anyone can fake the redirect. And real payments fail to register when the tab closes.
Some payments complete after the customer leaves the tab — bank transfers, delayed card settlements, successful retries. Without webhooks, those payments never get recorded. Money comes in; the app thinks it didn't.
If the frontend callback and the webhook both fire — or a network retry hits twice — the app processes the same payment twice. Customers get charged twice. Refund requests start arriving.
Secret keys sometimes end up in browser code where anyone can read them. This lets attackers initiate fake transactions or read transaction data. A serious security hole — and one that gets apps shut down by providers.
Payments live only on the provider's dashboard — not in your own database. When you need to reconcile, refund, or report, you're scrolling through a dashboard instead of querying data.
Refunds happen manually — a WhatsApp message to the provider, a spreadsheet entry, a hope that it works. Disputes get lost in inboxes. Nothing is trackable.
Four stages. Every one of them is required. Most broken payment systems are missing at least two.
This is the sequence I build for every payment integration. Nothing is skipped.
In Nigeria, mobile networks drop constantly. Customers close tabs. USSD sessions time out. Bank transfers arrive hours later. If your app trusts only the frontend redirect, you will lose payments every single day — payments where the customer paid and your app never knew. The webhook is what makes a payment system reliable.
A checkout page is 20% of payment integration. The other 80% is what happens behind it — and that's where real reliability is built.
Frontend flow that only ever exposes the public key. All sensitive logic lives server-side. Card data is never stored by your app — the provider handles it.
Every transaction verified against the provider's API before your app treats it as paid. No trusting the browser. No fake redirect tricks.
A dedicated webhook endpoint that receives events, verifies signatures, and processes them idempotently. Includes retry handling for transient failures.
A proper database structure for payments — reference, amount, status, customer, timestamp, provider, metadata. Queryable, reportable, auditable.
A refund flow you can trigger from your own admin panel. Disputes tracked with statuses, notes and outcomes — not lost in an email inbox.
Recurring billing with plan management, renewals, proration, failed payment retries, and cancellation. The full lifecycle, not just the first charge.
Different providers suit different businesses. Here's the honest breakdown.
Best developer documentation in Nigeria. Strong webhook reliability. Cards, transfers, USSD, subscriptions. Ideal first choice for most Nigerian apps.
Wider African coverage and multi-currency support. Good for businesses operating across borders or accepting international customers.
Best for international customers paying in USD/GBP/EUR. Not available for Nigerian-registered businesses to charge Nigerian customers directly, but useful for global SaaS.
Strong for enterprise, government and larger organisations with specific invoicing or settlement needs. More setup overhead, but robust.
Not sure which to use? I'll recommend based on what your business actually needs — customer location, ticket size, whether you need subscriptions, settlement timing, and what your existing stack already supports.
Structured, tested and audited. Payment code has zero tolerance for "it works most of the time."
You share access to the codebase. I review the current state — what payment flow exists, whether verification is server-side, whether webhooks are handled, whether secrets are exposed, and what the database currently records. You receive a written assessment of what's safe and what needs rebuilding.
If a provider isn't already set up, I help you choose the right one and get the account configured — API keys, webhook URLs, test mode access. You keep ownership of the account; I never hold your credentials.
Server-side endpoints for initiating transactions, verifying payments, handling webhooks and logging everything. Written in Node.js and integrated with your existing database structure.
The checkout flow is connected to your backend. Public key only on the frontend. Clear success, pending, failed and cancelled states handled properly — no vague "something went wrong" screens.
Test mode first, then live small-amount transactions. Includes: successful payment, failed payment, abandoned payment, network drop mid-flow, webhook retry, refund, and double-charge prevention.
You receive the code, the flow documented, the webhook URL registered, and clear notes on how to trigger refunds and check transaction records. Everything stays in your control.
Payment integration is not the place for experimentation. You're trusting someone with the code that handles your revenue.
React.js, Node.js, PostgreSQL, REST APIs. I build the frontend, backend and database together — so payment code isn't handed between three different developers.
Since 2015. Running a real Nigerian business means I understand what payments mean to you — not just as code, but as revenue, trust and reputation.
Real products in production with real users. Payment integrations tested against real Nigerian payment conditions — mobile networks, USSD timeouts, delayed transfers.
Many of my payment integration engagements are rescuing AI-built apps. I know exactly what vibe-coded payment flows look like — and what they're missing.
"We had customers paying and the app marking them unpaid. Emmanuel rewrote the flow and we haven't lost a payment since."
"He found our secret key exposed in the frontend. That alone was worth the fee. Then he rebuilt the whole flow properly."
"Refunds used to be a WhatsApp message. Now they're a button. Everything is reconciled properly."
Proper integration has four parts: (1) a checkout flow on the frontend that starts a transaction, (2) a backend endpoint that verifies the transaction against the provider's API before marking an order as paid, (3) a webhook handler that listens for the provider's server-to-server events so payments that complete after the customer leaves the tab still get recorded, and (4) a transaction record in your database that logs every payment attempt with its status, reference and amount. Missing any one of these causes payment problems — most commonly, orders marked as unpaid when the customer actually paid.
The most common causes are: not verifying transactions server-side (relying only on the frontend callback), missing webhook handling, no idempotency on retry attempts, and race conditions when the frontend callback and the webhook both fire. Proper integration verifies every transaction against the provider's API, uses the transaction reference as a unique key, and treats the webhook as the authoritative source of truth — not the browser callback.
A webhook is a server-to-server notification sent by the payment provider when something happens — a payment succeeds, fails, is refunded, or is disputed. Unlike the frontend callback (which fails if the customer closes the tab or loses network), the webhook always arrives and can be retried. Payments without proper webhook handling lose orders every day — especially in Nigeria where mobile network drops are common mid-transaction.
Yes. Paystack and Flutterwave both support recurring billing, and I build the full subscription lifecycle — plan creation, customer subscription, proration, renewals, failed payment retries, cancellation and dunning. I also build the database structure so your app knows who is on which plan, when it renews, and what happens when it fails.
It depends on scope. A single-provider integration for a simple checkout is at the lower end. Multi-provider integration, subscriptions, refunds, dispute handling, admin dashboards and reconciliation reports cost more. I quote per project after reviewing your app, and the quote is broken into clear milestones. Every quote includes proper webhook handling and server-side verification — I don't cut those for price.
Yes — frequently. AI tools are good at generating checkout UIs but poor at backend payment logic. Most of my payment integration work is retrofitting AI-generated apps with proper server-side verification, webhook handling, idempotency and transaction logging. The checkout screen stays; the fragile backend gets replaced.
Tell me what payment problems you're seeing — lost payments, double charges, no records, exposed keys, or a checkout flow you don't trust. I'll tell you honestly what needs fixing and what it costs.
Paystack · Flutterwave · Stripe · Nigeria-based, worldwide service