支付 SDK 的架构与授权模块定位:SDK 分层、授权服务接口、依赖关系

支付 SDK 采用分层可插拔架构设计,每层职责单一、通过接口契约通信。授权模块作为服务编排层的核心组件,向下依赖 管理与网络传输,向上为商户提供统一的认证入口。本章从整体分层切入,逐步收敛到授权模块的接口定义与依赖关系,为后续的 获取、刷新、验证等实现环节奠定架构基础。

1. SDK 分层架构设计

SDK 内部划分为四层,外加调用方(商户应用系统)构成完整调用链路。每层只依赖其直接下层,禁止跨层调用。

层次 职责 关键组件 / 模块
商户应用系统 集成 SDK 的业务系统,发起支付、查询、对账等请求 商户后端服务、客户端 App
SDK Facade 接口层 统一 API 入口,参数校验、请求路由、异常转换 PaymentClient、AuthorizationClient
服务编排层 业务逻辑编排,多模块协同完成原子操作 授权模块、支付模块、对账模块
核心协议层 管理、签名验签、协议序列化 TokenManager、Signer
网络通信层 底层 HTTP/gRPC 传输、连接池、重试与超时 HttpClient、RetryInterceptor
核心原则:授权模块只通过接口依赖核心协议层的 TokenManager,不直接操作网络连接或加密算法。各层通过依赖注入(DI)解耦,方便单元测试与模块替换。
支付SDK分层架构与授权模块定位 商户应用系统 (Merchant App) SDK Facade 接口层 (统一入口) 服务编排层 (Service Layer) 授权模块 获取 / 刷新 / 验证 支付核心模块 下单 / 退款 / 查询 核心协议层 (管理 / 签名 / 验签) 网络通信层 (HTTP / gRPC) 🔑 授权模块位于服务编排层,统一管理所有相关操作

2. 授权模块在服务层中的定位

授权模块归属于服务编排层,与支付模块、对账模块平级。它封装了与 生命周期相关的全部业务逻辑,对外提供三个核心能力:

  • 获取:使用客户端凭据(client_id + client_secret)或授权码向认证服务器申请 access_ + refresh_。
  • 刷新:在 access_ 即将过期时,使用 refresh_ 无感续期,避免支付流程中断。
  • 验证:对每次支付/查询请求校验 access_ 的有效性、作用域和签名。
常见误区:不要将 的存储与解析逻辑放在网络层或 Facade 层。授权模块必须作为独立编排单元存在,否则会导致 更新时多处耦合、难以维护。

3. 授权服务接口规范

SDK 通过 AuthorizationService 接口暴露授权能力。接口设计遵循无状态 + 幂等原则,每次调用携带完整上下文,不依赖内部缓存。

public interface AuthorizationService {

    /**
     * 获取访问令牌(客户端凭证模式)
     * @param clientId     商户应用ID
     * @param clientSecret 商户应用密钥
     * @param scopes       请求的权限范围列表
     * @return TokenResponse 包含 accessToken、refreshToken、expiresIn
     */
    TokenResponse getAccessToken(String clientId,
                                 String clientSecret,
                                 List<String> scopes);

    /**
     * 刷新访问令牌
     * @param refreshToken 上次获取的刷新令牌
     * @return TokenResponse 新的访问令牌与刷新令牌
     */
    TokenResponse refreshAccessToken(String refreshToken);

    /**
     * 验证访问令牌有效性
     * @param accessToken   待验证的令牌
     * @param requiredScopes 要求的权限范围
     * @return TokenValidationResult 包含有效标志、过期时间、实际作用域
     */
    TokenValidationResult verifyToken(String accessToken,
                                      List<String> requiredScopes);

    /**
     * 撤销指定令牌(主动失效)
     * @param  待撤销的 accessToken 或 refreshToken
     */
    void revokeToken(String );
}
方法 触发时机 幂等性 典型错误
getAccessToken SDK 初始化 / 首次获取 是(相同参数返回相同结果) clientSecret 错误、scope 超出授权范围
refreshAccessToken access_ 过期前 5 分钟(由调度器触发) 是(重复刷新返回最新有效 ) refresh_ 已过期、已被撤销
verifyToken 每次支付 / 查询请求进入时 是(纯校验,无副作用) 篡改、签名不匹配、requiredScopes 缺失
revokeToken 商户主动 logout / 安全策略触发 否(重复撤销返回成功,无副作用) 已过期仍尝试撤销
接口设计技巧:getAccessToken 与 refreshAccessToken 返回相同的 TokenResponse 结构体,上层调用者无需区分 来源。验证接口 verifyToken 通过本地签名校验实现毫秒级响应,无需每次请求都回源认证服务器。

4. 模块依赖关系

授权模块的依赖分为内部 SDK 依赖和外部第三方依赖两类。合理的依赖管理是保证模块可测试、可替换的关键。

4.1 内部依赖(SDK 模块间)

依赖方向 被依赖模块 依赖目的
授权模块 → 核心协议层 TokenManager 创建、签名、序列化 对象
授权模块 → 核心协议层 Signer 请求签名与验签
授权模块 → 网络通信层 HttpClient 发送 获取/刷新请求到认证服务器
SDK Facade → 授权模块 AuthorizationService 对外暴露授权接口

4.2 外部依赖(第三方库)

以下为 Maven 风格的依赖声明,授权模块仅引入 JSON 解析与 HTTP 客户端两个基础库:

<!-- 支付 SDK 核心依赖 (包含授权模块) -->
<dependency>
    <groupId>com.payment.sdk</groupId>
    <artifactId>payment-sdk-auth</artifactId>
    <version>2.1.0</version>
</dependency>

<!-- JSON 序列化 ( 载荷解析) -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

<!-- HTTP 客户端 (认证服务器通信) -->
<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.2.1</version>
</dependency>
依赖管理要点:
  • 所有外部依赖声明为 compile 范围,SDK 打包时自动传递。
  • Jackson 与 HttpClient 的版本号统一集中在 dependencyManagement 中管理,避免版本冲突。
  • 授权模块不直接依赖任何数据库或缓存中间件—— 存储由调用方通过 TokenStore 接口注入。

5. 设计要点与常见误区

  • 严禁跨层依赖:授权模块只能调用核心协议层和网络通信层的接口,不得直接访问商户应用系统的数据源。
  • 接口版本化:AuthorizationService 从 v1 版本开始定义,后续新增方法必须通过接口继承或默认方法实现,避免破坏已有实现。
  • 存储由调用方决定:授权模块只负责生成和验证 ,不负责持久化。商户可通过实现 TokenStore 接口将 存入 Redis、数据库或内存。
常见错误:
1. 在授权模块内部缓存 导致多实例环境 不一致。
2. 在 HTTP 客户端层直接解析 响应体,绕过授权模块的签名校验。
3. 未将 clientSecret 配置为独立参数,硬编码在授权模块代码中。

通过以上分层设计与接口规范,授权模块在 SDK 中具备了清晰的边界、可替换的实现以及严格的依赖管控。下一阶段将进入具体的 获取与验证实现环节。