preface

As an important business, wechat Pay faces various problems on the client side. The core of the problem is the problem caused by platform implementation:

IOS and Android implementations are inconsistent

  • Easy to out of the Bug
  • Quality cannot be guaranteed through communication

Poor scalability and cannot quickly respond to service requirements

  • The iteration cycle of requirement change is long
  • Incomplete data reporting

The quality assurance system is not perfect

  • Lack of business and design knowledge precipitation
  • Loose Protocol management
  • Lack of uniform automated testing

Inconsistent user experience

For example, the picture below shows the cashier desk before android and iOS were unified.

In order to solve the core problem of platform implementation, and solve the past technical debt. We built a cross-platform framework based on C++ and refactored the core payment process.

Wechat Pay has been fully covered from iOS version 7.0.4 to Android version 7.0.7.

Online effect index

Take the iOS launch situation as an example:

The Crash rate

The Crash rate remained stable before and after the launch, without affecting the stability of wechat. No Crash is required for cross-platform payment, so that users can switch without perception.

For example, people can use wechat to send a red envelope, and the cash register and payment process are driven by cross-platform code written in C++.

performance

The core payment process code, for example, requires 3,512 lines across platforms and 6,328 lines native to iOS. Nearly 45% less code.

Take new requirements development as an example:

7.0.4 Version Requirement 1: The cashier desk is revised

7.0.4 Version Requirement 2: Simplified version of the cashier desk

  • Cross-platform implementation: iOS + Android 3 person-days in total, to be completed before the board closure time
  • Native implementation: iOS, Android board sealing time after a week to basically complete
  • Cross-platform implementation: iOS + Android 5 person-days in total, completed before the board closure time
  • Native implementation: iOS, Android board sealing time after a week to basically complete

So how can payment cross-platform software architectures effectively ensure quality and increase productivity? This is the main content of this article.

What is software architecture

What is software architecture? As Ivar Jacobson (the father of UML) said, take five people to answer this question, and each of them may have a different answer.

An architecture definition can be described in many ways, from code specifications to a release process that can be part of an architecture.

According to the business characteristics of wechat Payment, architecture is defined as: architecture is the components of the system and the relationship between them (communication mode). This is more in line with how we programmers understand architecture when we write business code on a daily basis. That is, MVC, MVVM, etc.

Why software architecture

Back in 1986, the author of the man-month myth talked about the complexity of software: the essential complexity of software lies in the complexity of business requirements.

The most fundamental means of managing complexity is separation of responsibilities. Architecture is slowly reappearing to achieve separation of responsibilities and code reuse. The essence of architecture is to manage complexity. Follow the wechat public account: Java Technology Stack, reply to: Architecture in the background, you can get the N architecture dry goods I sorted out.

Without architecture, all of our code is coupled together, and human mental models aren’t very good at dealing with this complexity, and architecture is essentially the same as sorting books in libraries, or organizing companies. To manage complexity for greater productivity.

Build payment cross-platform software architecture from zero to one

In the field of mobile client, the industry based on C++ to write business code, there is no mature architecture. Even using C++ to write business logic, but do not involve UI, do not involve interface jump flow.

Since the industry does not have a mature architecture to refer to, why not simply apply the industry’s common architecture?

1. Abstract business processes

Now the industry has MVC, MVP, MVVM. These are all familiar software architectures. But there is a problem with all these software architectures: they don’t handle business processes and interface transitions well.

Wechat pay has many procedures. A process consists of a combination of interfaces (viewControllers, activities) and associated business logic.

The MV(X) pattern above misses a very important point, which is who is responsible for the business process, the transition of the interface. That is, who maintains the relationship between the ViewController and the ViewController, where the logic of the business process is written.

If you follow the traditional MVC model, then the ViewController is responsible for communicating with the different ViewControllers. Then the ViewController cannot be reused, and even more fatal is that the code of the business process is very unclear. The code of the business process is scattered into various controllers, and a Controller may be coupled with the code of multiple businesses.

For example: a common transfer process may involve risk control interception, real name verification, checkout, card binding, payment success page, etc. With an MVC architecture, the code quickly becomes unmaintainable.

