razorpay payment already captured error on a second capture call
Fixes Razorpay 'payment already captured' errors from a second capture call. Use when your capture logic can run twice and you need idempotent capture handling. Not for authorization failures, order-id mismatches, or refund flows.
Razorpay payment already captured error on a second capture call
TL;DR
Razorpay payments can only be captured once; a second capture call always errors. Check the payment status with a fetch call before capturing, and treat "already captured" as success for your order state, not as a failure. Make your capture path idempotent so retries and double webhook deliveries cannot break it.
razorpay payment already captured error on a second capture callSteps
- Before every capture call, fetch the payment and check its status. Only call capture when the status is authorized. Success check: your code never calls capture on a payment that is already captured.
- Handle the "already captured" error explicitly: when you receive it, fetch the payment to confirm the captured status and amount, then mark your order paid. Success check: the error path ends in "order paid," not in an error state.
- Add idempotency to your capture flow: record that a capture was attempted for the payment id, and skip re-capture if the record exists. Success check: two rapid capture attempts produce one capture and one clean skip.
- Dedupe the triggers: webhooks, cron jobs, and manual admin actions can all fire capture for the same payment. Funnel them through one capture function with the status check from step 1. Success check: only one code path can call capture.
- Reconcile amounts: confirm the captured amount matches your order total before fulfilling. Success check: fulfillment only runs when captured amount equals the order amount.
When this applies
- Razorpay returns a "payment already captured" style error on your capture call.
- Your flow captures in a webhook handler, a job, or an admin action that can run twice.
- An agent built the capture logic without a status check.
When it doesn't
- The payment failed authorization; there is nothing to capture.
- Order-id mismatch errors; the payment is tied to the wrong order.
- Refunds; those are a separate flow on captured payments.
Tool + version compatibility
Razorpay Payments API (Orders API with manual capture), Razorpay webhooks, all current server SDKs.
"razorpay capture already captured"
Same error. Treat it as confirmation, not failure.
"razorpay double capture error"
The fix is the pre-capture status check plus a single capture path.
"razorpay payment capture idempotency"
Razorpay capture is not naturally idempotent; your status check provides the idempotency.
Why it happens
Razorpay separates authorization from capture: money is authorized at payment time and only moves on capture. Capture is a one-way state transition, so the second call has nothing to do and errors. Agent-built flows commonly call capture from both the success handler and a webhook handler (or retry it on timeout), and the second call hits the already-captured state.
Edge cases / pitfalls
- A capture call that times out may still have succeeded; always fetch status before deciding to retry, or you will manufacture this exact error.
- Partial captures complicate the status check; if you use them, track captured amounts yourself.
- Authorized payments expire if never captured; a status of authorized on an old payment may need a fresh authorization, not a capture.
- Never treat "already captured" as a reason to refund; it means the money is correctly collected.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_gnfBivGswkRWe2x9S05VIQ