Payment method, apparatus and electronic device
Patent Information
- Application Number
- CN202611426115.6
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-09-15
- Publication Date
- 2026-10-16
AI Technical Summary
[0002]目前,线下收银支付场景存在多重刚性约束:门店网络波动、断网、高延迟频发,支付请求与订单同步易超时丢包;收银终端多为算力、存储有限的工控设备,无法部署重型中间件;支付业务资损敏感度高,状态误判易引发资金纠纷;同时多数系统处于新旧分表迁移周期,需兼顾存量功能兼容与新架构落地
[0014]The aforementioned payment method employs a multi-threaded architecture on the client side to decouple front-end interaction from back-end tasks, avoiding blocking of the checkout process. A closed-loop design, including local pre-database storage, a conservative state machine, and double-layer compensation, ensures zero data loss in weak network conditions, fundamentally preventing misjudgments and losses in uncertain scenarios, while also balancing real-time synchronization efficiency with backup replenishment after network outages. On the server side, dynamic dual idempotency checks adapt to concurrent write scenarios from multiple entry points, automatically degrading under high load to ensure throughput and guaranteeing zero duplicate data entry for payment data in the sharded architecture. Bidirectional hash sharding breaks down cross-dimensional relationship barriers, combined with hotspot caching to improve query performance, supporting decoupled asynchronous reporting of payment and order links, and smooth migration between old and new shards. Ultimately, under the combined constraints of terminal limitations, unstable networks, and architectural iterations, it achieves highly reliable eventual consistency between end-to-end payments and orders.
Smart Images