Therefore, in order to adapt to the characteristics of wechat payment with multiple processes and complex interface jumps. The first step in architectural abstraction is to abstract the business process into a separate role, UseCase. Also, I’m abstracting the interface as UIPage. A large business process can be decomposed into small business processes.

Compare that to the MVC-based mess:

  1. Business process code can be aggregated into UseCase instead of being scattered across viewControllers and activities in iOS and Android.
  2. Business processes and interfaces are reused.
  3. Conform to wechat payment multi-process, interface jump complex business characteristics.

2. Add a routing mechanism

Now that the process has been abstracted, it is time to think more deeply about the business process. When developing a payment business process, developers can’t get around the following issues:

1. Spread between processes and pages.

Let’s say we want to transfer money to a friend, enter the amount, confirm the payment, and trigger the Cgi. The next process is variable. It could be that the user needs to go through a real name, it could be that the user needs to access a secure blocked WebView, or it could be that the cashier is normally pulled up.

The term CGI in this article can be understood as a network request, similar to an HTTP request.

So in the past, when iOS and Android were implemented separately, there was no unified processing mechanism. Either it is determined by a field in the network packet return, or it is maintained locally to determine what process to go next, and so on. It’s very cumbersome and error-prone.

2. Handling of special processes

Another special thing about payment business processes is that in the middle of normal processes, there are often special processes that need to be inserted. There are places to jump to a Webview, places to jump to an applet, places to pop up to inform the user of the risk, or to terminate the current process, and so on. We often need to add such processing over and over again in business code.

These problems led me to think that wechat Payment needs a routing mechanism.

First, look at the routing mechanism. The core idea of the routing mechanism is to pass data to the route, and then the route parses the data and responds.

Combine the characteristics of wechat payment and network closely related. Innovative use of payment domain models as data for delivery.

So how do you build this payment domain model?

Modeling is mapping. Domain knowledge + modeling method = domain modeling. So the domain knowledge here is an understanding of the payment business process. Modeling method, I used UML modeling. Eventually, the Proto protocol will be used by both the client and the background.

First of all, wechat payment business is closely related to the network, processes and pages are often connected by Cgi. Therefore, when modeling, the outermost layer is network packet back. For the routing mechanism, we are only concerned with the routing data model here.

The routing data model is composed of route types and the information required for each route type.

The route type clearly defines the behavior to be triggered. Whether you want to open a UseCase, an interface, a web page, a widget, a popup, etc.

And then there’s the data that these actions require. For example, the parameters needed to open the small program, popover required parameters, etc.

Once the payment domain model is established, the parsing of our routes becomes very clear. After the route is resolved, different actions are triggered based on the route type.

Processes, interface flows, for example, are handed over to UseCase.

Special processes, such as opening applets, opening webViews, pop-ups, etc., will be handled uniformly.

In our first step, we abstracted the business process to UseCase. The second step is to add a routing mechanism.

With the addition of routing, the payment cross-platform software architecture evolved like this.

After adding the routing mechanism, compare the old architecture of iOS and Android:

  1. Unified process, page flow. Clear and easy to maintain.
  2. Unified processing of special processes, reduce repetitive work.
  3. When the routing mechanism is added, the payment domain is modeled based on the characteristics of wechat payment and the network. The core idea of payment background protocol Reconfiguration 2.0 also revolves around this routing mechanism.

Let’s look at the productivity gains from adding routing. Take the payment process to open WebView, small procedures for example, reduce nearly 83% of the code. More importantly, the particular process here is handled uniformly within the routing mechanism, is not coupled to the business code, and is reusable.

3. Manage network requests

Let’s start with the original iOS flaw in handling payment network requests:

The original payment request is initiated through a singleton network center, and then after receiving the packet back, it is called back to the business side by throwing notification or invoking closure.

There are questions like:

1. CGI one-to-many communication problems.

Let me give you an example of a problem we had before.

The Cgi packet sent from the wallet overwrites the data on the payment page. Previously on iOS, you could only fix this by tinkering, increasing the scene value, and adding some tag bits. Maybe one day a new hole will appear.

1. After entering the wallet page, launch a Cgi

2, then enter the payment page also initiate the same Cgi.

3. If the return package initiated by receipt and payment arrives first

4, and then the wallet home page back to the package.

