Some thoughts on the design of payment platform architecture

Some thoughts on the design of payment platform architecture

My first task in my previous company was to develop a unified payment platform. Due to the company's business needs, it was necessary to connect to multiple third-party payment platforms. Previously, the company's payments were scattered in various projects, which was not conducive to payment management. Therefore, the task of aggregating the third-party payments and unifying the payment platform fell on my hands. It can be said that I designed it completely from scratch. After some practical summaries, I came up with some thoughts on the architecture design. I have always wanted to write down my own architecture design ideas, but I never started. A few days ago, someone asked a related question in the technical group, and I think it is necessary to write it down to help more developers who need to develop payment platforms.

Component Mode

Since the company's business is in many regions, it needs to provide multiple payment methods to meet the development of the business. Therefore, the payment platform designed needs to access multiple third-party payment channels, such as: WeChat Pay, Alipay, PayPal, IPayLinks, etc. We all know that each third-party payment has its own set of external APIs, and the official has a set of SDKs to implement these APIs. How should we organize these APIs?

Since third-party payment channels will change with the development of the business, the organization of these SDKs needs to be flexibly pluggable without affecting the overall architecture of the payment platform. Here I use the idea of ​​components to split the payment API into various components, such as payment components, refund components, order components, billing components, etc., so that when a third-party payment SDK is introduced, the required API can be flexibly added to the component. The architecture design is as follows:

The Builder mode is used to build corresponding component objects according to request parameters, separate components from the outside, and hide the implementation of component construction. The component mode + Builder mode makes the payment platform highly scalable.

Multi-account system

When connecting to various third-party payment platforms, we encountered an account problem. The reason was that the company's mini-program and APP at the time used different WeChat accounts, so there would be a problem that WeChat payment would correspond to multiple accounts. When I designed the payment platform, I did not consider this problem. At that time, third-party payment only corresponded to one account, and different third-party payment accounts were independent and not unified.

So I introduced a multi-account system. One of the most important core concepts of the multi-account system is to use accounts as the granularity, connect to multiple third-party payment platforms, unify account parameters, and build a unified payment account system. The payment platform does not need to worry about the account differences between different payments or how many accounts a third-party payment platform has.

At this point I add the account layer to the payment platform architecture diagram:

The front end only needs to pass the accountId, and the payment platform can query the corresponding payment account based on the accountId, and then build the component object corresponding to the payment account through the Builder mode, completely shielding the differences between different payments. In the multi-account system, it can support multiple payment accounts, fully meeting the development needs of the company's business.

Unified callback and asynchronous dispatch processing

Students who have done payment development know that current third-party payments have a feature, that is, after the payment/refund is successful, there will be a payment/refund callback function, the purpose of which is to allow the merchant platform to verify whether the order is legal, for example: to prevent the client from maliciously tampering with the amount and other parameters during payment. Then, after the payment is successful, the order will be in the payment state and need to wait for the callback of the third-party payment. If the callback is received at this time, it is found during verification that the order amount and the payment amount are not the same, and then the order will be changed to payment failure to prevent capital loss. The idea of ​​the callback is to ensure the final consistency, so when we call the payment, we do not need to verify the correctness of the parameters at this time, we only need to verify them during the callback.

Now that we have discussed the purpose of callbacks, how do we design callbacks for payment platforms?

Since the payment platform is connected to multiple third-party payment platforms, if each third-party payment platform sets a callback address, there will be multiple callback addresses. Since the callback API must be exposed to accept third-party callback requests, there will be security issues. We must set up security filtering on the outer layer of the API, otherwise illegal and violent access will easily occur. Therefore, we need to unify the callback API, perform security verification in a unified manner, and then perform another layer of distribution.

I suggest using RocketMQ for the distribution mechanism. Some people may ask, if RocketMQ is used for distribution, how to return the verification results to the third-party payment in real time? This problem was also a headache for me at the time. Here are some of my thoughts on callback design:

The company's system is based on the SpringCloud microservice architecture. Microservices communicate with each other through HTTP. At that time, many microservices were connected to my payment platform. If HTTP was used for distribution, the real-time return of messages could be guaranteed. However, there would be a problem. Due to network instability, request failure or timeout would occur, and the stability of the interface could not be guaranteed.

