1. 授权机制概述
授权机制是现代支付 SDK 的核心安全基础设施。它通过一个临时的、可撤销的凭证()代替用户的长期敏感凭据(如卡号、密码),在每次支付请求中仅验证 的有效性与作用域,从而降低凭据泄露风险、简化鉴权链路、支持精细化权限控制。
核心认知: 不是加密后的用户密码,而是一个由授权服务器签发的、包含有限权限与过期时间的访问凭证。支付 SDK 不直接处理用户凭据,只处理 。
1.1 核心概念
| 概念 | 说明 | 支付场景示例 |
|---|---|---|
| Access | 访问令牌,携带权限范围与过期时间,用于调用支付接口 | 调用「发起支付」「查询订单」接口时携带 |
| Refresh | 长期刷新令牌,用于在 Access 过期后无感续期 | SDK 后台静默刷新,用户无感知 |
| Scope(权限范围) | 限定 可操作的具体资源与动作 | payment:create payment:query 等 |
| 授权码(Authorization Code) | 临时一次性码,用于换取 Access (OAuth 2.0) | 用户在支付收银台授权后返回的临时码 |
| 令牌端点( Endpoint) | 授权服务器上用于颁发/刷新 的 REST API | POST /oauth/ |
1.2 支付场景的授权流程
典型的支付 SDK 授权流程分为四个阶段,整个过程对用户透明,仅 SDK 与授权服务器、支付网关交互。
- 初始化认证:SDK 首次启动时,使用客户端凭证(Client ID + Client Secret)向授权服务器请求一个基础 Access (无用户上下文)。
- 用户授权:当需要执行敏感操作(如绑定卡、支付确认)时,SDK 弹出 WebView 引导用户完成认证并返回授权码。
- 令牌交换:SDK 用授权码向 Endpoint 换取 Access + Refresh 。
- 业务调用:SDK 在 HTTP 头携带 Access 调用支付接口, 过期后自动使用 Refresh 续期。
实现要点:支付 SDK 不应将 Access 暴露给第三方应用层,必须固化在 SDK 内部存储或内存中,避免 XSS/网络嗅探导致令牌泄露。
1.3 生命周期
从创建到销毁经历以下六个阶段,每个阶段都有对应的状态与处理逻辑:
| 阶段 | 状态 | 触发条件 | 支付 SDK 行为 |
|---|---|---|---|
| 1. 签发 | active | 授权码交换或 Refresh 成功 | 存储到安全区域(iOS Keychain / Android Keystore) |
| 2. 使用 | active | 每次支付/查询请求 | 附加 Authorization: Bearer <> 到请求头 |
| 3. 过期 | expired | 超过 Access 有效期(通常 30~60 分钟) | 自动触发 Refresh 流程;若 Refresh 失败则再次引导用户授权 |
| 4. 刷新 | refreshing | SDK 检测到过期或收到 401 响应 | 使用 Refresh 请求新 Access ,原子替换旧令牌 |
| 5. 撤销 | revoked | 用户主动登出、安全策略触发 | 调用授权服务器的 revoke 端点,清除本地令牌 |
| 6. 删除 | deleted | SDK 卸载、数据清理 | 直接擦除所有令牌数据 |
常见错误:支付 SDK 在 过期后直接返回错误给应用层,而不是自动刷新,会导致用户支付流程中断。正确的做法是 SDK 内部捕获 401,静默完成 Refresh,再重试原请求。