Preventing Order Loss and Duplicate Submissions in Payment Systems
This article explains common causes of order loss and duplicate submissions in payment workflows, and provides practical backend strategies such as intermediate payment states, timeout queries, idempotent handling, retry mechanisms, and Redis‑based deduplication to ensure reliable order processing.
The simplified order flow consists of order submission followed by payment through a payment gateway, which interacts with third‑party channels (WeChat, Alipay, UnionPay). After a successful payment, the gateway sends an asynchronous notification to update its own order status and then notifies the business application to update its order status.
Order loss can occur when callbacks are missed or internal errors happen, leading to situations where the user has paid but the server has not updated the order status, potentially causing complaints or duplicate payments. Losses caused by external factors (steps 3 and 5) are called external order loss, while those caused by internal steps (4 and 6) are internal order loss.
To prevent order loss, the following measures are recommended:
1. Add an intermediate payment state "Paying". When an order attempts payment, first check for a "Paying" record and lock the pre‑pay operation. After payment succeeds, update the record to "Paid".
2. Define a timeout (e.g., 30 seconds) in the payment center. If no success callback is received within this window, actively query the payment result at intervals (10 s, 20 s, 30 s). If the result remains unknown after the maximum retries, handle it as an exception.
3. Once the payment center obtains the result, synchronize it to the business system via MQ or direct calls; direct calls should include retry logic (e.g., SpringBoot Retry).
4. Ensure idempotency for all payment result notifications on both the payment center and business applications, processing each message only once.
5. Business applications should also perform proactive timeout queries for payment results.
6. Store pending payment orders in a dedicated table and use a scheduled task to scan and query their status.
To prevent duplicate order submissions, consider the following approach:
1. When creating an order, compute a hash of the order information and check Redis for an existing key. If the key exists, reject the duplicate submission; otherwise, create a new key with an expiration time and proceed with order creation, effectively limiting identical operations within a short period.
WeChat Pay best practices are illustrated in the accompanying diagram.
PS: If you find this sharing useful, feel free to like or watch.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.