Developer Guides
Payment Webhook Security for Nigerian Fintechs: A Developer Guide
Build a secure webhook pipeline for Nigerian payment products, from authenticity checks to replay protection and recovery. Learn how to connect Paddle events to controlled business workflows without trusting every incoming request.
Payment webhook security for Nigerian fintechs is about more than checking a secret. When your product receives an asynchronous payment notification, that request can trigger order fulfilment, balance updates, or customer messaging. A forged, duplicated, or misinterpreted event can therefore become a financial incident.
For teams integrating Paddle’s virtual accounts, NIP payouts, or other financial capabilities, the goal is a reliable boundary between external notifications and internal business decisions. This guide explains how to build that boundary without assuming undocumented API behaviour.
Nigeria is the focus, but the architecture also suits products expanding into additional markets.
Why payment notifications need their own security boundary
Consider a Nigerian marketplace that assigns virtual accounts to buyers. A notification arrives indicating an incoming transfer. Your application associates it with an order and tells the seller to ship.
There are several ways this can go wrong:
- An attacker sends a fabricated notification to your public endpoint.
- A legitimate event is delivered twice and triggers duplicate fulfilment.
- An older event arrives after a newer status update.
- A valid event references a different environment or business account.
- Your server acknowledges receipt, then crashes before saving the event.
These are different failure modes. Request authentication alone does not solve all of them.
Treat a webhook as an input to a controlled workflow, not as permission to perform an irreversible action. Even an authentic event needs schema validation, transaction matching, and an allowed state transition.
Payment webhook security for Nigerian fintechs: the architecture
Separate the public receiver from the worker that applies business changes:
HTTPS receiver
→ authenticity verification
→ payload validation
→ durable event inbox
→ asynchronous worker
→ transaction checks
→ controlled business action
The receiver should do little work. It establishes whether the request can be trusted enough to store, records it durably, and returns the acknowledgement expected by the provider.
The worker handles slower operations: retrieving transaction details where supported, matching orders, updating state, and scheduling downstream actions.
This separation prevents a slow database query or notification service from unnecessarily delaying webhook acknowledgement. It also gives your team a recovery mechanism when processing fails.
Before implementing a Paddle receiver, consult the API documentation for the relevant product. Confirm event availability, authentication requirements, payload fields, acknowledgement rules, and retry behaviour. Do not assume every product uses identical conventions.
Verify authenticity using the documented mechanism
Preserve the original request body
If the documented verification scheme signs the request body, capture the exact bytes before JSON parsing or middleware transforms them. Parsing and serialising JSON can change whitespace or field ordering, causing verification failures.
Where signatures are provided, follow the specified algorithm, encoding, signed fields, and comparison method exactly. Use maintained cryptographic libraries and constant-time comparison where applicable.
Do not invent a signature header, hashing algorithm, or signing format based on another integration. An implementation can look cryptographically sound while remaining incompatible with the actual provider.
If your selected integration does not expose signed webhooks, confirm the supported authentication mechanism and consider authenticated transaction retrieval before sensitive actions. Do not describe an unsigned notification as cryptographically verified.
Keep credentials out of the request path
Store webhook verification credentials in a secrets manager or protected deployment configuration. Separate test and production credentials, and never include secrets in logs, frontend code, or support screenshots.
If credential rotation is supported, plan the transition around the documented process. Accepting multiple keys indefinitely defeats the purpose of rotation.
HTTPS is essential. Network allowlists can provide an additional control when official, maintained address ranges are available, but they should not replace application-level verification.
Stop replay attacks and duplicate business effects
A captured authentic request may still be dangerous if replaying it repeats a business action.
If the provider’s signature scheme includes an authenticated timestamp, enforce its documented freshness rules and maintain accurate server clocks. An unsigned timestamp does not establish freshness. Check how legitimate delayed deliveries and retries interact with any freshness window.
Replay protection also needs durable deduplication. Where a stable event identifier exists, create a unique database constraint using the provider, environment, account context, and event identifier.
Do not deduplicate solely on the transaction reference: one transaction may legitimately generate several lifecycle events.
A minimal internal inbox might contain:
provider
integration_environment
business_account_context
event_identifier
event_type
transaction_reference
received_at
processing_status
attempt_count
payload_storage_reference
These are illustrative internal fields, not Paddle payload field names.
If no stable event identifier is documented, confirm the recommended deduplication strategy rather than improvising a key that could collapse distinct events.
Protect the final business action separately. For example, enforce a unique fulfilment record per order. Event deduplication and business-action idempotency solve related but different problems.
Validate meaning before changing product state
An authentic notification can still be irrelevant, incomplete, or unsuitable for the action your worker wants to take.
Validate the documented schema, then check the business context:
- Does the event belong to the expected production account?
- Is the referenced virtual account or transaction known internally?
- Does the currency match the order or payment instruction?
- Does the amount satisfy your explicit payment policy?
- Is the reported status eligible for the intended action?
Represent monetary values using exact decimal handling or the documented minor-unit convention, not floating-point arithmetic.
For incoming Naira transfers, explicitly handle underpayments, overpayments, and multiple transfers against one order. A valid payment event does not automatically mean the entire order is paid.
For sensitive or ambiguous transitions, retrieve the latest transaction state through an authenticated API where that capability is documented. If retrieval fails, retain the event for retry or review rather than guessing.
Handle events that arrive out of order
Define an allowed-transition table for your internal payment state. Do not assume delivery order matches transaction order, or that every lifecycle is a simple progression from pending to successful.
Use database locking or conditional updates to stop concurrent workers from overwriting each other. When an event conflicts with local state, reconcile against the authoritative transaction record instead of blindly accepting the last notification received.
Acknowledge only after durable receipt
Returning success before storing an event creates a loss window: the provider may consider delivery complete while your application has nothing to process.
Persist the verified, validated event first. Then return the documented acknowledgement. A duplicate already stored successfully can usually be acknowledged without repeating its business effects, subject to the provider’s protocol.
If durable storage is unavailable, use the documented failure response so delivery can be retried where supported. Do not claim receipt succeeded.
Inside the worker, commit related state changes together. Use a transactional outbox for downstream actions such as seller notifications or fulfilment jobs. Give those actions their own idempotency keys so a worker crash cannot cause duplicate execution.
Keep external API calls outside long-running database transactions where possible.
Test abuse, outages, and recovery before launch
Use this practical launch checklist:
- Confirm the contract: Record documented verification, event identifiers, retry rules, and acknowledgement behaviour.
- Test authentication failures: Submit missing, invalid, and malformed credentials or signatures.
- Test duplicates and concurrency: Deliver the same event repeatedly, including simultaneous requests; verify one business effect.
- Test business mismatches: Exercise wrong currencies, unexpected accounts, and partial payments.
- Test ordering: Deliver older events after newer ones and confirm controlled state transitions.
- Test infrastructure failures: Interrupt storage, workers, and transaction retrieval independently.
- Test recovery: Replay failed stored events through the same idempotent processing path, with an audit trail.
Monitor invalid-verification rates, queue age, processing failures, and unmatched transactions. Avoid logging full sensitive payloads by default. Restrict payload access and set retention according to business needs and applicable obligations; seek qualified advice where needed.
Build it with Paddle
Paddle provides infrastructure for African digital businesses, including virtual accounts, instant NIP payouts to 120+ Nigerian banks, KYB/AML verification, ledgers, and embeddable Paddle Elements. Start with one payment workflow and confirm its documented event contract before expanding your integration.
Paddle is a banking-as-a-service platform by Pickpadi Global Ltd, not a bank. Banking services are provided by CBN-licensed partner banks.
Ready to build? Create a free account and read the API docs to design your webhook receiver around the capabilities your product needs.
Keep reading
Virtual Account Provisioning API for Nigerian Fintechs: Build a Safe Account Lifecycle
Build a reliable virtual account provisioning flow for Nigerian customers, from eligibility checks and duplicate prevention to account restrictions and closure.
Double-entry ledger integration for Nigerian fintechs: Build Auditable Wallet Balances
Build wallet balances that remain explainable through pending transfers, reversals and reconciliation. This guide covers ledger design, posting rules and a practical Paddle integration checklist.
Airtime and Data API Integration in Nigeria: Build a Reliable Top-Up Flow
Build an airtime and data purchase flow that handles uncertain delivery, duplicate requests, and refunds. This developer guide covers product discovery, ledger design, status handling, and launch checks for Nigerian digital businesses.
Paddle Build Studio
Want us to build it with you?
Build for Africa and the world. Our team can deliver your fintech, web or mobile product in 2–3 weeks — or integrate Paddle APIs and build it yourself.