Skip to content

Code Architecture ​

Updated: 10/15/26, 5:44:21 PM

The DaxPay main application follows a layered pattern of base-layer aggregates + business modules + startup entry, with channel integration pushed down into independent sub-applications. Every sub-application keeps the same pattern, so the structures can be compared and kept in sync during maintenance.

Main App Layering (dax-pay-open) ​

dax-pay-open/
├── daxpay-platform/              # Base layer
│   ├── daxpay-platform-core        # Common contracts: DTO / enums / exceptions / result wrapper
│   ├── daxpay-platform-common      # Common technical infrastructure (aggregate)
│   │   ├── common-i18n               # Backend i18n resources + JsonMessageSource
│   │   ├── common-mybatis-plus       # ORM configuration
│   │   ├── common-redis              # Redis configuration
│   │   ├── common-artemis            # Message queue
│   │   ├── common-json               # JSON serialization
│   │   ├── common-swagger            # API documentation
│   │   ├── common-config             # Encryption / platform config / deployment-mode enforcement
│   │   ├── common-request-context    # Request context
│   │   ├── common-translate          # Translation
│   │   └── common-spring             # Spring extensions
│   ├── daxpay-platform-capability  # Platform capabilities (aggregate)
│   │   ├── capability-auth            # Authentication
│   │   ├── capability-audit-log       # Audit log
│   │   ├── capability-file            # Files
│   │   ├── capability-cache           # Cache
│   │   ├── capability-nonce           # Anti-replay
│   │   ├── capability-social          # Social login
│   │   ├── capability-wechat          # WeChat open platform
│   │   ├── capability-alipay          # Alipay open platform
│   │   ├── capability-douyin          # Douyin open platform
│   │   └── capability-sensitive-word  # Sensitive words
│   └── daxpay-platform-service     # Platform business services (aggregate)
│       ├── service-iam               # Users / roles / menus / permission codes
│       ├── service-system            # Dictionaries / configuration / logs
│       ├── service-baseapi           # Base APIs
│       └── service-notify            # In-app notifications / announcements / SSE
├── daxpay-payment/                # Payment business
│   ├── daxpay-payment-core          # Payment domain core: domain models / transaction engine / open API contracts
│   ├── daxpay-payment-admin         # Operator (admin) portal controllers and services
│   ├── daxpay-payment-merchant      # Merchant self-service portal controllers and services
│   ├── daxpay-payment-unipay        # Unified acquiring /unipay/**, gateway products, public H5
│   ├── daxpay-payment-app-admin     # Operator mobile app / mini-program payment APIs
│   └── daxpay-payment-app-merchant  # Merchant mobile app / mini-program payment APIs
├── daxpay-channel/                # Channel business (orchestration layer)
│   ├── daxpay-channel-alipay        # Alipay channel (HTTP declaration + config CRUD)
│   ├── daxpay-channel-wechat        # WeChat channel
│   ├── daxpay-channel-douyin        # Douyin channel
│   ├── daxpay-channel-ums           # UMS channel
│   ├── daxpay-channel-union         # UnionPay (QuickPass) channel
│   └── ...                          # 20+ channel capabilities, all routed uniformly by the orchestration layer, no SDKs
├── daxpay-plugin/                 # Payment plugins
│   ├── daxpay-plugin-easypay        # EasyPay protocol plugin
│   └── daxpay-plugin-risk           # Payment risk-control plugin (blacklist + hit records)
├── daxpay-demo/                   # Feature demo module
└── daxpay-start/                  # Startup entry (port 9999)

Responsibility Boundary Between Orchestration and Integration ​

DaxPay's channel system strictly separates the orchestration layer (main application) from the integration layer (sub-applications). This is the core design behind SDK isolation:

ResponsibilityMain app daxpay-channel/*Sub-app channel-one / channel-two
Third-party SDK callsNo SDK imports at allDirectly calls alipay-sdk / wxjava / etc.
Channel configuration CRUDEntity / DAO / ControllerNo persistence
Payment strategy orchestrationstrategy → serviceNo business orchestration
HTTP declarative interfaces@HttpExchange client@RestController endpoints
Signing / signature verificationBusiness signatures (RSA)Channel signatures (inside the SDK)
Callback assemblyForwards to sub-apps for verification and parsingVerifies and parses raw payloads

Invocation mechanism — The main application creates an @HttpExchange proxy for each channel through the ChannelRestClientSupport factory, bound to the corresponding sub-application's baseUrl; requests pass through ChannelTransportEncryptInterceptor for AES-GCM transport encryption; sub-application responses use the unified {code, msg, data} (DaxResult), and the main application treats code == 0 as success.

Channel routing assignment — Each channel's XxxClientConfig is bound at compile time to channelProperties.getOne() (port 20100), getTwo() (port 20200), or getThree() (port 20300):

Bound to channel-one (20100)Bound to channel-two (20200)Bound to channel-three (20300)
Alipay, WeChat, Douyin, UMS, UnionPay (QuickPass)Lakala, Haikerongtong, Dougong, Leshua, Suixingfu, HemaPay, Adapay, Fuyou, YeePayStripe

Sub-service Split Principles ​

The main application calls each independent sub-service over HTTP. The goals of the split:

  • Channel SDK dependency isolation — Third-party SDKs stay out of the main application, avoiding transitive dependency conflicts from alipay-sdk / wxjava and the like
  • Independent upgrades — Sub-services can be released per channel, so frequent channel upgrades do not affect less active channels
  • Elastic scaling — High-volume channels (Alipay, WeChat) can scale out independently with multiple instances

Channel Sub-service List ​

Sub-serviceLanguage / frameworkExposed capabilityPortChannels
dax-pay-channel-oneJava / Spring Boot 4.1Direct channel integration201005 (Alipay / WeChat / Douyin / UMS / UnionPay)
dax-pay-channel-twoJava / Spring Boot 4.1Aggregate channel integration202009 (Lakala / Haikerongtong / Dougong / Leshua / Suixingfu / HemaPay / Adapay / Fuyou / YeePay)
dax-pay-channel-threeJava / Spring Boot 4.1International payment channel integration203001 (Stripe)

The channel sub-applications also have experimental Go copies — experimental in nature and outside the mainline support scope. See Applications.

How the main application calls each sub-service:

Sub-applications are a lightweight subset of the main project's structure: the platform layer keeps only core + common (config / i18n / json / util) + service-system, without capability or the other services. Common contracts (DTOs / interfaces / exceptions) live in platform-core so that later channel sub-applications can reuse them. Each sub-application is an independent git repository with its own version — there is no Maven dependency on the main project, only a structural correspondence.