Figure CN122928340A_ABST
Abstract
Description
Technical Field
[0001] This application relates to the field of financial technology, and in particular to a payment method, device and electronic device. Background Technology
[0002] Currently, offline payment scenarios face multiple rigid constraints: frequent network fluctuations, outages, and high latency at stores, leading to timeouts and packet loss during payment request and order synchronization; POS terminals are mostly industrial control equipment with limited computing power and storage, making it impossible to deploy heavy middleware; payment transactions are highly sensitive to financial losses, and misjudgments can easily cause disputes; meanwhile, most systems are in the process of migrating between old and new tables, requiring a balance between compatibility with existing functions and the implementation of the new architecture. Existing general-purpose distributed payment solutions heavily rely on real-time networks, and in weak network environments, issues such as unverifiable payment status and failed system checks after payment have been deducted by the channel can easily arise. Furthermore, they struggle to simultaneously adapt to the complex requirements of terminal performance limitations, cross-dimensional table join queries, multi-entry concurrent anti-duplicate measures, and smooth architecture migration, typically only addressing one type of problem at a time and failing to form an end-to-end consistency guarantee system. Summary of the Invention
[0003] In order to address the shortcomings of the prior art, the purpose of this application is to provide a payment method, device and electronic device that can achieve payment consistency in the event of environmental anomalies.
[0004] To achieve the above objectives, this application adopts the following technical solution: A payment method, comprising: The local payment plugin runs on a multi-threaded architecture based on the main payment thread and an asynchronous thread pool to respond to payment code payment requests. Before calling the upstream payment channel, the main payment thread generates a payment order number and creates a payment order record to obtain the local payment order with the corresponding business order number. Based on the local payment order, a payment code payment is initiated to the corresponding upstream payment channel. If the upstream channel is abnormal, the local payment order is atomically updated to the payment in progress state. At the same time, a query task is submitted to the asynchronous thread pool. The background worker thread polls for the query according to the adaptive backoff strategy until the final payment state is obtained or the safe termination threshold is reached, and the final state local payment order is obtained. For local payment orders that have been updated to the final state of paid or refunded and are marked as unsynchronized, a single asynchronous reporting thread is triggered through an asynchronous thread pool to synchronize payment data to the server. At the same time, the background scheduling thread obtains unsynchronized payment orders and segments them according to store identifiers. The reporting priority is calculated based on order amount, payment duration and network quality. Corresponding worker threads are assigned to each segment to perform tiered batch compensation reporting, so as to output payment order data to be entered into the database. The system adopts a multi-threaded concurrent consumption mode to receive reported payment order data, and performs dual idempotent checks on the existence of the payment order number using a distributed lock and the database. The lock expiration time and check granularity are dynamically adjusted according to the current number of concurrent threads and the amount of messages back up. In high-load scenarios, the system automatically degrades to a fallback check using a unique key in a sharded table. After the check passes, the data is written to the corresponding payment sharded table according to the sharded table routing rules at the store level, generating server-side payment order records stored in the sharded table. Based on the synchronous generation of payment order records on the server, a two-way mapping relationship between payment order number and corresponding business order number is generated. The mapping from payment to business is stored in a table partitioned by payment order number hash, and the mapping from business to payment is stored in a table partitioned by business order number hash. Then, a thread-safe hot spot mapping cache is built based on historical query frequency, and pre-routing loading is performed on high-frequency mappings to realize bidirectional fast query across table dimensions, so as to realize payment.
[0005] Furthermore, the specific steps for generating a payment order number and creating a payment order record include: The main payment thread establishes a thread-safe connection with the local lightweight database and generates a globally unique payment order number by concatenating the last six digits of the store identifier with a timestamp and a three-digit random number. A row-level transaction is initiated in the local database, and a payment order record containing the business order number, store identifier, transaction amount, payment method, payment status, and creation time is created using atomic write. The payment status is initialized to unpaid and the synchronization flag is set to unsynchronized. After the transaction is committed, a local payment order bound to the corresponding business order number is obtained, which serves as the unified data benchmark for subsequent payment execution, status polling, and compensation reporting.
[0006] Furthermore, the specific steps for the background worker thread to poll and query orders according to the adaptive backoff strategy include: The background worker thread first parses the exception type returned by the upstream channel. If it is a channel processing exception, the initial order query interval is set to 1 second. If it is a network timeout or HTTP exception, the initial order query interval is set to 2 seconds. After each order query failure, the polling interval is multiplied by the backoff coefficient according to the exponential backoff rule and a random jitter value is added to avoid the channel request impact caused by multiple orders querying at the same time. When the cumulative number of order queries reaches the maximum number threshold or the duration reaches the safe termination threshold, automatic polling is stopped and the payment order is marked as pending confirmation. The payment is kept in the payment in progress state throughout the process and is not directly judged as payment failure, so as to avoid the risk of financial loss when the channel has deducted the payment but the system misjudged the failure.
[0007] Furthermore, the steps for calculating reporting priority based on order amount, payment duration, and network quality specifically include: The background scheduling thread scans the local database at fixed intervals for payment orders marked as unsynchronized, and groups all unsynchronized orders by store identifier. For each store group, a reporting priority value is calculated, with the transaction amount accounting for 50%, the time elapsed since payment completion accounting for 30%, and the network quality score converted from the success rate of the last three reports accounting for 20%. Based on the priority value, stores are divided into high, medium, and low levels. High-priority stores are allocated 2 concurrent worker threads with a batch capacity of 20 transactions, medium-priority stores are allocated 1 worker thread with a batch capacity of 50 transactions, and low-priority stores are merged for reporting with a batch capacity of 100 transactions. The batch capacity and number of concurrent threads are dynamically adjusted based on real-time network quality to adapt to scenarios with fluctuating network conditions.
[0008] Furthermore, the steps for performing dual idempotent checks on distributed locks and database existence based on the payment order number specifically include: A distributed lock key is constructed by concatenating the store identifier and the payment order number. The lock expiration time is dynamically calculated based on the current number of concurrent consumer threads and the message queue backlog. The default lock duration is 300 seconds, which is reduced to 120 seconds when the message backlog exceeds the warning threshold. The RedisSETNX command is executed to request a distributed exclusive lock. After the lock is successfully acquired, the payment migration table is queried according to the store-level table routing rules to verify whether the payment order number already exists. When the number of concurrent consumer threads exceeds the limit or the message backlog reaches the degradation threshold, the distributed lock verification is automatically skipped, and the unique key constraint of the payment order number in the payment table is used to complete the fallback idempotency verification. This ensures that data is not written repeatedly while also taking into account the processing throughput under high load scenarios.
[0009] Furthermore, the specific steps for synchronously generating a two-way mapping relationship between payment order numbers and corresponding business order numbers include: Within the same database transaction where payment orders are entered, a hash operation is performed on the payment order number, and then modulo 10 is taken to obtain the routing suffix for the payment and business mapping sub-tables; a hash operation is performed on the business order number, and then modulo 10 is taken to obtain the routing suffix for the business and payment mapping sub-tables; associated records containing payment order number, business order number, business type, and extended information are written to the payment and business mapping sub-tables, and simultaneously, reverse associated records containing business order number and payment order number are written to the business and payment mapping sub-tables; the bidirectional mapping relationship takes effect simultaneously after the transaction is successfully committed, and is rolled back along with the payment order records if the transaction fails, establishing a cross-dimensional bidirectional query link between the payment sub-table and the business order sub-table.
[0010] Furthermore, it also includes a dual-link writing step for order details, specifically including: Upon receiving business order details data uploaded from the POS terminal, the system first verifies the integrity of the order master information and product details fields. It then requests a distributed concurrent lock using a combination of order number, store identifier, and company identifier as the key. After acquiring the lock, it executes the old order table write link: deleting records of the same order number from the master table, product table, and payment table in the existing database, and then rewriting the complete order master data, product details, and payment details, ensuring compatibility with existing reports and reconciliation functions. Simultaneously, it executes the new order partition table write link: calling the new order domain synchronization interface through a service proxy, routing to the corresponding new partition table by modulo the company identifier, and writing to the order master table, product table, and payment table. The payment order link and order detail link are decoupled and reported independently and asynchronously. A bidirectional mapping relationship is used to complete the association and matching of payment data and order data, achieving eventual consistency between payment and order data during the migration cycle between the old and new partition tables.
[0011] Furthermore, the specific steps for constructing a thread-safe hotspot mapping cache include: The system periodically tracks the query frequency of each payment order number and business order number in the two mapping tables, marking mappings with query counts exceeding a hotspot threshold within a continuous statistical period as hotspot mappings. During off-peak business hours, the routing results of hotspot mappings and core related fields are preloaded into a thread-safe distributed cache layer, with a cache expiration time set and active invalidation supported. When multiple threads concurrently query mapping relationships, the cache is queried first to obtain the routing results, directly locating the target table. If the cache misses, hash table calculation is performed, and the calculation result is written back to the cache. When the mapping relationship changes, cache invalidation is triggered synchronously to ensure consistency between cached data and table data, improve the response speed of bidirectional queries across tables, and support efficient convergence of payment data and business order data.
[0012] To achieve the above objectives, this application adopts the following technical solution: A payment device includes: an acquisition module, a calculation module, and an output module.
[0013] To achieve the above objectives, this application adopts the following technical solution: Electronic devices store computer programs that, when executed, can implement methods such as payment.
[0014] The aforementioned payment method employs a multi-threaded architecture on the client side to decouple front-end interaction from back-end tasks, avoiding blocking of the checkout process. A closed-loop design, including local pre-database storage, a conservative state machine, and double-layer compensation, ensures zero data loss in weak network conditions, fundamentally preventing misjudgments and losses in uncertain scenarios, while also balancing real-time synchronization efficiency with backup replenishment after network outages. On the server side, dynamic dual idempotency checks adapt to concurrent write scenarios from multiple entry points, automatically degrading under high load to ensure throughput and guaranteeing zero duplicate data entry for payment data in the sharded architecture. Bidirectional hash sharding breaks down cross-dimensional relationship barriers, combined with hotspot caching to improve query performance, supporting decoupled asynchronous reporting of payment and order links, and smooth migration between old and new shards. Ultimately, under the combined constraints of terminal limitations, unstable networks, and architectural iterations, it achieves highly reliable eventual consistency between end-to-end payments and orders. Attached Figure Description
[0015] Figure 1 A structural block diagram of an electronic device provided in an embodiment of this application.
[0016] Figure 2 A flowchart illustrating a payment method provided in an embodiment of this application.
[0017] Reference numerals 100, electronic device; 11, processor; 12, memory. Detailed Implementation
[0018] To enable those skilled in the art to better understand the present application, the technical solutions in specific embodiments of the present application will be clearly and completely described below with reference to the accompanying drawings.
[0019] It should be noted that the terms "first," "second," and similar terms used in this application specification and claims do not indicate any order, quantity, or importance, but are merely used to distinguish different components. Similarly, "an" or "a" and similar terms do not indicate a quantity limitation, but rather indicate the presence of at least one. "A plurality of" indicates at least two. "Comprising" and similar terms mean that the elements or objects preceding "comprising" cover the elements or objects listed after "comprising" and their equivalents, and do not exclude other elements or objects. "Connection" and similar terms are not limited to physical or mechanical connections, but can include electrical connections, whether direct or indirect.
[0020] The singular forms “a,” “the,” and “the” used in this application specification and appended claims are also intended to include the plural forms, unless the context clearly indicates otherwise.
[0021] The payment method provided in this embodiment can be executed in electronic device 100 or similar device. Figure 1This is a hardware structure block diagram of an electronic device 100 that implements an embodiment of this application. For example... Figure 1 As shown, the electronic device 100 may include one or more ( Figure 1 (Only one is shown) memory 12 and processor 11. The electronic device 100 is the control terminal of the payment device, which is used to control the operation of the payment device to ensure payment consistency in the event of environmental anomalies.
[0022] The memory 12 stores program instructions, such as software programs and modules for application software, like a computer program for a payment method in this embodiment. The processor 11 executes the program instructions stored in the memory 12. By running the computer program stored in the memory 12, it can perform various functional applications and data processing to support the implementation of payments in the event of environmental anomalies.
[0023] The processor 11 may include, but is not limited to, a microprocessor 11 (Microcontroller Unit, abbreviated as MCU) or a programmable gate array (Field Programmable Gate Array, abbreviated as FPGA).
[0024] Those skilled in the art will understand that Figure 1 The structure shown is for illustrative purposes only and does not limit the structure of the electronic device 100 described above. For example, the electronic device 100 may also include components that are more... Figure 1 The more or fewer components shown, or having the same Figure 1 The different configurations shown are illustrated.
[0025] In some embodiments, a portion of the payment method described below is executed in electronic device 100 to make a payment.
[0026] This embodiment also provides a payment method. Figure 2 This is a flowchart of a payment method according to an embodiment of this application, which is used to ensure payment consistency under abnormal conditions.
[0027] like Figure 2 As shown in the embodiments provided in this application, a payment method includes: S1 runs the local payment plugin based on a multi-threaded architecture of a main payment thread and an asynchronous thread pool to respond to payment code payment requests. Before calling the upstream payment channel, the main payment thread generates a payment order number and creates a payment order record, obtaining the local payment order with the corresponding business order number. In the above steps, the main payment thread is responsible for responding to payment requests from the POS terminal and executing core payment call logic, while the asynchronous thread pool handles non-real-time interactive tasks such as background order checking and data reporting. The core purpose of this division of labor is to avoid background operations blocking the front-end interaction of the POS terminal, adapting to the constraints of limited computing power of the POS terminal and the need to prioritize the smoothness of POS operations. Persisting payment orders locally before calling the upstream payment channel, rather than recording them after successful payment, is the foundation of the entire end-side consistency logic: offline store networks may be interrupted at any time. If the system relies on the server to generate payment orders or only record them after successful payment, once the network is interrupted, the payment status will be untraceable, and subsequent compensation and order checking will also lose their data source. Local payment orders are bound one-to-one with business order numbers, ensuring that every payment can be traced back to the corresponding business order, preventing payment and order disconnection from the source. After this step is implemented, payment order creation and status management can be completed without relying on a real-time network, reducing the POS terminal's dependence on network stability and providing a unified data benchmark for all subsequent status changes and compensation reporting actions.
[0028] S2 initiates payment code payment to the corresponding upstream payment channel based on the local payment order. If the upstream channel encounters an anomaly, the local payment order is atomically updated to the payment in progress state. At the same time, a query task is submitted to the asynchronous thread pool. The background worker thread polls for the query task according to the adaptive backoff strategy until the final payment state is obtained or the safe termination threshold is reached, thus obtaining the final state local payment order. In the above steps, upstream channel anomalies include not only explicit payment failures but also all scenarios where the final payment result cannot be confirmed, such as channel returning "processing in progress," network timeouts, and interface request failures. For these uncertain results, this method does not directly determine payment failure. Instead, it atomically updates the local payment order to a "paying in progress" state and then delegates it to an asynchronous thread pool for polling and order retrieval. Atomic updates are used here to adapt to multi-threaded environments and avoid state inconsistencies caused by multiple threads simultaneously modifying the same payment order status. Delegating the order retrieval task to an asynchronous thread pool ensures the main payment thread is quickly released, without affecting subsequent cashier operations. The adaptive backoff polling strategy dynamically adjusts the query interval based on the anomaly type and the order retrieval result, avoiding pressure on the payment channel from frequent requests and adapting to order retrieval efficiency during offline network fluctuations. Setting a safe termination threshold prevents abnormal orders from occupying thread resources for extended periods. This step works in close coordination with the previous step's local persistence feature: because the payment order is already persistently stored locally, this intermediate state of payment can be retained for a long time and continuously checked for confirmation. If a synchronous call mode without local state is used, only a failure result can be returned to the user in abnormal scenarios, which can easily lead to financial losses where the channel has deducted the payment but the system has failed to determine it. This step establishes a financial loss prevention mechanism at the level of state determination rules to help reduce the risk of financial disputes in uncertain scenarios.
[0029] For local payment orders that have been updated to the final state of paid or refunded and are marked as unsynchronized, S3 triggers a single asynchronous reporting thread through an asynchronous thread pool to synchronize payment data to the server. At the same time, the background scheduling thread obtains unsynchronized payment orders and segments them according to store identifiers. Based on order amount, payment duration and network quality, the reporting priority is calculated, and corresponding worker threads are assigned to each segment to perform tiered batch compensation reporting, so as to output payment order data to be entered into the database.
[0030] The above steps establish two reporting paths: single asynchronous reporting for normal network scenarios, triggering reporting immediately upon payment order update to the final state to ensure real-time payment data synchronization and enable the server and frontend to quickly obtain payment results; and batch tiered compensation as a fallback mechanism, where a background scheduling thread periodically scans locally unsynchronized payment orders, shards them by store identifier, calculates reporting priority based on order attributes and network status, and allocates corresponding resources to different shards for reporting. The sharding design by store identifier echoes the server-side table partitioning architecture, reducing subsequent server-side routing and processing overhead; the tiered reporting design prioritizes the synchronization of high-importance orders when network quality is poor, balancing synchronization efficiency and resource consumption. This step sets synchronization status flags on local payment orders, accurately filtering out all unsynchronized orders and preventing missed or duplicate transmissions. These settings achieve the user experience requirements under normal network conditions, solve the data recovery problem after long-term network outages, and adapt to the characteristics of unstable store networks.
[0031] S4 uses a multi-threaded concurrent consumption mode to receive reported payment order data and performs dual idempotent checks on the payment order number using a distributed lock and database existence. It dynamically adjusts the lock expiration time and check granularity based on the current number of concurrent threads and message backlog, and automatically downgrades to a backup check using a unique key in a sharded table under high load scenarios. After the check passes, the data is written to the corresponding payment sharded table according to the sharding routing rules at the store level, generating server-side payment order records stored in the sharded table.
[0032] In the above steps, the server receives payment order data from multiple entry points, including single-transaction reporting, batch compensation, and message queue retries, and uses multi-threaded concurrent consumption to improve processing throughput. To avoid duplicate entries under multiple entry points and high concurrency, a dual idempotent mechanism of distributed lock verification and database existence verification is implemented. The former uses a distributed lock to control that only one thread processes the same payment order at a time, while the latter uses database-level existence checks to provide a fallback against duplicates. Simultaneously, the solution dynamically adjusts the lock expiration time and verification granularity based on the current number of concurrent threads and message backlog, ensuring strict idempotency under low system load and automatically downgrading to database-level fallback verification under high load scenarios, preventing the distributed lock from becoming a system performance bottleneck. Payment orders that pass verification are written to the corresponding sharded tables according to the sharding routing rules at the store level, achieving sharded storage of payment data and improving the performance of subsequent store-level queries and statistics. The deep integration of idempotent logic and sharding routing avoids the performance loss of cross-table deduplication under a sharded architecture, thus improving data consistency and processing efficiency in sharded scenarios.
[0033] S5 synchronously generates a two-way mapping relationship between payment order number and corresponding business order number based on the server-side payment order record. The mapping from payment to business is stored in a table based on the hash of payment order number, and the mapping from business to payment is stored in a table based on the hash of business order number. Then, a thread-safe hot spot mapping cache is built based on the historical query frequency, and pre-routing loading is performed on high-frequency mappings to realize bidirectional fast query across table dimensions, so as to realize payment.
[0034] In the above steps, payment orders and business orders belong to different sharding systems. Payment orders are sharded by store, while business orders are sharded by company. Inconsistent sharding rules lead to poor cross-table query performance. Therefore, the solution synchronously generates a two-way mapping relationship: the mapping from payment to business is stored in a sharded table based on the payment order number hash, supporting quick location of the corresponding business order by payment order number; the mapping from business to payment is stored in a sharded table based on the business order number hash, supporting quick querying of all associated payment orders by business order number. The two-way mapping and payment order data entry are completed synchronously, ensuring consistency between the mapping relationship and the payment order data. Based on this, a thread-safe hotspot mapping cache is built based on historical query frequency. High-frequency access mapping relationships are preloaded into the cache layer, further improving response speed under multi-threaded concurrent queries. The two-way mapping allows payment order reporting and order detail uploads to be decoupled and executed independently and asynchronously. They can complete their own data entry without waiting for the other party's data to arrive, ultimately achieving convergence through the mapping relationship. This naturally adapts to the timing characteristics of local plugins, where payment speed is fast but order detail synchronization speed is slow. This design also supports the migration of order system data between old and new tables. Regardless of whether order data is written to the old table or the new table, it can be associated with payment orders through mapping relationships, ensuring the availability of business queries during the migration.
[0035] As one implementation method, the steps of generating a payment order number and creating a payment order record specifically include: The main payment thread establishes a thread-safe connection with the local lightweight database and generates a globally unique payment order number by concatenating the last six digits of the store identifier with a timestamp and a three-digit random number. A row-level transaction is initiated in the local database, and a payment order record containing the business order number, store identifier, transaction amount, payment method, payment status, and creation time is created using atomic write. The payment status is initialized to unpaid and the synchronization flag is set to unsynchronized. After the transaction is committed, a local payment order bound to the corresponding business order number is obtained, which serves as the unified data benchmark for subsequent payment execution, status polling, and compensation reporting.
[0036] In the above steps, after the main payment thread responds to the payment code payment request from the POS terminal, it first establishes a thread-safe connection with the local lightweight database. This local lightweight database is typically implemented using an embedded database, requiring no additional independent service process, and has extremely low memory and disk resource consumption, making it suitable for the hardware constraints of the POS terminal with limited computing power and storage resources. The thread-safe connection is designed to adapt to the multi-threaded architecture of the local payment plugin. Besides the main payment thread handling payment order creation and channel invocation, subsequent asynchronous order query threads and batch reporting threads all need to access the same payment order data. If a non-thread-safe database connection is used, concurrent reading and writing of the same data row by multiple threads can easily lead to dirty reads, write overwriting, or even database file corruption. The thread-safe connection mechanism ensures the order of data access when multiple threads access the database simultaneously, avoiding concurrency conflicts at the underlying access level.
[0037] After establishing a database connection, the main payment thread generates a globally unique payment order number according to preset rules. Specifically, the generation rule involves concatenating a timestamp with the last six digits of the store identifier, followed by a three-digit random number. The timestamp uses system time accurate to the second, ensuring the payment order number inherently possesses a temporal attribute. This facilitates subsequent scanning of unsynchronized orders, clearing historical data, and tracing payment records by time. Furthermore, the increasing time dimension significantly reduces the probability of duplicate order numbers across different time periods. The last six digits of the store identifier are taken from the store number bound to the current POS terminal, used to distinguish payment orders from different stores. This ensures that local payment order numbers from different stores are not duplicated, adapting to multi-terminal deployment scenarios in chain stores. It also aligns with subsequent rules for segmented reporting by store and server-side table partitioning by store dimension, giving the payment order number inherent routing attributes and reducing additional computational overhead during subsequent data processing. The three-digit random number at the end resolves the issue of conflicting order numbers from multiple payments generated within the same second at the same store. The discreteness of the random number further amplifies the uniqueness of the order number, ensuring that locally generated payment order numbers possess globally unique attributes. This method does not require applying for a number range from the server or waiting for the server to return a tracking number. It does not rely on a network connection at all. Even if the store is offline, it can still generate payment vouchers and advance the payment process normally. This is a key prerequisite for the normal execution of the payment process in a weak network environment.
[0038] After generating the payment order number, the main payment thread initiates a row-level transaction in the local database to create a complete payment order record using atomic writes. Row-level transactions mean that the transaction locks only the currently being written row of payment order data, rather than locking the entire payment order table. This fine-grained locking mechanism ensures atomicity while minimizing blocking of other payment order read / write operations, adapting to scenarios where multiple threads concurrently process multiple payments. It prevents the write of a single payment from slowing down overall processing efficiency, meeting the performance optimization needs under limited terminal computing power. Atomic writes mean that all fields of the payment order record are either written successfully or rolled back completely, preventing incomplete data with some fields written and others missing. Even in extreme cases such as program crashes or terminal power outages during the write process, incomplete payment order records will not be generated, ensuring the integrity and validity of data in the local database. The written payment order record includes core fields such as business order number, store identifier, transaction amount, payment method, payment status, and creation time. Among them, the business order number is bound one-to-one with the business order number pre-generated on the POS terminal, establishing a relationship between payment and business order from the very beginning of payment order creation. This provides an initial basis for subsequent two-way mapping and association on the server side, preventing payment orders from becoming disconnected from business orders. The store identifier forms a verification relationship with the store information in the payment order number, and also provides a grouping basis for subsequent batch compensation reporting by store. The transaction amount and payment method are core attributes of the payment business, used for subsequent channel calls, reconciliation calculations, and amount verification. The payment status and creation time constitute the initial information of the payment state machine, used for subsequent state transition judgments and timeout control.
[0039] The payment status in the payment order record is initialized to unpaid, and the synchronization flag is set to unsynchronized. The payment status is initialized to unpaid because the upstream payment channel has not yet been invoked, and the final payment result is not yet determined. This conforms to the initial flow logic of the payment state machine and provides a baseline state for subsequent state updates in abnormal scenarios, avoiding subsequent process anomalies caused by incorrect initial states. Setting the synchronization flag to unsynchronized indicates that the payment order has not yet been successfully reported to the server. This flag is the core filtering criterion for subsequent single asynchronous reporting and batch compensation reporting. Subsequent asynchronous threads use payment orders with the synchronization flag set to unsynchronized to accurately locate the data that needs to be reported, ensuring that no unsynchronized orders are missed and no synchronized orders are reported repeatedly. After all fields are written, the main payment thread commits the database transaction. If the transaction commits successfully, the local payment order bound to the corresponding business order number is officially obtained; if the transaction commit fails, it is automatically rolled back, leaving no invalid data and ensuring the cleanliness and reliability of the local database.
[0040] As one implementation method, the steps of polling and querying orders by a background worker thread according to an adaptive backoff strategy specifically include: The background worker thread first parses the exception type returned by the upstream channel. If it is a channel processing exception, the initial order query interval is set to 1 second. If it is a network timeout or HTTP exception, the initial order query interval is set to 2 seconds. After each order query failure, the polling interval is multiplied by the backoff coefficient according to the exponential backoff rule and a random jitter value is added to avoid the channel request impact caused by multiple orders querying at the same time. When the cumulative number of order queries reaches the maximum number threshold or the duration reaches the safe termination threshold, automatic polling is stopped and the payment order is marked as pending confirmation. The payment is kept in the payment in progress state throughout the process and is not directly judged as payment failure, so as to avoid the risk of financial loss when the channel has deducted the payment but the system misjudged the failure.
[0041] In the above steps, after the background worker thread receives the order query task, it first parses the exception type returned by the upstream channel to determine the initial interval for the first round of order queries. There are two types of exceptions here. One type is processing exceptions at the channel business level, i.e., responses from the upstream payment channel that explicitly return "payment processing in progress," "user awaiting password input," or "transaction awaiting confirmation," indicating a clear intermediate business state. These exceptions mean that the payment request has successfully reached the upstream system, but the final payment result has not yet been generated, and the certainty of the result confirmation is relatively high. Therefore, the initial order query interval is set to 1 second to obtain the final payment status as quickly as possible with a shorter interval, reducing user waiting time. The other type is network-level exceptions, including request timeouts, HTTP connection failures, network interruptions, and other scenarios where it is impossible to confirm whether the request has reached the upstream channel. These exceptions are usually accompanied by overall fluctuations in the store's network, and repeated requests within a short period are likely to still fail. Therefore, the initial order query interval is set to 2 seconds to appropriately lengthen the initial query period and avoid frequently initiating invalid requests during network jitter periods, which would exacerbate network load and channel pressure. The core purpose of delegating the order inquiry task to background worker threads in an asynchronous thread pool is to decouple the main payment process from the order inquiry process. The main payment thread can release resources after updating the status and submitting the task, and continue responding to subsequent operations on the POS terminal. This prevents continuous polling from blocking front-end interactions, ensuring the smooth operation of the POS terminal and adapting to scenarios where the POS terminal prioritizes front-end business responsiveness. Since the payment order is atomically written to a local lightweight database via row-level transactions, the payment status has a persistent storage medium. This allows the background worker threads to independently perform polling and continuously update the status. Even if the main payment thread is released or the terminal program restarts, the intermediate state of the payment order will not be lost, and the order inquiry process can continue based on local records.
[0042] Each time a query request fails to obtain the final payment status, the background worker thread adjusts the query interval for the next round according to an exponential backoff rule. The specific steps are as follows: using the previous round's query interval as a baseline, multiplying it by a preset backoff coefficient to obtain the base interval, and then adding a small range of random fluctuations as the actual waiting time for the next round of querying. The core logic of the exponential backoff rule is that as the number of failed queries increases, the query interval gradually lengthens; the more failures, the lower the query frequency. The rationale for this design is that consecutive query failures usually indicate abnormal channel status or persistently poor store network performance. High-frequency retries in a short period not only make it difficult to obtain results but also continuously consume terminal network and thread resources. Simultaneously, sending a large number of requests to the upstream channel may trigger the channel's rate-limiting protection mechanism, further prolonging the status confirmation time. Through exponentially increasing interval adjustments, the system can adaptively match the duration of the anomaly. In the early stages of an anomaly, a higher query frequency is maintained to ensure response speed; as the anomaly persists, the frequency is automatically reduced to minimize unnecessary overhead, achieving a dynamic balance between query efficiency and system load. By adding random jitter to the backoff calculation, the problem of concentrated traffic when multiple orders are simultaneously queryed can be solved: If a batch of network anomalies occur in offline stores, multiple payment orders will enter the polling state simultaneously. If a fixed backoff interval is used for all of them, periodic request peaks will be formed, causing concentrated impact on the upstream payment channel. Random jitter adds random offsets in positive and negative directions to the basic interval, which disperses the query requests of each order in the time dimension, avoids the thundering herd effect of synchronous retries, smooths the overall request traffic, and reduces the risk of rate limiting on the channel side. This adaptive adjustment mechanism is executed entirely within the local plugin and can dynamically adapt to the actual anomaly of each order to fit the complex network environment of offline payments.
[0043] When the cumulative number of order queries reaches the preset maximum threshold, or the polling duration reaches the preset safety termination threshold, the background worker thread stops automatically polling for orders, marks the corresponding local payment order as pending confirmation, and maintains the payment order in a "payment in progress" state throughout the process, never directly determining it as a payment failure. The purpose of setting dual safety termination thresholds is to prevent abnormal orders from occupying background thread resources and database connections for extended periods: the terminal's asynchronous thread pool capacity and local database concurrency capabilities are limited. If an order remains in a polling state indefinitely, it will continuously consume system resources, affecting the processing efficiency of subsequent normal payments. Through termination control in both the number of queries and duration, thread and connection resources can be automatically released after a reasonable confirmation period, ensuring the overall system's operational stability. Maintaining the payment in progress state throughout the process and not directly determining failure is the core conservative state machine rule of this step, and also the core guarantee of zero tolerance for financial losses: in offline payment scenarios, all uncertain results may include the possibility that the channel has already deducted funds. If the system rashly determines failure, it is very easy for the user to actually pay successfully, but the cashier displays a failure, leading to duplicate payments, financial disputes, and customer complaints. Therefore, if payment failure cannot be 100% confirmed, the intermediate payment status is retained, and the final confirmation is delegated to subsequent manual verification or batch compensation processes after network recovery. This eliminates the risk of financial loss due to misjudgment at the root of the problem. This method can be implemented through manual order reconfirmation or by the server proactively checking and completing the status during the batch compensation reporting process, always preserving the possibility of status traceability and correction.
[0044] As one implementation method, the steps for calculating reporting priority based on order amount, payment duration, and network quality specifically include: The background scheduling thread scans the local database at fixed intervals for payment orders marked as unsynchronized, and groups all unsynchronized orders by store identifier. For each store group, a reporting priority value is calculated, with the transaction amount accounting for 50%, the time elapsed since payment completion accounting for 30%, and the network quality score converted from the success rate of the last three reports accounting for 20%. Based on the priority value, stores are divided into high, medium, and low levels. High-priority stores are allocated 2 concurrent worker threads with a batch capacity of 20 transactions, medium-priority stores are allocated 1 worker thread with a batch capacity of 50 transactions, and low-priority stores are merged for reporting with a batch capacity of 100 transactions. The batch capacity and number of concurrent threads are dynamically adjusted based on real-time network quality to adapt to scenarios with fluctuating network conditions.
[0045] In the above steps, the background scheduling thread scans all payment orders marked as unsynchronized in the local lightweight database according to a preset fixed period. After data retrieval, all unsynchronized orders are first grouped by store identifier. The fixed-period scanning, rather than real-time triggering, is used to avoid excessive terminal resource consumption from frequent database scans. The scanning period can be flexibly configured according to the store's business volume, controlling system overhead while ensuring timely compensation. Grouping by store identifier has the following advantages: First, it echoes the server-side routing rules for payment orders by store dimension. After orders from the same store are reported centrally, the server can directly route them to the corresponding sub-table for processing, reducing the computational overhead of cross-table routing and improving server-side processing efficiency. Second, the network status of offline stores is usually presented holistically on a store-by-store basis. Orders from the same store face a basically consistent network environment. Grouping by store facilitates unified assessment of network quality and allocation of reporting resources, avoiding continuous failures caused by scattered reporting when a single store has a poor network. Because each payment order has a clear synchronization status flag, the background scheduling thread can accurately filter out all orders to be compensated through simple conditional queries, without the need to maintain an additional independent compensation queue, and there will be no cases of missed or duplicate reports.
[0046] After grouping stores, the backend scheduling thread calculates the reporting priority value for each store group, using a weighted summation method that integrates three dimensions of indicators: transaction amount (50%), time elapsed since payment completion (30%), and network quality score converted from the success rate of the last three reports (20%). The transaction amount dimension uses the transaction amount of orders within the group for calculation. Since orders with higher transaction amounts have higher requirements for reconciliation timeliness and greater financial risk exposure, prioritizing their reporting can shorten the local retention time of large orders, reduce the risk of data loss or reconciliation anomalies, and align with the zero-tolerance scenario constraints of offline cashier losses. The time elapsed since payment completion is the time span from the payment order being updated to its final state to the current moment. Orders with longer time elapsed have higher priority. Assigning a second-highest weight ensures fairness in order compensation, prevents new orders from continuously jumping the queue and causing historical orders to remain unsynchronized for extended periods, and prevents the gradual accumulation of unsynchronized early orders leading to data backlog. The network quality score is calculated based on the success rate of the store's last three reporting requests. The higher the reporting success rate, the higher the network quality score, which means that the network connectivity between the store and the server is better. The 20% weighting is to tilt the reporting resources towards stores with better network conditions, reduce reporting failures and retries caused by poor network conditions, and improve the overall compensation efficiency.
[0047] After calculating the priority value of each store shard, all store shards are divided into three priority levels: high, medium, and low. Different numbers of concurrent threads and batch capacities are assigned to each level. High-priority shards are allocated two concurrent worker threads with a batch reporting capacity of 20 transactions. This ensures high-value orders can be quickly synchronized through more threads and smaller batch granularity, reducing the synchronization latency of critical data. Medium-priority shards are allocated one worker thread with a batch capacity of 50 transactions. This balances synchronization efficiency with resource consumption, suitable for regular orders of average volume. Low-priority shards merge orders from multiple stores for unified reporting, increasing the batch capacity to 100 transactions. This batch merging reduces the number of HTTP requests, lowers network interaction overhead, and accommodates the backup synchronization needs of non-core orders. Meanwhile, the entire reporting process dynamically adjusts batch size and concurrent thread count based on real-time network quality. When consecutive reporting failures occur, the number of concurrent threads and batch size are automatically reduced to avoid overburdening the network. When the network recovers and the reporting success rate rebounds, the number of threads and batch size are gradually restored, achieving dynamic adaptation between the reporting strategy and the network environment. Since the asynchronous thread pool capacity and uplink network bandwidth of the POS terminal are limited, they cannot support simultaneous concurrent reporting of all unsynchronized orders. Using an average resource allocation approach would lead to delayed synchronization of important orders and could also trigger network congestion due to excessive concurrency. By prioritizing and matching resources, overall compensation efficiency and business value can be maximized within the constraints of limited terminal resources.
[0048] As one implementation method, the steps of performing dual idempotent checks on distributed locks and database existence based on payment order numbers specifically include: A distributed lock key is constructed by concatenating the store identifier and the payment order number. The lock expiration time is dynamically calculated based on the current number of concurrent consumer threads and the message queue backlog. The default lock duration is 300 seconds, which is reduced to 120 seconds when the message backlog exceeds the warning threshold. The RedisSETNX command is executed to request a distributed exclusive lock. After the lock is successfully acquired, the payment migration table is queried according to the store-level table routing rules to verify whether the payment order number already exists. When the number of concurrent consumer threads exceeds the limit or the message backlog reaches the degradation threshold, the distributed lock verification is automatically skipped, and the unique key constraint of the payment order number in the payment table is used to complete the fallback idempotency verification. This ensures that data is not written repeatedly while also taking into account the processing throughput under high load scenarios.
[0049] In the above steps, a distributed lock key value is constructed by concatenating the store identifier and the payment order number. The lock expiration time is dynamically calculated based on the current number of concurrent consumer threads and the message queue backlog. Constructing the lock key using a combination of the store identifier and the payment order number satisfies the server-side payment order's table partitioning routing rules at the store level. The store identifier naturally carries partitioning routing information; concatenating it with the payment order number ensures both global uniqueness of the lock granularity and allows direct parsing of the corresponding table partitioning location through the key value, reducing the overhead of subsequent database queries. Fixed-length locks exacerbate lock contention and thread blocking under high load, while fixed-short locks may expire prematurely due to transaction timeouts under low load. Dynamic durations, however, adapt to changes in system load, achieving a dynamic balance between concurrency safety and processing efficiency. This is particularly suitable for offline POS scenarios, where pulse-like traffic fluctuations occur after network recovery and batch compensation reporting. Therefore, the lock expiration time is dynamically calculated, with a default setting of 300 seconds. This duration covers the complete transaction cycle of payment order entry and related data writing under normal load, preventing premature lock release from causing subsequent concurrent threads to enter and resulting in duplicate writes, thus ensuring the rigor of idempotent control. When the message backlog in the message queue exceeds the preset warning threshold, the lock duration is automatically reduced to 120 seconds, shortening the holding period of the lock resource by a single thread, accelerating the overall turnover speed of the lock resource, reducing the blocking waiting time of consumer threads, and alleviating the pressure of continuous message backlog.
[0050] The Redis SETNX command is executed to acquire a distributed exclusive lock. After successful lock acquisition, the payment migration table is queried according to the store-level table routing rules to verify whether the payment order number already exists, forming a second layer of data fallback verification. The two layers of verification in the dual idempotency mechanism serve different protective functions: The first layer, the distributed lock, is a deduplication prevention control at the concurrency entry point. Utilizing the atomicity of the Redis SETNX command, it ensures that only one consumer thread can successfully acquire the lock and process the same payment order at a time, intercepting concurrent duplicate requests at the request entry point and preventing a large number of concurrent writes from directly penetrating to the database layer, causing numerous write conflicts, database performance degradation, or even a cascading failure. The SETNX command is chosen to implement the distributed lock precisely because its native atomicity guarantees the uniqueness of lock acquisitions in multi-threaded concurrent scenarios, preventing race conditions where multiple threads acquire the lock simultaneously. The second layer, database existence verification, is a fallback protection at the data persistence level. For extreme abnormal scenarios such as Redis node failure, unexpected lock expiration, and duplicate message delivery, the payment migration table is queried to confirm whether the payment order has been entered into the database from the data source, completely eliminating the generation of duplicate data. The choice of using the payment migration table instead of directly traversing all payment shards for deduplication is precisely to adapt to the performance requirements of the sharded architecture: without a unified lightweight index table, cross-shard deduplication requires traversing all shards, and the performance overhead increases linearly with the number of shards; while the payment migration table, as a simplified index of all payment orders, combined with the sharding routing rules at the store level, can quickly locate the target shard and complete the verification, significantly reducing the pressure on the database from the deduplication operation. These two layers of verification complement each other and progress progressively: the distributed lock handles entry point interception in daily high-concurrency scenarios, while the database verification provides a safety net for extreme abnormal scenarios, jointly ensuring the absolute uniqueness of payment order data under multiple entry points and high concurrency.
[0051] When the number of concurrent consumer threads exceeds the preset limit or the message backlog reaches the degradation threshold, the distributed lock verification is automatically skipped, and the unique key constraint of the payment order number in the payment sub-table is used to complete the fallback idempotency verification, achieving elastic degradation under high load scenarios. Under normal business load, dual verification can achieve strict zero duplicate writes without significantly impacting overall processing performance; however, when the system faces a concentrated traffic peak, the contention for distributed locks becomes a system performance bottleneck, with a large number of consumer threads blocked waiting for lock resources, leading to a decrease in overall consumption efficiency, further exacerbating message backlog, and even affecting the processing time of normal transactions. The payment sub-table itself has set the payment order number as a unique key, and the unique key constraint at the database level naturally has anti-duplicate capabilities. Although a small number of write conflict errors may occur after degradation, the database level can physically guarantee that the data is not duplicated, and after eliminating the overhead of lock contention, the overall consumption throughput will be significantly improved, making it more suitable for high-load, fast consumption scenarios.
[0052] As one implementation method, the steps for synchronously generating a two-way mapping relationship between payment order numbers and corresponding business order numbers specifically include: Within the same database transaction where payment orders are entered, a hash operation is performed on the payment order number, and then modulo 10 is taken to obtain the routing suffix for the payment and business mapping sub-tables; a hash operation is performed on the business order number, and then modulo 10 is taken to obtain the routing suffix for the business and payment mapping sub-tables; associated records containing payment order number, business order number, business type, and extended information are written to the payment and business mapping sub-tables, and simultaneously, reverse associated records containing business order number and payment order number are written to the business and payment mapping sub-tables; the bidirectional mapping relationship takes effect simultaneously after the transaction is successfully committed, and is rolled back along with the payment order records if the transaction fails, establishing a cross-dimensional bidirectional query link between the payment sub-table and the business order sub-table.
[0053] In the above steps, the generation of the bidirectional mapping relationship is performed entirely within the same database transaction for payment order entry. Binding the mapping write and payment order entry to the same transaction leverages the atomicity of database transactions, ensuring that the payment order record and the mapping relationship can only be written successfully or rolled back unsuccessfully simultaneously. This avoids the incomplete state of a payment order being entered but the mapping missing, or a mapping being generated but the payment order writing failing, thus preventing data silos. These steps work in conjunction with double idempotency checks. Double idempotency ensures that the same payment order is processed only once at the request entry level, while transaction atomicity ensures strict synchronization of the payment order and mapping states at the data persistence level. This ensures that every successfully entered payment order corresponds to a complete and valid bidirectional mapping relationship, preventing any gaps in the relationship. If the design deviates from the shared transaction, separating the mapping write and payment order entry into two independent operations, a program exception or database failure could result in inconsistent, corrupted data. Subsequent queries might encounter issues such as a payment order existing but no corresponding order found, or an order existing but no payment record found.
[0054] Performing a hash operation on the payment order number and then taking the modulo of 10 yields the routing suffix for the payment-to-business direction mapping table, which is the core guarantee for forward query performance. The hash operation in this application has the characteristic of uniform dispersion, which can evenly distribute the globally unique payment order number across 10 tables, avoiding the performance degradation caused by the continuous expansion of data volume in a single table. At the same time, setting the number of tables to 10 balances data dispersion and operational complexity, supporting the storage needs of large-scale payment data without increasing operational and query costs due to an excessive number of tables. When the business process needs to look up the corresponding business order using the payment order number, if the mapping table is sharded according to the store dimension along with the payment order, the store to which the payment order belongs must be known to locate the shard. However, in most reverse lookup scenarios, only the payment order number is available, and store information cannot be directly obtained. The entire shard must be traversed for a query, and the performance overhead increases linearly with the number of tables. By hashing the payment order number, a single hash modulo operation is performed on the payment order number to directly locate the unique target mapping table. A single query can retrieve the associated business order information, completely avoiding the overhead of cross-table traversal.
[0055] After performing a hash operation on the business order number and taking the modulo of 10, the routing suffix of the business-to-payment mapping table is obtained, which is a targeted optimization for reverse query scenarios. Consistent with the design logic of forward queries, the reverse mapping table is hash-partitioned based on the business order number. When it is necessary to query all payment records associated with a business order number, simply perform a hash modulo operation based on the business order number to quickly locate the corresponding partition and obtain the association information of all payment orders under that order at once, including multiple records such as normal payments, refunds, and retry payments, adapting to business scenarios where one business order corresponds to multiple payment orders. If only a one-way payment-to-business mapping table is set up, reverse queries would require traversing all mapping partitions and matching and filtering by the business order number field. In scenarios with large data volumes, the query efficiency is extremely low, failing to meet the business needs of high-frequency order retrieval and reconciliation at offline cashiers. The two mapping tables are partitioned based on their respective query primary keys, and independent index shards are built for queries in both directions, enabling bidirectional queries to achieve the performance level of single-table queries and solving the performance problem of bidirectional join queries under cross-dimensional partitioning.
[0056] After completing the table partitioning and routing calculation, inverse association records are simultaneously written to the two mapping partitions, fully covering the data requirements of both types of queries. The payment-to-business mapping partition is written with a complete association record containing payment order number, business order number, business type, and extended information. Besides the core order number association, it also carries business type identifiers and extended attributes to distinguish payment associations in different business scenarios, supporting subsequent multi-business domain payment association queries. The business-to-payment mapping partition is written with a simplified reverse association record containing business order number and payment order number, enabling one-to-many association indexing capabilities while controlling storage overhead while ensuring query performance. The simultaneous writing of these two records ensures that queries in either direction can directly hit the corresponding partition without secondary redirection, supporting both reverse order lookups on the payment side and payment aggregation on the order side, adapting to query needs across different stages of the entire process.
[0057] Upon successful transaction commit, the bidirectional mapping relationship takes effect simultaneously. If the transaction fails, both mapping records are rolled back along with the payment order record, maintaining strict consistency in data state throughout the process. This setup ensures the mapping relationship is entirely dependent on the payment order's lifecycle; if the payment order exists, the mapping must exist; if the payment order is canceled, the mapping expires synchronously, preventing residual invalid associated data and the abnormal state of mapping preceding the payment order. Because the bidirectional mapping is reliable and complete, the payment and order chains can be completely decoupled and reported independently and asynchronously. Each chain can complete its own data entry without waiting for the other's data to arrive, ultimately achieving association and matching through the mapping relationship.
[0058] As one implementation method, the method also includes a dual-link order detail writing step, specifically including: Upon receiving business order details data uploaded from the POS terminal, the system first verifies the integrity of the order master information and product details fields. It then requests a distributed concurrent lock using a combination of order number, store identifier, and company identifier as the key. After acquiring the lock, it executes the old order table write link: deleting records of the same order number from the master table, product table, and payment table in the existing database, and then rewriting the complete order master data, product details, and payment details, ensuring compatibility with existing reports and reconciliation functions. Simultaneously, it executes the new order partition table write link: calling the new order domain synchronization interface through a service proxy, routing to the corresponding new partition table by modulo the company identifier, and writing to the order master table, product table, and payment table. The payment order link and order detail link are decoupled and reported independently and asynchronously. A bidirectional mapping relationship is used to complete the association and matching of payment data and order data, achieving eventual consistency between payment and order data during the migration cycle between the old and new partition tables.
[0059] In the above steps, after receiving the business order details data uploaded by the POS terminal, the first step is to perform a field integrity check on the order master information and product details. Business order details typically contain multiple levels of information, including order master data, product details data, and payment settlement data. Missing fields will cause errors in subsequent business functions such as report statistics, financial reconciliation, and operational analysis. After successful verification, a distributed concurrent lock is applied for using a combination of the order number, store identifier, and company identifier as the key to control concurrent write permissions for the same order. A three-dimensional key combination is used to construct the lock key: the order number is a unique identifier for a single order, the store identifier corresponds to the business dimension of the offline store, and the company identifier corresponds to the entity management dimension, ensuring that only one processing thread can write the order data at any given time. This setup can adapt to scenarios with multi-threaded concurrent processing on the server side, avoiding concurrency issues such as data overwriting, duplicate writing, and detail corruption caused by repeated uploads, retrying reports, and simultaneous processing by multiple links for the same order. This provides a fundamental guarantee for data accuracy for subsequent dual-link writes.
[0060] After acquiring the distributed concurrent lock, the old order table write process is executed first. Specifically, it adopts a processing mode of first deleting existing orders with the same number, and then rewriting the full data. This involves sequentially deleting the corresponding order's master table record, product table record, and payment table record in the old database, and then completely writing the order master data, all product details, and payment details of the uploaded order. Using a delete-then-write mode instead of incremental updates can adapt to the complex table structure and business logic of the existing system: offline POS order data contains complex structures such as multi-level details, multi-dimensional discounts, and multiple payment method combinations. If field-level incremental updates are used, data differences need to be compared one by one and corresponding updates need to be executed, resulting in high logical complexity and a high risk of missing field updates or errors in adding or deleting detail rows. The delete-then-write mode, however, ensures that the data written each time is complete and consistent by covering the entire data. The processing logic is simple and reliable, and it can maximize compatibility with all business rules of the existing system. The old order table is the data source for all existing functions such as reports, reconciliation, business analysis, and membership accounting. It ensures the integrity and accuracy of the old table data so that all existing business functions can run normally during the migration period. This avoids disabling the old system and switching business entry points. Frontline cashiers and operations staff will not be aware of the architectural changes at all, achieving a smooth migration without the business being aware of it. This adapts to the rigid constraint that the iteration of existing systems cannot be switched off in a one-size-fits-all manner.
[0061] While executing the old order table write process, the new order shard write process is simultaneously initiated. The service proxy calls the synchronization interface of the new order domain to complete the order data write under the new architecture. The service proxy layer decouples the upstream upload entry point from the underlying shard architecture. The POS terminal only needs to upload order data in a unified format, without needing to be aware of the underlying sharding rules, number of shards, and node distribution. This avoids modifying the POS terminal's upload logic when the new shard architecture is expanded or routing rules are adjusted, thus reducing the coupling cost of architecture iteration. The new order shard uses a routing rule based on the company identifier modulo. Modulo calculation is performed based on the company entity number to which the order belongs to locate the corresponding new shard node, and then the data is written sequentially to the order main table, product table, and payment table. Order statistics, financial accounting, and operational analysis for offline chain stores are typically based on company entities. Sharding by company dimension allows most business queries to fall directly within a single shard, avoiding the performance loss of cross-table queries and significantly improving the efficiency of order queries and statistics under the new architecture. The parallel execution of two write links allows the POS terminal to perform only one upload action, and the server will automatically complete the data persistence of the two systems. This does not increase the reporting burden on the terminal or extend the overall processing time, and the synchronization and construction of the old and new data sets are completed without the front end being aware of it.
[0062] The payment order process and order details process are decoupled and reported independently and asynchronously. Each process has its own independent reporting entry point, processing flow, and storage system, with no strict sequential dependency. Payment data can be entered into the database first, followed by order data, or order data can be written first, followed by payment data synchronization, resulting in complete decoupling in timing. Data association and matching between the two processes are entirely based on the aforementioned bidirectional mapping relationship: when a payment order is entered into the database, a bidirectional mapping between the payment order number and the business order number is generated synchronously; when order details are entered into the database, the corresponding business order number is also bound. Once both sets of data are stored, the mapping relationship automatically associates and matches payment data with order data, forming a complete end-to-end view of the business order. This decoupling design, deeply integrated with the bidirectional mapping feature, produces multiple technical benefits: First, it naturally adapts to the fast-paced nature of offline payment and slow-paced order processing. Local payment plugins typically confirm payment results within seconds, while order details contain multi-dimensional information such as products, discounts, inventory, and membership details, making assembly and uploading time-consuming. With a tightly coupled architecture, the payment process must wait for the order to be written before returning a result, significantly lengthening payment wait times and impacting checkout efficiency. After decoupling, the payment chain can independently complete all processes and quickly return results. Order data is automatically associated after subsequent synchronization, ensuring checkout speed while avoiding the user experience issue of successful payment but no order information. Second, it supports the smooth migration of the order system. Because the payment and order chains are decoupled, the payment chain reduces modification risks throughout the entire migration cycle from the old table to the new partitioned table. Regardless of whether order data is written to the old table or the new partitioned table, the payment chain completes the association through a unified bidirectional mapping, unaffected by the migration progress. This significantly reduces the complexity and risk of the overall architecture migration, avoiding the financial losses that might arise from the simultaneous modification of the payment system and the order system. Third, it enhances the independent evolution capability of the two links. The functional iteration of the payment side and the architectural upgrade of the order side can be promoted separately without interference, which is more suitable for the business needs of continuous iteration of offline POS systems.
[0063] As one implementation method, the steps for constructing a thread-safe hotspot mapping cache specifically include: The system periodically tracks the query frequency of each payment order number and business order number in the two mapping tables, marking mappings with query counts exceeding a hotspot threshold within a continuous statistical period as hotspot mappings. During off-peak business hours, the routing results of hotspot mappings and core related fields are preloaded into a thread-safe distributed cache layer, with a cache expiration time set and active invalidation supported. When multiple threads concurrently query mapping relationships, the cache is queried first to obtain the routing results, directly locating the target table. If the cache misses, hash table calculation is performed, and the calculation result is written back to the cache. When the mapping relationship changes, cache invalidation is triggered synchronously to ensure consistency between cached data and table data, improve the response speed of bidirectional queries across tables, and support efficient convergence of payment data and business order data.
[0064] Periodically analyzing the query frequency of each payment order number and business order number in the two mapping tables is a prerequisite for identifying hot data and achieving accurate caching. While bidirectional hash partitioning solves the query path problem of cross-dimensional associations at the architectural level, each association query requires hashing, modulo operations, and table routing for the order number. In multi-threaded, high-concurrency scenarios such as reconciliation, refunds, and order queries, repeated routing calculations continuously consume server-side computing resources. The above steps employ a periodic statistical approach, asynchronously collecting all query request logs from both mapping tables, aggregating query counts by payment order number and business order number respectively. The statistical period can be flexibly configured based on business traffic characteristics. After the statistics are completed, mapping relationships where the number of queries exceeds a preset hot data threshold for multiple consecutive statistical periods are marked as hot data mappings, completing the hierarchical identification of hot and cold data. Setting rules for continuous periodicity can avoid misjudgments caused by sudden surges in traffic. For example, multiple queries for a single order within a short period do not necessarily indicate long-term high frequency; only data with consistently high access volume has caching value. Hotspot thresholds can be dynamically adjusted based on overall cache capacity. When cache resources are sufficient, the threshold is lowered to expand hotspot coverage; when resources are scarce, the threshold is raised to focus on core high-frequency data. This ensures that limited cache resources prioritize serving the most frequent query scenarios, achieving the optimal balance between resource investment and performance gains. All of the above processes are executed asynchronously, without intruding on the normal main query chain, and without increasing the response latency of business queries, thus completing the identification and updating of hotspot data.
[0065] Preloading the routing results of hotspot mappings and core related fields into a thread-safe distributed cache layer during off-peak hours is a core design feature to ensure query performance during peak hours. Offline POS scenarios exhibit significant traffic fluctuations: query requests are concentrated and system load is high during daytime business hours, while access volume is extremely low and system resources are abundant during off-peak hours such as the early morning. Therefore, performing batch preloading during off-peak hours avoids consuming system resources during peak hours and allows for cache warm-up of hotspot data before the next day's traffic peak, preventing large-scale cache penetration and concentrated origin pulls during peak hours. The preloaded content is not the full range of fields in the mapped records, but rather streamlined core information: on one hand, it includes the routing results of the corresponding table for payment and business order numbers, allowing direct retrieval of the target table location during queries, skipping the hash modulo calculation process; on the other hand, it includes frequently queried core fields such as business type and association status, allowing some simple association checks to be returned directly from the cache without accessing the database, further reducing database access pressure. The caching layer employs a thread-safe distributed cache implementation, natively supporting multi-threaded concurrent read and write operations. It features atomic read and write operations, preventing concurrency issues such as dirty reads and write overwriting that can occur when multiple threads access the same cached data simultaneously, thus adapting to the server-side environment of multi-threaded concurrent queries. Furthermore, it sets expiration times for cached data, using an automatic expiration mechanism to naturally evict infrequently accessed data and prevent long-term inaccessible data from continuously occupying cache resources, serving as a fallback mechanism for dynamically updating frequently accessed data.
[0066] When multiple threads concurrently query mapping relationships, a bypass caching strategy is employed, prioritizing caching, completing the query from the source, and writing back the result. When a query request arrives, the distributed cache layer is accessed first to attempt to obtain the corresponding order number's table routing and core association information. If the cache is hit, the route result in the cache is used directly to locate the target table, eliminating the need for hash calculations and table partitioning. A single query can complete the association location, significantly shortening the response chain. If the cache is missed, the process falls back to the basic hash table partitioning calculation logic. A hash modulo operation is performed on the queried order number to obtain the target table route, and then the corresponding mapping table is accessed to obtain the complete association data. After the query is completed, the table routing result obtained in this calculation is written back to the cache layer with a short initial expiration time. This setup achieves extreme performance for hot queries while also ensuring fault tolerance for cold data queries. While cold data may not be cached on the first query, it is automatically written to the cache. Subsequent accesses will gradually increase its frequency, bringing it into the hotspot statistics and eventually making it pre-loaded long-term hotspot data. If it is no longer accessed, it will be automatically evicted after a short expiration time, without occupying long-term cache resources. Both directions of mapping queries share the same cache read / write logic. Whether querying business orders using payment order numbers or aggregating payment records using business order numbers, both can benefit from caching acceleration, achieving a symmetrical performance improvement for bidirectional queries.
[0067] When the mapping relationship changes, cache invalidation is triggered synchronously. In normal business processes, the mapping relationship between payment orders and business orders usually remains unchanged after it is generated. However, in special scenarios such as order correction, payment cancellation and reopening, and abnormal data repair, the mapping relationship may be updated. If only the cache expiration time is relied upon as a fallback, inconsistencies may occur between cached data and database data within the expiration period. This could lead to incorrect results in join queries, affecting the accuracy of core business processes such as reconciliation and refunds. Therefore, when the mapping relationship is updated, within the same database transaction updating the mapping sub-table, a cache deletion instruction for the corresponding order number is simultaneously sent to the cache layer. After the transaction is successfully committed, the old cache immediately becomes invalid. Subsequent first queries for that order number will re-access the database, load the latest mapping relationship, and write back to the cache, ensuring that the cached data always remains consistent with the sub-table data. This transaction-bound active invalidation design strictly binds the cache state to the database state, with data changes and cache invalidation occurring simultaneously, thus preventing the generation of dirty cache data. The cache expiration time serves as a fallback guarantee in extreme scenarios. Even if the active invalidation command fails to execute due to network fluctuations or other reasons, the cache will be automatically replaced after expiration, ultimately achieving data consistency.
[0068] This application also includes a payment device for a payment method, comprising: an acquisition module, a calculation module, and an output module.
[0069] It should be understood that those skilled in the art can make improvements or modifications based on the above description, and all such improvements and modifications should fall within the protection scope of the appended claims.
Claims
1. A payment method, characterized in that, The local payment plugin runs on a multi-threaded architecture based on the main payment thread and an asynchronous thread pool to respond to payment code payment requests. Before calling the upstream payment channel, the main payment thread generates a payment order number and creates a payment order record to obtain the local payment order with the corresponding business order number. Based on the local payment order, a payment code payment is initiated to the corresponding upstream payment channel. If the upstream channel is abnormal, the local payment order is updated to the payment in progress state. At the same time, a query task is submitted to the asynchronous thread pool. The background worker thread polls the query task according to the adaptive backoff strategy until the final payment state is obtained or the safe termination threshold is reached, and the final state local payment order is obtained. For local payment orders that have been updated to the final state of paid or refunded and are marked as unsynchronized, a single asynchronous reporting thread is triggered through an asynchronous thread pool to synchronize payment data to the server. At the same time, the background scheduling thread obtains unsynchronized payment orders and segments them according to store identifiers. The reporting priority is calculated based on order amount, payment duration and network quality. Corresponding worker threads are assigned to each segment to perform tiered batch compensation reporting, so as to output payment order data to be entered into the database. The system adopts a multi-threaded concurrent consumption mode to receive reported payment order data, and performs dual idempotent checks on the existence of the payment order number using a distributed lock and the database. The lock expiration time and check granularity are dynamically adjusted according to the current number of concurrent threads and the amount of messages back up. In high-load scenarios, the system automatically degrades to a fallback check using a unique key in a sharded table. After the check passes, the data is written to the corresponding payment sharded table according to the sharded table routing rules at the store level, generating server-side payment order records stored in the sharded table. Based on the server-side payment record, a two-way mapping relationship between payment order number and corresponding business order number is generated synchronously. The mapping from payment to business is stored in a table with payment order number hash, and the mapping from business to payment is stored in a table with business order number hash. Then, a thread-safe hotspot mapping cache is built based on historical query frequency. Pre-routing loading is performed on high-frequency mappings to enable bidirectional fast queries across table dimensions, thereby enabling payment.
2. The payment method according to claim 1, characterized in that, The steps of generating a payment order number and creating a payment order record specifically include: The main payment thread establishes a thread-safe connection with the local lightweight database and generates a globally unique payment order number by concatenating the last six digits of the store identifier with a timestamp and a three-digit random number. A row-level transaction is initiated in the local database, and a payment order record containing the business order number, store identifier, transaction amount, payment method, payment status, and creation time is created using atomic write. The payment status is initialized to unpaid and the synchronization flag is set to unsynchronized. After the transaction is committed, a local payment order bound to the corresponding business order number is obtained, which serves as the unified data benchmark for subsequent payment execution, status polling, and compensation reporting.
3. The payment method according to claim 2, characterized in that, The specific steps of polling and checking orders by the background worker thread according to the adaptive backoff strategy include: The background worker thread first parses the exception type returned by the upstream channel. If it is a channel processing exception, the initial order query interval is set to 1 second. If it is a network timeout or HTTP exception, the initial order query interval is set to 2 seconds. After each order query failure, the polling interval is multiplied by the backoff coefficient according to the exponential backoff rule and a random jitter value is added to avoid the channel request impact caused by multiple orders querying at the same time. When the cumulative number of order queries reaches the maximum number threshold or the duration reaches the safe termination threshold, automatic polling is stopped and the payment order is marked as pending confirmation. The payment is kept in the payment in progress state throughout the process and is not directly judged as payment failure, so as to avoid the risk of financial loss when the channel has deducted the payment but the system misjudged the failure.
4. The payment method according to claim 3, characterized in that, The steps for calculating reporting priority based on order amount, payment duration, and network quality specifically include: The background scheduling thread scans the local database at fixed intervals for payment orders marked as unsynchronized, and groups all unsynchronized orders by store identifier. For each store group, a reporting priority value is calculated, with the transaction amount accounting for 50%, the time elapsed since payment completion accounting for 30%, and the network quality score converted from the success rate of the last three reports accounting for 20%. Based on the priority value, stores are divided into high, medium, and low levels. High-priority stores are allocated 2 concurrent worker threads with a batch capacity of 20 transactions, medium-priority stores are allocated 1 worker thread with a batch capacity of 50 transactions, and low-priority stores are merged for reporting with a batch capacity of 100 transactions. The batch capacity and number of concurrent threads are dynamically adjusted based on real-time network quality to adapt to scenarios with fluctuating network conditions.
5. The payment method according to claim 4, characterized in that, The steps of performing dual idempotent checks on distributed locks and database existence based on payment order numbers specifically include: A distributed lock key is constructed by concatenating the store identifier and the payment order number. The lock expiration time is dynamically calculated based on the current number of concurrent consumer threads and the message queue backlog. The default lock duration is 300 seconds, which is reduced to 120 seconds when the message backlog exceeds the warning threshold. The RedisSETNX command is executed to request a distributed exclusive lock. After the lock is successfully acquired, the payment migration table is queried according to the store-level table routing rules to verify whether the payment order number already exists. When the number of concurrent consumer threads exceeds the limit or the message backlog reaches the degradation threshold, the distributed lock verification is automatically skipped, and the unique key constraint of the payment order number in the payment table is used to complete the fallback idempotency verification. This ensures that data is not written repeatedly while also taking into account the processing throughput under high load scenarios.
6. The payment method according to claim 5, characterized in that, The steps for synchronously generating a two-way mapping relationship between payment order numbers and corresponding business order numbers specifically include: Within the same database transaction where payment orders are entered, a hash operation is performed on the payment order number, and then modulo 10 is taken to obtain the routing suffix for the payment and business mapping sub-tables; a hash operation is performed on the business order number, and then modulo 10 is taken to obtain the routing suffix for the business and payment mapping sub-tables; associated records containing payment order number, business order number, business type, and extended information are written to the payment and business mapping sub-tables, and simultaneously, reverse associated records containing business order number and payment order number are written to the business and payment mapping sub-tables; the bidirectional mapping relationship takes effect simultaneously after the transaction is successfully committed, and is rolled back along with the payment order records if the transaction fails, establishing a cross-dimensional bidirectional query link between the payment sub-table and the business order sub-table.
7. The payment method according to claim 1, characterized in that, It also includes a dual-link writing step for order details, specifically including: Upon receiving business order details data uploaded from the POS terminal, the system first verifies the integrity of the order master information and product details fields. It then requests a distributed concurrent lock using a combination of order number, store identifier, and company identifier as the key. After acquiring the lock, it executes the old order table write link: deleting records of the same order number from the master table, product table, and payment table in the existing database, and then rewriting the complete order master data, product details, and payment details, ensuring compatibility with existing reports and reconciliation functions. Simultaneously, it executes the new order partition table write link: calling the new order domain synchronization interface through a service proxy, routing to the corresponding new partition table by modulo the company identifier, and writing to the order master table, product table, and payment table. The payment order link and order detail link are decoupled and reported independently and asynchronously. A bidirectional mapping relationship is used to complete the association and matching of payment data and order data, achieving eventual consistency between payment and order data during the migration cycle between the old and new partition tables.
8. The payment method according to claim 6, characterized in that, The steps for constructing a thread-safe hotspot mapping cache specifically include: The system periodically tracks the query frequency of each payment order number and business order number in the two mapping tables, marking mappings with query counts exceeding a hotspot threshold within a continuous statistical period as hotspot mappings. During off-peak business hours, the routing results of hotspot mappings and core related fields are preloaded into a thread-safe distributed cache layer, with a cache expiration time set and active invalidation supported. When multiple threads concurrently query mapping relationships, the cache is queried first to obtain the routing results, directly locating the target table. If the cache misses, hash table calculation is performed, and the calculation result is written back to the cache. When the mapping relationship changes, cache invalidation is triggered synchronously to ensure consistency between cached data and table data, improve the response speed of bidirectional queries across tables, and support efficient convergence of payment data and business order data.
9. A payment device applied to the payment method of claims 1 to 8, characterized in that, include: The module consists of an acquisition module, a calculation module, and an output module.
10. An electronic device, characterized in that, The electronic device stores a computer program that, when executed, enables the payment method as described in any one of claims 1 to 8.