If the third-party payment receives a false response, it will initiate a callback request again within a period of time. The purpose of doing this is to ensure the success rate of the callback. For the third-party payment, this is fine, but for the merchant payment platform, it may be a rather tricky design. Think about it, suppose an order is maliciously tampered with the amount during payment, the callback verification fails, and false is returned to the third-party payment. At this time, the third-party payment will repeatedly send the callback. No matter how many times the callback is sent, the verification will fail, which adds unnecessary interactions. Of course, idempotence can also be used here. The following is an application scenario description of WeChat payment callback:

Based on the above two considerations, I think it is unnecessary to return false to the third-party payment. For the robustness of the system, I use message queues for asynchronous distribution. The payment platform directly returns true after receiving the callback request. At this time, you may ask a question. If the verification fails at this time, but true is returned at this time, will there be a problem? First of all, if the verification fails, the order must be in a state of payment failure. The purpose of returning true at this time is to reduce unnecessary remote interactions with third-party payment.

Because RocketMQ messages are persisted to disk, the biggest advantage of using message queues for asynchronous distribution is that you can review the messages in the message queue to troubleshoot problems, and the message queue can also reduce traffic peaks during business peaks.

The following is a unified callback and dispatch processing architecture design diagram:

Aggregate payment

The payment platform aggregates a variety of third-party payments, so a lot of adaptation work needs to be done at the request layer to meet the needs of multiple payments. You may think, why not just add a few lines of if else in the adaptation? This is fine and can also meet the needs of multiple payments, but have you ever thought about what you would do if you add another third-party payment at this time? You can only add multiple else conditions to the original method, which will cause the request layer code to constantly change with the development of the business, making the code extremely inelegant and difficult to maintain. At this time, we have to use the strategy pattern to eliminate these if else codes. When we add a third-party payment, we only need to create a new Strategy class. You can take a look at the Dahua Design Pattern to see how to use the strategy pattern.

Therefore, I added an extra payment strategy layer before the Builder mode:

Request processing

Since the payment platform involves funds, various payment requests and returns, as well as exception records are extremely important in a payment platform, we need to record each payment request record for subsequent troubleshooting.

Based on this requirement, I designed a Handler layer before I started to request third-party payment. All requests must be processed by the Handler layer. The core methods of the Handler are as follows:

In principle, the Handler layer I designed uses the template mode, which can not only realize log recording, but also realize multiple processing methods, such as request monitoring, message push, etc., realizing the high scalability of the Handler layer.

The following is the architectural design diagram of the Handler layer:

Written in ***

The above is my payment platform architecture design idea. In summary, the payment platform needs to be scalable, stable, and highly available. Therefore, I used a lot of design patterns and introduced message queues to handle callback distribution issues when designing the payment platform, so that the payment platform has these characteristics. I hope it can give you some inspiration and help. I will post the overall architecture design diagram of the payment platform:

<<:  Foreign media revealed that Huawei's backup operating system is actually Aurora OS: developed based on Sailfish OS and compatible with Android

>>:  It is reported online that Huawei may adopt the Jiguang mobile phone operating system? Netizens: Where is its own Hongmeng?

Recommend

Facebook launches virtual robot assistant 'M'

According to foreign media reports, Facebook has ...

Tonghua SEO training: how to statistically analyze website ranking data

Most of the monitoring of website ranking data is...

Android M tries to get more AOSP apps into the Play Store

Google released a technical preview of the next v...

Double Eleven advertising farce: a bite and a bite back

As Double Eleven approaches, major e-commerce com...

Huawei AppGallery keyword search bidding advertising is now online!

Huawei AppGallery launched the "Search Keywo...

2019 Advertising Monetization Insights Report (Part 1)

As 2020 approaches, many media have begun plannin...

What is that thing tied to the bird's leg?

Bird migration has always been an important topic...

Letting your child become a "conspicuous bag" actually has such benefits?

Review expert: Chen Mingxin, national second-leve...

Will live streaming sales end sooner or later?

It is undeniable that live streaming with goods h...

Do barnacles and lice make whales itchy? How do whales scratch themselves?

Let’s talk about the second form first. Scratchin...