5. CGI lifecycle issues.

From time to time, there will be user feedback, why did not do what operation, suddenly will pop up the network error.

The reason is that there is a problem with the LIFE cycle of Cgi, and the Cgi package back is still processed after the business ends.

Solution:

1. Abstract Cgi as a stand-alone object

Architecturally, the old architecture was an intensive API implemented through the singleton pattern, while our new architecture is a discrete API implemented through the command pattern.

That is, encapsulate the Cgi as a separate object. We aggregate cGI-related properties and capabilities. When developing your business, simply inherit BaseCgi and set the parameters.

2. Divide responsibilities and define life cycle

Until now, android and iOS didn’t agree on who should initiate Cgi. Some people couple activities, viewControllers, and UI code.

Therefore, in the cross-platform software architecture, we are uniformly initiated by the business process UseCase. And the life cycle is one-to-one, a Cgi is only handled by one UseCase, and the Cgi is destroyed when the UseCase is destroyed.

Compare the old architecture:

  1. Eliminate the bugs caused by one-to-many communication
  2. The life cycle is bound to the business logic so that no business ends and the Cgi returns to trigger the action.
  3. High cohesion, low coupling. Cgi-related data can be processed in a centralized manner without awareness on the business side.
  4. Provides unified caching and encryption capabilities.

In steps 1 and 2, we abstracted the business process and added routing mechanisms.

After managing the network request in step 3. Our software architecture evolved like this.

4. Standardize data transfer

The older architectures of iOS and Android both suffered from poor messaging and data pollution. This is the most serious problem. Both iOS and Android have had their fair share of bugs.

First of all, let’s take a look at the recent live network problems:

Before the emergence of iOS, many internal colleagues and external users are giving feedback: after the change page, the blank box will be popped for no reason. Payment, in turn, is about money, causing users to panic.

The specific reasons are:

  1. When you go to the payment front page, the data is returned in the background and written to a public Model.
  2. Then go to the wallet page, and then go to the change page. The public model was passed along.
  3. The change page then reads the data from the public Model, but the code can’t handle it, resulting in a problem that scares users.

In addition, there have been a number of previous android, iOS, such as wallet page change display errors. At the time of payment. Bank card failure and so on.

The problems are so varied that they seem to happen in different places and different situations. Every time you encounter this kind of problem, you have to tinker.

But dig a little deeper, and the real cause is a software architecture problem:

The old payment architecture used the blackboard model, although it was easy to read and write data. But the problems are out of proportion to the benefits:

1. Public read and write data types exist.

Android passes the data type as a dictionary, while iOS passes it as a Model object. All interfaces and business logic share the same data.

2. Disordered data flow.

The flow of data is not traceable, and changes to the data can occur wherever public data is used.

So pay for cross-platform software architecture to eliminate such problems. Here’s how I did it:

  1. Remove public read/write data types
  2. Data of Value Type is passed so that later processes modify the data without affecting previous processes.
  3. Data is passed in one direction and only necessary data is dependency injected.
  4. If data changes require notification of the prior flow, use proxy mode communication.

After canonical data transfer. Compare the old architecture:

  1. Fundamentally solve the problem of data pollution that has plagued wechat payment for a long time from the framework.
  2. The flow of data becomes one-way and traceable.

In the previous three steps, we abstracted the business process and added a routing mechanism to unify the management of network requests.

So by standardizing data transfer, our software architecture evolves like this.

conclusion

The essential complexity of software lies in complex business requirements. The essence of software architecture is to manage complexity, so a truly good architecture is repeatedly refined and summarized from complex business requirements to solve real business problems, not empty talk.

Software architecture is the cornerstone of our business development, in addition to cleaning up the flaws of the historical architecture. It also enables and adds value to the business. On the basis of establishing the software architecture, it also establishes the cross-platform automatic data reporting mechanism of wechat Pay around the software architecture, which can bring huge business benefits such as preventing repeated payments and safe crosscutting. If there is an opportunity, I will further write relevant articles and discuss with you.

Architecture is an evolving process. As new payment services are written based on the cross-platform software architecture, I will continue to update and iterate on this architecture. Make the software architecture more compatible with wechat Payment, more robust and complete.