Payment API timeouts: retry safely without creating duplicate orders

A payment API timeout creates uncertainty, not proof of failure. The provider may have accepted the request even though your application did not receive the response. The operational challenge is to recover the result without creating an unnecessary second payment. This guide uses a single order with a delayed response to explain the identifiers, state transitions and checks that make recovery understandable.

OrsunPay editorial teamPublished
Editorial illustration: Payment API timeouts: retry safely without creating duplicate orders

Identify the business operation before sending it

Create an internal payment operation for the order before making the network request. Store the amount, currency and purpose in a durable record. Use the integration's documented idempotency mechanism where supported, with a key tied to that operation rather than a new random value for every retry. The exact rules and retention periods belong to the API contract, so confirm them rather than assuming a universal standard. If the customer changes the order or amount, decide whether that creates a new business operation instead of reusing an incompatible request.

Developer tools

Distinguish a transport error from a payment result

Your application should not translate every HTTP or network problem into a final declined status. A request that never left the client differs from one accepted by the server before the connection broke. Record enough technical context to investigate without logging payment secrets or unnecessary customer data. In the example, order B205 moves to an unresolved state when the response times out. The customer sees a clear message that the result is being checked. Staff should have the same interpretation, rather than receiving an automatic instruction to charge again.

Payment webhooks

Retrieve and reconcile the existing operation

Use the documented status-retrieval path and the identifiers already recorded to look for the original result. A verified notification may also arrive while the application is checking. Both paths should converge on one order state through controlled transitions. Stripe's PaymentIntents documentation provides one provider's payment lifecycle model; its identifiers and statuses must not be treated as universal names across integrations. Build the application around the contract you actually use. If the result remains uncertain, preserve that uncertainty and escalate it rather than manufacturing a success or failure for convenience.

Make repeated processing safe

Idempotency is useful at more than the payment-creation boundary. The application should also prevent a repeated success notification from shipping the same order twice. Store an event identifier or another documented deduplication reference and make the update to business state atomic where your data model requires it. A retrying worker must know whether its previous attempt already applied the business action. Separate receiving an event from completing fulfilment so a failure in one downstream system does not force you to repeat every earlier step without checking its outcome.

  • Keep one durable identifier for the intended operation.
  • Preserve the provider reference when it becomes available.
  • Deduplicate repeated events before business side effects.
  • Route unresolved outcomes to a visible investigation queue.

Test the failures that are easy to miss

A useful test set includes a response lost after acceptance, a duplicate webhook, a notification delivered before the API response and a downstream fulfilment error. Define the expected order state after each scenario. Do not merely assert that the code returns an HTTP success response. Check that the customer is not invited to pay again unnecessarily and that staff can identify what happened. For B205, the desired result is one paid order and one fulfilment action, even if several network messages were required to discover and apply the outcome.

Apply the design to OrsunPay carefully

OrsunPay documents REST endpoints, exact decimal amounts, idempotent creation and signed webhook events. Confirm the contract for the operation and deployment you intend to use. The merchant's PSP remains responsible for processing and settlement, while OrsunPay supplies the software workflow. Avoid assuming that a general retry policy can safely cascade a payment to another provider: automatic cascading is not currently part of the offering. Begin with reliable recovery of the original operation, then add further behaviour only when its supported scope and failure consequences are explicitly understood.

Explore OrsunPay

Talk to our team

Sources

Keep reading