Agent Wranglers

Amounts and orders Required

Create each charge with an idempotency key

Send an idempotency key, built from your own stable IDs, on every provider request that creates a payment, a refund or a payout.

How to do it

A request can time out after the provider has charged the card. A retry with the same key returns the first result instead of charging again. Build the key from the order and attempt, such as order-ord_8f2k-attempt-1, and reuse it for every retry of that request. Make a new key only when the amount or payment method changes. Providers forget keys after a while, after 24 hours at Stripe. After that, look the payment up by your order ID instead of retrying. The server side of the same idea is idempotency keys, and the attack test is race conditions.

Example

const idempotencyKey = `order-${order.id}-attempt-${order.attempt}`
const intent = await withRetries(() => stripe.paymentIntents.create(
  { amount: order.totalMinor, currency: order.currency.toLowerCase(), metadata: { orderId: order.id } },
  { idempotencyKey },
))
idempotency_key = f"order-{order.id}-attempt-{order.attempt}"
intent = with_retries(lambda: stripe.PaymentIntent.create(
    amount=order.total_minor,
    currency=order.currency.lower(),
    metadata={"order_id": order.id},
    idempotency_key=idempotency_key,
))

How to check

In a test, make the provider call time out after the request was sent, then retry. The provider shows one payment, and the order shows one charge.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers payments playbook: https://agentwranglers.se/playbook/payments/amounts-and-orders/idempotent-charge-creation.