Core Concepts

Payment Attempts

Understanding payment attempts and their relationship with intents

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 IntentPayment Attempt
What: "Please charge my customer $100"What: "Customer trying to pay with Visa *1234"
Lifecycle: Selection → Pending → Success/FailedLifecycle: Initiated → Pending → Success/Failed
Quantity: One per transactionQuantity: Multiple sequential attempts possible
Purpose: Represents the payment requestPurpose: Represents execution with specific method

Visual Example

mermaid
graph TD
    A[Payment Intent: $100] --> B[Attempt 1: Visa *1234]
    B --> C{Success?}
    C -->|No| D[Intent returns to Selection]
    D --> E[Attempt 2: PayPal]
    E --> F{Success?}
    F -->|Yes| G[Intent status: Success]
    F -->|No| H[Intent status: Failed]
    C -->|Yes| G

Multiple Sequential Attempts

An intent can have multiple attempts in sequence:

  1. First Attempt: Customer tries to pay with Card A → Declined
  2. Intent returns to selection status
  3. Second Attempt: Customer tries different Card B → Success
  4. Intent moves to success status

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:

StatusDescription
initiatedAttempt created, ready to process
pendingPayment is being processed
authorizedPayment authorized (for delayed capture)
successPayment completed successfully
failedPayment failed
chargebackPayment was charged back
canceledAttempt 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"
}
PropertyDescription
idUnique attempt identifier
intent_idParent intent ID
attempt_statusCurrent attempt status
methodPayment method used (card, paypal, etc.)
brandPayment brand (visa, mastercard, etc.)
failure_reasonWhy it failed (if applicable)

When Attempts Are Created

Interactive Payments (Customer-Initiated)

Attempts are created automatically when:

  1. Customer selects a payment method on checkout page
  2. Customer clicks "Pay" button
  3. NjiaPay processes the payment with the chosen PSP

Non-Interactive Payments (Auto-Payments)

You explicitly create an attempt via API:

Terminal
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 canceled status
  • Intent moves to canceled status

Failure Handling

When an attempt fails, the system evaluates:

  1. Are there alternative payment methods available?
    • Yes → Intent returns to selection, customer can retry
    • No → Intent moves to failed status
  2. Why did it fail?
    • Failure reason is recorded (e.g., CardExpired, InsufficientFunds)

Common Failure Reasons

Failure ReasonDescription
CardExpiredCard expiration date has passed
CardBlockedCard is blocked by issuer
InsufficientFundsNot enough balance
CVCDeclinedIncorrect CVV/CVC code
FraudFlagged as potential fraud
ThreeDSAuthenticationError3D Secure authentication failed
RefusedByIssuerBank 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 selection state)
  • Must have prior successful payment with MIT enabled

See Auto Payments Guide for complete details.

Payment Intents

Learn about payment intents

Status Lifecycle

Understand status transitions

Auto Payments

Set up recurring payments