A decline means the card issuer or processor refused the transaction. Common reasons:
| Reason | What happened | What to do |
|---|---|---|
| Insufficient funds | Customer's balance is too low | Ask the customer to use a different card |
| Invalid card number | PAN failed Luhn check or is not recognized | Prompt the customer to re-enter card details |
| Expired card | The card's expiry date has passed | Ask for an updated card |
| CVV mismatch | CVV does not match the issuer's records | Ask the customer to re-enter CVV |
| AVS mismatch | Billing address does not match | Ask the customer to verify their billing address |
| Fraud suspect | Issuer flagged the transaction | Do not retry — contact the customer |
| Processor error | Temporary issue at the processor | Retry after a delay |
Check response_status and response_code on every transaction response.
{
"id": "TRANSACTION-02LGEHRR1BZSPA6WRY1T3H4CD",
"type": "sale",
"amount": 5000,
"transaction_state": "failed",
"response_status": "declined",
"response_code": "05",
"response_message": "Transaction declined by the issuer.",
"avs_result_code": "n",
"cvv_result": "N",
"correlation_id": "c3d4e5f6-a7b8-9012-cdef-123456789abc"
}
import time, requests, os
API_KEY = os.environ["PARADISE_API_KEY"]
BASE = "https://api.dev.paradisegateway.net"
def process_with_retry(payload, max_retries=3):
for attempt in range(max_retries):
resp = requests.post(
f"{BASE}/v1/transactions",
headers={"Content-Type": "application/json", "APIKEY": API_KEY},
json=payload,
)
result = resp.json()
if result["response_status"] == "approved":
return {"success": True, "transaction": result}
if result["response_status"] == "declined":
return {
"success": False,
"reason": "declined",
"message": result.get("response_message", "Transaction declined"),
"avs": result.get("avs_result_code"),
"cvv": result.get("cvv_result"),
}
# error — retry with backoff
wait = 2 ** attempt
print(f"Error on attempt {attempt + 1}, retrying in {wait}s...")
time.sleep(wait)
return {"success": False, "reason": "error", "message": "Max retries exceeded"}| Scenario | User-facing message |
|---|---|
| Declined — insufficient funds | "Your card was declined. Please try a different payment method." |
| Declined — invalid card | "We couldn't process your card. Please check the number and try again." |
| Declined — AVS mismatch | "Your billing address doesn't match. Please verify and retry." |
| Error — temporary | "Something went wrong. Please try again in a moment." |
Never expose raw error details
Do not show response_code, response_message, or processor details to the customer. Use friendly messages and log the details server-side.
Use these test card numbers to simulate specific scenarios:
| Card number | Expected result |
|---|---|
4000000000000002 | Declined |
5200000000000007 | Declined |
4111111111111111 | Approved |
See Quick reference — test cards for the full list.
- Handle payment failures — broader error handling patterns
- Error handling concepts
- Fraud prevention