Payment Idempotency

Payment idempotency ensures that multiple submissions of the same payment request only take effect once, avoiding double charge. Core mechanisms: idempotency key, state machine, reconciliation with payment provider. This article explains implementation points with a reference table.

Overview

  • Idempotency key: Merchant order id or client-provided idempotency_key; before payment, check if already processed; if yes, return previous result.
  • State machine: Pending → InProgress → Paid/Closed/Failed. Only certain states allow charge; duplicate requests return current state.
  • Provider idempotency: WeChat, Alipay, etc. support same out_trade_no for multiple queries or submissions; only process once. Follow provider docs for correct params.
  • Reconciliation: Periodically reconcile with provider; handle anomalies (over-charge, under-charge).

Example

Example 1: Flow

Plain text
1. Request carries order_id or idempotency_key
2. Check payment record: exists and final state → return original result
3. Not exists or non-final → call payment provider
4. Provider success → update to paid, persist
5. Provider in-progress → poll or async callback
6. Duplicate requests intercepted at step 2

Example 2: Main points

PointDescription
Idempotency keyOrder id or idempotency_key; unique index
State machineFinal states (paid/closed) immutable
ProviderPass out_trade_no etc.; use provider idempotency
ReconciliationDaily reconciliation; fix inconsistencies manually or automatically

Example 3: Concurrency

  • Same order, concurrent requests: unique index + insert to "grab" slot, or SELECT FOR UPDATE; only one request proceeds to payment; others return "in progress" or original result.

Core Mechanism / Behavior

  • Idempotency check: Before calling provider, check DB for existing record with same key; return if final state.
  • State transitions: Only valid transitions allowed; final states block further changes.
  • Provider: Use provider's idempotency (e.g. out_trade_no) to avoid double charge on their side.

Key Rules

  • Idempotency key required; reject if missing, or generate server-side key and return to client.
  • State machine must be strict; final states irreversible; in-progress, closed, etc. must be well-defined.
  • Reconciliation is last line of defense; have a process when provider and local records differ.

What's Next

See Idempotency Design, Distributed Transactions. See Database Transactions for atomic state updates.