支付宝第三方应用的 app_auth_token 是否需要保存?
支付老李
结论
app_auth_token 需要及时记录并安全保存。还要一并保存返回的 app_refresh_token、授权商户标识和有效期。
分几种情况:
app_auth_token尚未过期:可以直接用它代商户调用接口。app_auth_token丢失,但有效的app_refresh_token仍在:通常可以通过刷新令牌重新获取,不需要商户再次授权。app_auth_token和app_refresh_token都丢失:支付宝一般不提供根据商户 ID 直接查询或找回明文令牌的接口。原授权码失效后,通常只能请商户重新完成授权。- 刚完成授权,但还没有兑换令牌:只要
app_auth_code仍然有效且未被使用,就可以继续兑换;如果已经过期或使用过,就不能再用它获取令牌。
因此,不能把“以后再从支付宝查回来”当作容错方案。
为什么必须保存
app_auth_token 表示商户允许第三方应用代其调用接口。第三方应用调用需要商户授权的开放接口时,必须携带该令牌。
授权流程大致如下:
- 商户进入第三方应用的支付宝授权页面。
- 商户确认授权。
- 支付宝回调第三方应用,并返回
app_auth_code。 - 第三方应用使用
app_auth_code调用alipay.open.auth.token.app。 - 支付宝返回
app_auth_token、app_refresh_token和有效期等信息。 - 第三方应用保存令牌,供后续接口调用使用。
app_auth_code 是短期的一次性凭证,不适合长期保存或反复兑换。需要持久化的是兑换后得到的令牌信息。
推荐的保存字段
建议至少保存以下内容:
auth_app_id
user_id
app_auth_token
app_refresh_token
expires_in
re_expires_in
app_auth_token_expires_at
app_refresh_token_expires_at
updated_at
实际字段应以当前使用的支付宝接口文档和 SDK 响应为准。有效期最好根据接口返回值计算,不要写死在代码中。
如果同一个第三方应用获得了多个商户的授权,应按“第三方应用 + 授权商户”建立唯一关系,防止不同商户的令牌相互覆盖。
获取并保存令牌
下面是支付宝 Java SDK 的常见调用方式。不同 SDK 版本的类名或方法签名可能略有差异,请以项目实际依赖的版本为准。
AlipayOpenAuthTokenAppRequest request =
new AlipayOpenAuthTokenAppRequest();
AlipayOpenAuthTokenAppModel model =
new AlipayOpenAuthTokenAppModel();
model.setGrantType("authorization_code");
model.setCode(appAuthCode);
request.setBizModel(model);
AlipayOpenAuthTokenAppResponse response =
alipayClient.execute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
"获取授权令牌失败: " + response.getSubCode()
+ " - " + response.getSubMsg()
);
}
// 应在返回授权回调的处理流程中立即持久化
saveOrUpdateToken(
response.getAuthAppId(),
response.getUserId(),
response.getAppAuthToken(),
response.getAppRefreshToken(),
response.getExpiresIn(),
response.getReExpiresIn()
);
保存时最好使用事务或原子更新。只有数据库写入成功,才能认为授权接入已经完成。
使用刷新令牌重新获取
如果 app_auth_token 丢失或即将过期,而有效的 app_refresh_token 仍然存在,可以再次调用 alipay.open.auth.token.app:
AlipayOpenAuthTokenAppRequest request =
new AlipayOpenAuthTokenAppRequest();
AlipayOpenAuthTokenAppModel model =
new AlipayOpenAuthTokenAppModel();
model.setGrantType("refresh_token");
model.setRefreshToken(savedAppRefreshToken);
request.setBizModel(model);
AlipayOpenAuthTokenAppResponse response =
alipayClient.execute(request);
if (!response.isSuccess()) {
throw new IllegalStateException(
"刷新授权令牌失败: " + response.getSubCode()
+ " - " + response.getSubMsg()
);
}
// 刷新后应以本次响应为准,更新全部令牌和有效期
saveOrUpdateToken(
response.getAuthAppId(),
response.getUserId(),
response.getAppAuthToken(),
response.getAppRefreshToken(),
response.getExpiresIn(),
response.getReExpiresIn()
);
刷新后,应以本次响应为准更新全部令牌和有效期。如果响应中返回了新的 app_refresh_token,必须同时覆盖旧值,不能只更新 app_auth_token。
两个令牌都丢失怎么办
可以按以下顺序排查:
- 检查数据库备份、密钥管理系统和历史数据迁移记录。
- 确认原
app_auth_code是否仍然有效且从未兑换。 - 如果还保存着
app_refresh_token,使用刷新模式重新获取。 - 如果所有有效凭证都已丢失,重新生成授权链接,请商户再次完成授权。
商户与第三方应用之间的授权关系可能仍然存在,但这不代表第三方应用可以在没有凭证的情况下取回令牌。出于授权安全考虑,仅凭商户 ID、支付宝账号或应用 ID,无法静默恢复 app_auth_token。
注意事项
- 不要将
app_auth_token或app_refresh_token输出到普通日志、错误页面或监控系统的明文字段中。 - 数据库中的令牌应加密存储,并严格限制读取权限。
- 根据接口返回的有效期安排提前刷新,避免令牌到期后业务突然中断。
- 刷新令牌时需要处理并发,防止多个任务同时刷新并相互覆盖结果。
- 商户解除授权、授权范围发生变化或应用状态异常时,即使令牌还没有达到预计过期时间,也可能无法继续调用接口。
- 调用具体业务接口时,需要按照支付宝 SDK 的要求传入
app_auth_token。不同语言和 SDK 版本的传参位置可能不同。 - 令牌交换或刷新失败时,应保存
code、sub_code、sub_msg等非敏感错误信息,方便排查问题,但不要记录完整令牌。
备注:内容仅供参考。
