To test Paystack payments: use your test API keys (sk_test_ and pk_test_), initialize transactions against the standard API endpoints, and use Paystack test card numbers (4084 0840 8408 4081 for success, 4084 0840 8408 4085 for declined). For Flutterwave: use test keys (FLWSECK_TEST-), and use Flutterwave test card 4242 4242 4242 4242 for success. Both platforms simulate the full payment flow including webhooks. Bank transfer testing generates a virtual account in sandbox that you can simulate paying. Before going live, run at least 5 test scenarios: successful card, declined card, successful bank transfer, expired transfer, and webhook delivery confirmation.
Shipping a payment integration without proper testing is how developers accidentally charge customers wrong amounts, miss payment confirmations, or create duplicate orders. The sandbox exists so you can catch these bugs before real money is involved.
Both Paystack and Flutterwave provide test environments that behave almost identically to production. The key differences:
The sandbox uses the same API endpoints as production (api.paystack.co for Paystack, api.flutterwave.com for Flutterwave). The system distinguishes test from live based on your API key prefix, not the URL. This means your code does not need environment-specific URLs. You just swap the API keys.
A common mistake is testing only the "happy path" (successful card payment). Production users will trigger every edge case: wrong OTP, insufficient funds, expired transfer, abandoned checkout, duplicate clicks on the "pay" button. Test these in sandbox before they happen in production.
Getting your test keys: Log into the Paystack dashboard. Toggle to "Test Mode" using the switch in the top-left corner. Go to Settings, then API Keys & Webhooks. Copy your test public key (pk_test_...) and test secret key (sk_test_...). Use these in your application's environment variables.
Paystack test card numbers:
Testing bank transfers: When you initialize a transaction with the "bank_transfer" channel, the sandbox generates a virtual account number. In test mode, Paystack simulates the transfer confirmation automatically after a few seconds. You do not need to actually send money. Watch your webhook endpoint for the confirmation notification.
Testing USSD: USSD payments cannot be fully simulated in sandbox because they require dialing a USSD code on a real phone. Paystack's sandbox shows the USSD prompt but may not trigger a completion webhook automatically. For USSD testing, use the Paystack dashboard's manual simulation tools or wait until you do a small live test.
Webhook testing: Set your webhook URL in the test mode settings (Settings, then API Keys & Webhooks, then Webhook URL). Make sure this points to a publicly accessible endpoint. If your development server is running locally, use a tunneling tool like ngrok to expose it. Paystack sends test webhooks to this URL for every test transaction, just like it would in production.
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
Getting your test keys: Log into the Flutterwave dashboard. Switch to "Test Mode" using the toggle. Navigate to Settings, then API. Copy your test public key (FLWPUBK_TEST-...) and test secret key (FLWSECK_TEST-...). Also note the encryption key for inline checkout.
Flutterwave test card numbers:
Testing bank transfers: Flutterwave's sandbox generates a test bank transfer instruction (account number and bank name). The sandbox may auto-complete the transfer or provide a button on the checkout page to simulate payment. Check the Flutterwave developer docs for the current simulation behavior, as this varies by integration method.
Webhook setup: In the Flutterwave dashboard under Settings, then Webhooks, set your webhook URL and the "Secret Hash" (a shared secret used to verify webhook authenticity). Send test transactions and verify your endpoint receives the webhook payloads correctly.
Note on amount format: Remember that Flutterwave uses the main currency unit (naira), not the smallest unit (kobo). If you are testing both gateways, be careful not to apply Paystack's kobo conversion to Flutterwave requests or vice versa. This is the most common bug when developers support both platforms.
Do not go live until you have successfully tested all five of these scenarios.
Scenario 1: Successful card payment. Use the success test card. Verify: (a) the Paystack/Flutterwave checkout opens correctly, (b) the test card is accepted, (c) your callback URL receives the redirect with the transaction reference, (d) your server-side verification confirms the payment, (e) your webhook handler receives and processes the confirmation, (f) the order status in your database updates to "paid."
Scenario 2: Declined card payment. Use the decline test card. Verify: (a) the checkout shows a clear error message to the customer, (b) your system does not mark the order as paid, (c) the customer can retry payment without re-entering their order details, (d) no webhook is sent for a declined card (or if one is sent, your handler correctly identifies it as a failure).
Scenario 3: Successful bank transfer. Initialize a transaction with bank_transfer as a payment channel. Verify: (a) the virtual account details display correctly, (b) the sandbox simulates the transfer, (c) your webhook handler receives the bank transfer confirmation, (d) the order status updates to "paid." This is the test most developers skip, and it is where most production bugs hide.
Scenario 4: Expired bank transfer. Initialize a bank transfer but do not simulate payment. Wait for the transaction to expire (or check if the sandbox has a way to force expiration). Verify: (a) your system receives a failure/expiration webhook, (b) the order status updates to "expired" or "failed," (c) any reserved inventory is released.
Scenario 5: Duplicate webhook handling. Manually send the same webhook payload to your endpoint twice (using curl or Postman). Verify: (a) your server processes the first webhook correctly, (b) the second identical webhook is recognized as a duplicate and does not trigger duplicate order fulfillment, (c) no duplicate entries are created in your database.
Once all test scenarios pass, work through this checklist before accepting real money.
Proper payment testing is part of a broader set of engineering skills: understanding API integration patterns, writing tests, handling edge cases, and deploying applications with the correct configuration. These skills are best learned in context, not in isolation.
McTaba Academy covers payment integration and testing as part of its full-stack curriculum. Full-Stack Software & AI Engineering (NGN 140,000 to 220,000; exchange rates fluctuate, check current price at checkout) includes hands-on exercises for building and testing Paystack and Flutterwave integrations. Deployment: Going Live (NGN 6,000 to 10,000; exchange rates fluctuate, check current price at checkout) covers the production deployment and environment configuration that payment integrations require. Or start with Tech Foundations (NGN 3,500 to 6,000; exchange rates fluctuate, check current price at checkout) if you are still building your programming fundamentals. Create a free account to see all options.
The official sandbox documentation for Paystack and Flutterwave is also essential reading. Both include up-to-date test card numbers, simulation instructions, and sandbox behavior details.
Create a free McTaba Academy account. Access starter lessons, join the community, and explore at your own pace.
Create Free Account