Simulating Declined Cards on Paystack
To simulate a card decline in Paystack test mode: use card 4084080000000409 to trigger "Do Not Honor", or 4084080000000005 to trigger "Insufficient Funds". These cards will fire a charge.failed webhook event. Verify that your webhook handler does not fulfill the order, your frontend shows a useful error message, and your retry flow works.
Test Cards That Trigger Specific Decline Reasons
| Card Number | Decline Reason | gateway_response |
|---|---|---|
4084080000000409 |
Declined by issuer | Do Not Honor |
4084080000000005 |
Insufficient funds | Insufficient Funds |
4084080000000007 |
Card expired (simulate) | Expired Card |
4084080000000009 |
Incorrect PIN | Incorrect PIN |
All test decline cards use CVV 408 and any future expiry date.
Handling the Decline in Your Webhook Handler
// Webhook handler — handle both success and failure events
if (event.event === 'charge.success') {
await fulfillOrder(event.data.metadata.order_id);
}
if (event.event === 'charge.failed') {
var orderId = event.data.metadata?.order_id;
var reason = event.data.gateway_response; // "Do Not Honor", "Insufficient Funds", etc.
await db.orders.update({
id: orderId,
status: 'payment_failed',
failure_reason: reason,
});
// Notify the customer
await sendEmail(event.data.customer.email, {
subject: 'Payment failed',
body: 'Your payment of NGN ' + (event.data.amount / 100) + ' could not be processed. Reason: ' + reason + '. Please try a different card.',
});
}
Test this by sending the decline test card through your actual checkout flow in test mode, then verifying the webhook fires and your order status updates to payment_failed.
Learn More
This guide is part of the Paystack testing guide.
Key Takeaways
- ✓Card 4084080000000409 triggers "Do Not Honor" — the most common real-world decline reason.
- ✓Card 4084080000000005 triggers "Insufficient Funds" — test that your UI suggests the customer checks their balance.
- ✓A declined card fires a charge.failed webhook event, not charge.success — your handler must handle both.
- ✓Never fulfill an order based on the checkout callback alone — always verify via webhook or the verify endpoint.
- ✓Test your retry flow: can a customer enter a different card after a decline without losing their cart?
- ✓Log the gateway_response field from decline events — it tells you exactly why the card was declined.
Frequently Asked Questions
- Does Paystack send a webhook for declined cards?
- Yes. Paystack fires a charge.failed webhook event when a card is declined. Your webhook endpoint receives this event with the same structure as charge.success, but with status: "failed" and a gateway_response explaining the decline reason.
- How do I test that my frontend shows the right error message for each decline type?
- Use the Paystack Inline popup in test mode with each decline test card. The Paystack popup will display a decline message. Additionally, check that your backend stores the gateway_response and any customer-facing messaging maps it to a helpful instruction (e.g., "Insufficient Funds" → "Please check your account balance or try a different card").
- What is the difference between a declined card and a failed charge?
- A declined card is when the issuing bank rejects the charge (gateway_response like "Do Not Honor" or "Insufficient Funds"). A failed charge can also result from network issues, expired cards, or Paystack's own risk checks. Both result in a charge.failed webhook event, but the gateway_response field tells you the specific reason.
- Should I show the raw gateway_response to customers?
- No — raw gateway responses like "Do Not Honor" are technical and unhelpful to customers. Map them to friendly messages: "Do Not Honor" → "Your bank declined this payment. Please try a different card or contact your bank." Keep the raw response in your logs for debugging but show a friendly message to the user.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon