Pay
Two-step Processing

Two-Step Payment Processing

Prevent payment-order mismatches by separating client-side authorization from server-side capture


Two-step processing separates payment authorization from capture to prevent payment-order mismatches caused by server failures or connection issues when customers submit payment through Payment Form or Checkout Plugin.

By authorizing on the client and capturing on the server, you ensure your system controls the final charge after confirming the order is recorded.

Prerequisites

Before implementing two-step processing, it's helpful to learn about the following topics.


When to Use Two-Step Processing


Use two-step processing to ensure payment and order data stay synchronized when processing involves both client-side and server-side operations.

Two-step processing validates the payment method and reserves funds without immediately transferring them. Your server only captures the charge after successfully completing its operations (recording the order, updating inventory, etc.), ensuring customers are never charged for orders your system doesn't know about.

Authorizing a Payment

Two-step processing is enabled by default on your API key. When customers submit payments through Payment Form or Checkout Plugin, an authorization is automatically created instead of immediately capturing funds. These client-side components collect payment details, validate the payment method, and create an authorization that holds funds without transferring them.

When a customer completes the payment form or checkout, the payment method is validated and an authorization is created. The response includes a transaction object with status='authorized' and a transaction ID. Your client-side code should send this transaction ID to your server. Your server can then process the order, record it in your database, and only after successful completion, capture the authorization. If server-side processing fails, the authorization remains uncaptured and will expire, preventing the customer from being charged for an order your system never recorded.


Capturing an Authorization

Capture a previously authorized payment by updating the transaction status to processed. This transfers the funds and completes the transaction.

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Capture a previously authorized payment
transaction_id = 'txn_abc123def456'
 
transaction = pl.Transaction.get(transaction_id)
transaction.update(status={'value': 'processed'})
 
print(f"Transaction ID: {transaction.id}")
print(f"Status: {transaction.status}")
print(f"Captured Amount: ${transaction.amount}")

This example:

  1. References the authorized transaction by ID
  2. Updates status='processed' to capture the funds
  3. Transfers the full authorized amount to your account
  4. Completes the transaction and begins settlement

Once captured, funds enter the settlement process and will be deposited to your account according to your processing schedule.


Authorization Best Practices

Follow these best practices when implementing two-step processing:

Timing

Authorizations automatically expire after 2 minutes if not captured, design your server-side flow to capture authorizations as soon as order processing completes.

Error Handling

  • Check authorization status - Verify transaction is authorized before attempting capture
  • Handle failures gracefully - If server-side processing takes longer than 2 minutes, the authorization will auto-void and you'll need to restart the payment flow
  • Optimize processing time - Ensure your server-side order processing completes well within the 2-minute window

Schema Reference


The following transaction status values are used in two-step processing. For complete API reference, see Transactions API Reference.

Transaction Status

Status values used during the authorization and capture lifecycle:

status
object
The status information for this transaction, including the current state, a detailed status code, and a human-readable message explaining the result.
code
enum[string]
A machine-readable code detailing the specific reason or result for the transaction status. This provides granular information about success, failure reasons, or other status conditions.
Values: approved, card_expired, duplicate_attempt, exceeded_limit, general_decline, insufficient_bal, invalid_card_code, invalid_card_number, invalid_zip, invalid_address, invalid_account_number, suspicious_activity, too_many_attempts, processing_issue, issue_reading_card, not_supported, general_reject, general_adjustment, payment_stopped
Read-only permissions: "Undocumented"
message
stringRead-only
A human-readable message describing the transaction status and code. This text is suitable for display to users and provides context about the transaction outcome.
value
enum[string]
The current processing status of the transaction, indicating its lifecycle state such as processing, processed, authorized, declined, voided, or rejected.
Values: processing, authorized, processed, declined, rejected, voided, adjusted

Status Flow:

  1. authorized - Funds are held but not captured
  2. processed - Funds are captured and settling

Authorizations automatically transition to voided status after 2 minutes if not captured.

Next Steps

Enhance your two-step payment processing implementation


Handle Payment Reversals

Process refunds and voids to reverse captured payments or cancel authorizations when orders are cancelled or modified.

Monitor Transaction Status

Track transaction status to understand payment lifecycle from authorized to processed or voided and handle status changes in your application.

Set Up Webhooks

Subscribe to webhook notifications to receive real-time updates for authorization and capture events and keep your system synchronized.


Related articles