How We Unified iOS and Android Payments with a C++ Cross‑Platform Architecture
Facing divergent iOS and Android implementations, the WeChat Pay team built a C++‑based cross‑platform framework that consolidates payment flows, introduces a UseCase‑driven routing mechanism, refactors network requests, and enforces strict data passing, resulting in reduced code size, fewer bugs, and faster feature delivery.
Background
WeChat Pay faced serious issues because its iOS and Android clients were implemented separately. The core problems included frequent bugs, inability to guarantee quality through communication alone, poor scalability, long iteration cycles, incomplete data reporting, and inconsistent user experience.
Easy to introduce bugs
Quality cannot be guaranteed through communication alone
Additional pain points were poor extensibility, slow response to business changes, incomplete data reporting, insufficient quality‑assurance processes, lack of design knowledge, loose protocol management, and missing automated testing.
User‑experience inconsistency was evident; the checkout UI differed between Android and iOS, as shown in the following image:
Cross‑Platform Solution
To eliminate platform fragmentation, a C++ cross‑platform framework was created and the core payment flow was refactored. The framework has been fully covered on iOS since version 7.0.4 and on Android since version 7.0.7.
Online Metrics
Crash rate : remained stable before and after launch; no regressions were introduced, and users experienced a seamless switch to the cross‑platform checkout.
Example: sending a red‑packet uses the same cross‑platform code to drive the checkout UI.
Performance improvement :
The core payment flow required 3,512 lines of cross‑platform code versus 6,328 lines of native iOS code – a reduction of nearly 45%.
New feature development example (version 7.0.4):
Cross‑platform implementation of checkout redesign: 3 person‑days for iOS + Android, completed before the freeze.
Native implementation: took about a week after the freeze.
What Is Software Architecture?
Software architecture is the set of components and the relationships (communication methods) between them. Common patterns include MVC, MVP, and MVVM, which can be viewed as concrete manifestations of this definition.
Why Architecture Matters
Complex business requirements introduce inherent software complexity. Architecture manages this complexity by separating responsibilities, enabling code reuse, and providing a clear structure that improves productivity.
Building the Cross‑Platform Architecture from Scratch
In mobile clients, C++ is used for business logic without UI. Existing patterns (MVC/MVP/MVVM) do not handle business flow and view transitions adequately for WeChat Pay’s many processes.
1. Abstract Business Flow
Introduce a UseCase to encapsulate a business flow and a UIPage to represent a screen. This aggregates flow code, enables reuse, and matches the complex multi‑step payment processes.
Business‑flow code lives in UseCase instead of being scattered across ViewControllers/Activities.
Both flow and UI become reusable.
The approach fits the numerous, intricate payment scenarios.
2. Add Routing Mechanism
Define a routing data model that carries a route type and the parameters required for that type (e.g., opening a mini‑program, a WebView, or a dialog). The router parses the model and triggers the appropriate action.
Special flows such as opening a mini‑program, a WebView, or a popup are handled uniformly via the router, eliminating duplicated handling code.
3. Manage Network Requests
The old design used a singleton network center that sent requests and delivered responses via notifications or callbacks, leading to one‑to‑many communication bugs and lifecycle mismatches.
Solution: abstract each CGI as an independent object using the command pattern. Each UseCase owns its CGI, and the CGI’s lifecycle matches the UseCase’s lifecycle.
Eliminate one‑to‑many communication bugs.
Bind CGI lifecycle to business logic, preventing stale callbacks.
High cohesion, low coupling; unified caching and encryption.
4. Standardize Data Passing
Replace shared mutable models with immutable value‑type data passed uni‑directionally via dependency injection. When upstream notification is required, use a delegate pattern.
Remove public mutable data structures.
Pass value‑type data so later modifications do not affect earlier steps.
Enforce single‑direction data flow.
Use delegates for required backward communication.
Results
Code size reduced by ~45%, feature development time cut from a week to a few days, special‑flow handling unified, crash rate unchanged, and data‑pollution problems eliminated.
The architecture evolved through four steps: abstracting business flow, adding a routing mechanism, managing network requests, and standardizing data passing, yielding a robust, maintainable cross‑platform payment system.
Conclusion
A well‑designed software architecture that manages complexity enables higher productivity, fewer bugs, and faster feature delivery. It also serves as a foundation for further capabilities such as automated reporting, duplicate‑payment prevention, and cross‑cutting security concerns.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
