Integrating Paystack and Flutterwave: Beyond the Basic Checkout
The hosted checkout page is one feature of a payment gateway, not the product. The real operational value is in the reconciliation automation, retry logic, sub-account routing, and failure handling that most implementations never reach.
Integrating Paystack and Flutterwave: Beyond the Basic Checkout
The Paystack and Flutterwave documentation quickstart guides go from zero to a working payment page in twenty minutes. This is useful for getting started. It is not sufficient for a business running real payment volume.
The difference between a quickstart integration and a production payment system is the operational layer between the payment gateway and your business: reconciliation, failure handling, retry logic, sub-account routing, and the audit trail that lets you investigate any payment event six months later.
What Both Gateways Actually Support
Paystack and Flutterwave have different feature emphasis but broadly equivalent production capabilities:
| Capability | Paystack | Flutterwave |
|---|---|---|
| Hosted checkout | ✓ | ✓ |
| Inline checkout (embedded) | ✓ | ✓ |
| Virtual accounts | ✓ | ✓ |
| Recurring/subscriptions | ✓ | ✓ |
| Split payments | ✓ | ✓ |
| Refunds API | ✓ | ✓ |
| Bulk disbursements | ✓ (Transfer API) | ✓ |
| Multi-currency | Limited | Stronger |
| Mobile money | Limited | Uganda/Ghana/Kenya focused |
| International cards | ✓ | ✓ |
Both support webhook delivery for all transaction events. Both provide dashboard reconciliation exports. Paystack's developer experience is generally considered stronger for Nigerian developers building .ng-focused products; Flutterwave has stronger multi-country coverage for pan-African applications.
The integration architecture principles below apply to both.
Webhook Architecture: The Foundation Everything Else Builds On
Payment gateway integrations that poll for payment status are unreliable; they miss events, create race conditions, and create unnecessary API load. Webhooks — where the gateway pushes event notifications to your endpoint in real time — are the correct pattern.
A production webhook implementation has five requirements:
1. Idempotency: Payment gateways guarantee at-least-once delivery, not exactly-once. If your endpoint returns a non-200 response, the gateway retries. Your handler must detect duplicate events and skip processing for events already processed.
// Event deduplication example
async function handlePaymentWebhook(event: PaystackEvent) {
const existing = await db.webhookEvents.findUnique({
where: { id: event.data.id }
})
if (existing) return // Already processed
await db.webhookEvents.create({ data: { id: event.data.id, ...event } })
await processPaymentEvent(event)
}
2. Signature verification: Paystack sends an x-paystack-signature header with an HMAC-SHA512 signature of the payload using your secret key. Verify this before processing. Flutterwave uses a verif-hash header. An endpoint that does not verify signatures can be triggered by anyone with the URL.
import crypto from 'crypto'
function verifyPaystackSignature(payload: string, signature: string, secret: string): boolean {
const hash = crypto.createHmac('sha512', secret).update(payload).digest('hex')
return hash === signature
}
3. Synchronous acknowledgement, asynchronous processing: Return HTTP 200 immediately upon receiving a valid, verified webhook. Then process the event asynchronously. If processing takes longer than five seconds, the gateway may consider the delivery failed and retry. Use a queue (Redis, Cloudflare Queues, or a database-backed job queue) to decouple receipt from processing.
4. Ordered processing per reference: Payment events for the same transaction reference must be processed in order. An event marking a payment as success received before or after a failed event for the same reference must be handled correctly. Store events with timestamps and process in chronological order when multiple events share a reference.
5. Dead letter handling: Events that fail processing after retries must be stored for investigation, not silently dropped. Implement a dead letter queue or table where failed events are retained with their error context. Review this queue daily.
Subscription Billing With Robust Retry Logic
Paystack and Flutterwave both support subscription billing — charging a card on a recurring schedule. The naive subscription implementation creates customers, creates a subscription plan, and expects payments to flow. The production implementation handles what happens when they do not.
Card expiry: Customer cards expire. A subscription that silently fails on an expired card is both lost revenue and a customer service incident waiting to happen. Your subscription system needs:
- Expiry monitoring: flag subscriptions whose cards expire within thirty days
- Pre-expiry communication: email the customer thirty, fourteen, and three days before expiry requesting card update
- Update flow: inline card update that does not require re-creating the subscription
Insufficient funds failures: The most common subscription failure in Nigerian operations is insufficient funds — the debit day falls before salary credit for many customers. Smart retry logic significantly recovers these failures.
A retry schedule: immediate retry at T+6 hours, then T+24 hours, then T+72 hours, then T+7 days. Notify the customer at each failure with a manual payment link as an alternative. Cancel the subscription after the last retry only; most recoverable failures resolve within seven days.
async function handleFailedSubscription(subscriptionId: string, attemptNumber: number) {
const retryDelays = [6, 24, 72, 168] // hours
if (attemptNumber < retryDelays.length) {
await scheduleRetry(subscriptionId, retryDelays[attemptNumber])
await notifyCustomerOfFailure(subscriptionId, attemptNumber)
} else {
await cancelSubscription(subscriptionId)
await notifyCustomerOfCancellation(subscriptionId)
}
}
Dunning management: The communication sequence around failed payments — how you notify, what you offer, when you restrict access, when you cancel — is called dunning. A well-designed dunning sequence recovers 30–50% of initially failed subscription renewals. Most businesses using out-of-the-box gateway subscriptions never customise this; it is a direct revenue impact.
Split Payments for Marketplace and Multi-Party Models
Both gateways support sub-accounts — receiving accounts that split transaction revenue between the platform and third parties in configurable ratios.
A property management platform collecting rent on behalf of landlords: the tenant pays ₦500,000; the platform retains a 5% management fee (₦25,000); the landlord receives ₦475,000. Without split payment infrastructure, this requires the platform to collect the full amount and manually transfer the landlord's share — a reconciliation and cash flow management burden. With sub-accounts, the split is atomic: both parties receive their portion in the same settlement cycle, and the platform's P&L records only the management fee.
Paystack sub-account setup:
// Create a sub-account for each third party
const subAccount = await paystack.subaccounts.create({
business_name: landlordName,
settlement_bank: landlordBankCode,
account_number: landlordAccountNumber,
percentage_charge: 5, // platform retains 5%
})
// Include sub-account in transaction initiation
const transaction = await paystack.transactions.initialize({
amount: rentAmount,
email: tenantEmail,
subaccount: subAccount.data.subaccount_code,
bearer: 'subaccount', // tenant bears transaction fees
})
Settlement timing: Sub-account holders receive their split according to the platform's settlement schedule. For platforms where sub-account holders (landlords, merchants, contractors) have cash flow expectations, ensure the settlement timing is explicit in the platform agreement and reflected in the communication templates.
Refund Automation
Manual refund processing — customer requests refund, support agent logs into gateway dashboard, initiates refund, sends confirmation — is an operational bottleneck that creates customer satisfaction delays and audit trail gaps.
An automated refund workflow:
- Customer requests refund through your application (specifying transaction reference and reason)
- Your system validates eligibility (within refund window, transaction was successful, not already refunded)
- Eligible refunds trigger Paystack/Flutterwave Refund API call automatically
- Webhook confirms refund processing; customer receives automated confirmation
- Refund reason logged to transaction record for dispute resolution
The gateway charges a ₦150 refund processing fee (Paystack). Build this into your refund policy disclosure and your margin calculations before offering "free returns."
Ineligible refunds (outside window, disputed, fraud-suspected) route to a human review queue with full transaction context preloaded. A support agent reviews and either approves (triggering the automation) or declines (triggering a templated response with the reason).
Bulk Disbursements
Paystack's Transfer API and Flutterwave's Transfer product enable bulk outbound payments — payroll, supplier payments, agent commissions, cashback distributions — through the gateway account. The operational advantages over manual bank transfers:
- Batch initiation: upload a CSV or POST an array; initiate hundreds of transfers in one API call
- Transfer status tracking: every transfer has a status (pending, success, failed, reversed) queryable through the API and delivered via webhook
- Single audit trail: all transfers logged in the gateway with timestamps, recipients, amounts, and bank references
- Failure handling: failed transfers (invalid account number, bank system downtime) are surfaced with specific failure reasons, enabling automatic retry or exception routing
The gateway fees for transfers (Paystack: ₦10 per transfer up to ₦5,000, then a tiered percentage) are lower than most commercial bank transfer fees at volume.
Reconciliation Architecture
Payment reconciliation is the process of confirming that payments received in the gateway match what should have been paid according to your application records. The naive approach is to manually compare a gateway dashboard export to your database at month end. The production approach is continuous automated reconciliation:
Daily settlement webhook → compare gateway settled amounts against expected amounts from your transaction records → flag discrepancies → log reconciliation run and outcome → alert on any unmatched transactions.
Unmatched transactions fall into three categories: payments received in the gateway with no matching record in your database (gateway webhooks that failed); records in your database showing paid status with no matching gateway settlement (a webhook processing bug); timing differences that will resolve in the next settlement cycle.
Reconciliation runs daily at the same time. Discrepancies that persist beyond the next cycle are escalated to manual review. This structure means your finance team reviews exceptions rather than manually reconciling every payment.
Choosing Between Paystack and Flutterwave
Use Paystack when: your primary market is Nigeria, your team has more experience with Paystack's documentation and support, or you need strong recurring billing with Nigerian card networks.
Use Flutterwave when: you need multi-country coverage (Ghana, Kenya, Uganda, South Africa alongside Nigeria), you need multi-currency settlement, or you need mobile money integrations in East or West Africa.
Use both when: you are building a marketplace or platform where some merchants prefer one gateway's onboarding experience, or when you need gateway redundancy for high-volume operations where gateway downtime would cause material revenue loss.
Whatever the choice, the operational architecture — webhooks, idempotency, retry logic, reconciliation — is the same. The gateway is the mechanism; the architecture is what determines whether your payment operations scale cleanly.
Related Articles
- Open Banking Nigeria: CBN Framework and Business Software — Building on the open banking framework
- API Architecture: End Integration Hell — Designing APIs that make integration painless
- Fraud Detection Architecture for Nigerian Financial Applications — Security patterns for financial operations