Payment Attempts
A payment attempt is a single try to process a payment using a specific payment method. Each attempt represents a concrete action taken to fulfill a payment intent.
Intent vs Attempt Relationship
Understanding the distinction between intents and attempts is crucial:
| Payment Intent | Payment Attempt |
|---|---|
| What: "Please charge my customer $100" | What: "Customer trying to pay with Visa *1234" |
| Lifecycle: Selection → Pending → Success/Failed | Lifecycle: Initiated → Pending → Success/Failed |
| Quantity: One per transaction | Quantity: Multiple sequential attempts possible |
| Purpose: Represents the payment request | Purpose: Represents execution with specific method |
Visual Example
Multiple Sequential Attempts
An intent can have multiple attempts in sequence:
- First Attempt: Customer tries to pay with Card A → Declined
- Intent returns to
selectionstatus - Second Attempt: Customer tries different Card B → Success
- Intent moves to
successstatus
Example Scenario
// Intent created
{
"intent_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": 10000,
"status": "selection",
"attempt_count": 0
}
// First attempt (card declined)
{
"intent_id": "550e8400-e29b-41d4-a716-446655440000",
"attempt_id": 12345,
"method": "card",
"status": "failed",
"failure_reason": "CardDeclined"
}
// Intent goes back to "selection"
// Second attempt (PayPal succeeds)
{
"intent_id": "550e8400-e29b-41d4-a716-446655440000",
"attempt_id": 12346,
"method": "paypal",
"status": "success"
}
// Intent now in "success" status
Attempt Statuses
Each attempt has its own lifecycle:
| Status | Description |
|---|---|
initiated | Attempt created, ready to process |
pending | Payment is being processed |
authorized | Payment authorized (for delayed capture) |
success | Payment completed successfully |
failed | Payment failed |
chargeback | Payment was charged back |
canceled | Attempt was canceled |
Attempt Properties
{
"id": 12345,
"intent_id": "550e8400-e29b-41d4-a716-446655440000",
"attempt_status": "success",
"method": "card",
"brand": "visa",
"card_last4": "1234",
"card_bin": "424242",
"failure_reason": null,
"created": "2024-01-15T10:30:00Z"
}
| Property | Description |
|---|---|
id | Unique attempt identifier |
intent_id | Parent intent ID |
attempt_status | Current attempt status |
method | Payment method used (card, paypal, etc.) |
brand | Payment brand (visa, mastercard, etc.) |
failure_reason | Why it failed (if applicable) |
When Attempts Are Created
Interactive Payments (Customer-Initiated)
Attempts are created automatically when:
- Customer selects a payment method on checkout page
- Customer clicks "Pay" button
- NjiaPay processes the payment with the chosen PSP
Non-Interactive Payments (Auto-Payments)
You explicitly create an attempt via API:
POST /api/intents/auto-attempt
{
"amount": 10000,
"currency": "ZAR",
"reference_id": "subscription_renewal_march",
"purchaser_id": "customer_abc",
"credentials": ["credential_token_xyz"]
}
See Auto Payments Guide for details.
Attempt Cancellation
Attempts can be canceled by customers:
Customer Cancellation
Customer clicks "Cancel" or closes the checkout page:
- Attempt moves to
canceledstatus - Intent moves to
canceledstatus
Failure Handling
When an attempt fails, the system evaluates:
- Are there alternative payment methods available?
- Yes → Intent returns to
selection, customer can retry - No → Intent moves to
failedstatus
- Yes → Intent returns to
- Why did it fail?
- Failure reason is recorded (e.g.,
CardExpired,InsufficientFunds)
- Failure reason is recorded (e.g.,
Common Failure Reasons
| Failure Reason | Description |
|---|---|
CardExpired | Card expiration date has passed |
CardBlocked | Card is blocked by issuer |
InsufficientFunds | Not enough balance |
CVCDeclined | Incorrect CVV/CVC code |
Fraud | Flagged as potential fraud |
ThreeDSAuthenticationError | 3D Secure authentication failed |
RefusedByIssuer | Bank declined without specific reason |
Attempt Actions
Some attempts require additional customer actions:
Redirect Action
{
"action": {
"type": "redirect",
"url": "https://3ds-provider.com/authenticate",
"method": "GET"
}
}
Customer will be redirected to complete 3D Secure authentication.
Authenticate Action
{
"action": {
"type": "authenticate",
"how": "otp"
}
}
Customer must provide additional authentication on the NjiaPay checkout page (OTP, PIN, etc.).
Auto-Payment Attempts
For recurring payments, you create attempts without customer interaction:
POST /api/intents/auto-attempt
{
"amount": 10000,
"currency": "ZAR",
"reference_id": "subscription_month_2",
"purchaser_id": "customer_abc",
"credentials": ["stored_credential_token"]
}
Key differences:
- No redirect to checkout page
- Uses previously stored payment credentials
- Immediate success or failure (no
selectionstate) - Must have prior successful payment with MIT enabled
See Auto Payments Guide for complete details.