不同产品代签约返回的app_auth_token是否一致
结论
app_auth_token 表示商户对服务商应用的授权关系,并非某个支付产品或支付场景的专用凭证。
具体来说:
- 同一服务商应用代表同一商户调用当面付、JSAPI、H5 支付或网站支付等接口时,通常不需要按产品区分
app_auth_token,使用该商户当前有效的授权令牌即可。 - 不要假定不同签约流程返回的
app_auth_token字符串始终相同。重复签约、重新授权或令牌更新后,接口可能返回新的令牌。 - 收到新的
app_auth_token后,应及时覆盖保存并改用最新值。不要继续依赖旧令牌,也不要只比较令牌字符串来判断授权关系是否发生变化。 - 不同商户的
app_auth_token必须严格隔离,不能混用。
这些结论有一个前提:多个产品均由同一个服务商应用代同一个商户签约。如果服务商应用 app_id 或被代签约商户发生变化,就属于另一组授权关系,需要单独保存令牌。
原因
app_auth_token 用于证明某个商户已经授权某个服务商应用代其调用开放平台接口。产品签约则决定商户开通了哪些能力,如当面付、JSAPI 支付、H5 支付或网站支付。两者属于不同维度。
可以这样理解:
app_auth_token:服务商是否有权代表该商户调用接口。- 产品签约状态:该商户是否已经开通对应的支付产品。
- 支付接口:在授权有效且产品已经开通的情况下执行具体业务。
调用不同支付场景时,通常需要调整的是支付接口及业务参数,而不是根据产品选择不同的 app_auth_token。
即使两次 Confirm 返回了相同的令牌字符串,也没有必要按签约产品分别保存两份。反过来,如果字符串不同,也不能据此判断它们分别属于不同的支付产品。
推荐处理方式
建议以“服务商应用 + 商户”作为授权记录的唯一维度:
(service_app_id, merchant_id) -> latest_app_auth_token
其中,merchant_id 应使用能够稳定标识商户的字段,例如支付宝商户账号对应的唯一标识。不要只用店铺名称或签约产品名称作为键。
处理流程如下:
- 调用
alipay.open.agent.create创建代签约事务。 - 根据产品调用对应的签约接口:
- 当面付:
alipay.open.agent.facetoface.sign - 通用产品:
alipay.open.agent.common.sign
- 当面付:
- 调用对应的 Confirm 接口提交。
- Confirm 成功后,保存响应中最新的
app_auth_token。 - 后续代表该商户调用支付接口时,统一从这条授权记录中读取当前令牌。
- 同时检查目标产品是否已经成功开通,不能将“取得令牌”理解为“所有产品均已开通”。
如果再次 Confirm 返回了新的 app_auth_token,应覆盖更新原有记录,而不是按产品新增一条令牌记录。
调用示例
下面使用 Java SDK 的常见调用形式进行说明。具体请求类和业务参数应以当前使用的支付宝开放平台 SDK 为准。
String merchantId = "2088xxxxxxxxxxxx";
String appAuthToken = tokenRepository.getLatestToken(
serviceAppId,
merchantId
);
AlipayTradePrecreateRequest request =
new AlipayTradePrecreateRequest();
request.setBizContent("""
{
"out_trade_no": "ORDER_202609130001",
"total_amount": "100.00",
"subject": "订单支付"
}
""");
AlipayTradePrecreateResponse response =
alipayClient.execute(request, null, appAuthToken);
if (!response.isSuccess()) {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
调用其他支付场景时,仍可使用该商户当前有效的 app_auth_token:
AlipayTradeWapPayRequest request =
new AlipayTradeWapPayRequest();
request.setBizContent("""
{
"out_trade_no": "ORDER_202609130002",
"total_amount": "100.00",
"subject": "H5订单支付",
"product_code": "QUICK_WAP_WAY"
}
""");
AlipayTradeWapPayResponse response =
alipayClient.pageExecute(request, null, appAuthToken);
这里更换的是支付接口和 product_code,授权主体并未变化,所以不需要为 H5 支付另外选择一枚产品令牌。
令牌更新示例
Confirm 成功后,可以按以下方式处理返回值:
String newToken = confirmResponse.getAppAuthToken();
if (newToken == null || newToken.isBlank()) {
throw new IllegalStateException(
"Confirm 成功,但未取得 app_auth_token"
);
}
tokenRepository.saveOrUpdate(
serviceAppId,
merchantId,
newToken
);
数据库更新需要保证原子性,避免并发签约时,较早返回的响应覆盖较新的令牌。如果条件允许,还可以保存更新时间、授权状态和关联的商户标识,方便排查问题。
关于旧令牌是否立即失效
仅凭接口返回了不同的 app_auth_token,无法判断旧令牌是否会立即失效。旧令牌能否继续使用,可能受重新授权、取消授权、令牌更新和开放平台当前规则的影响。
实际系统不应依赖旧令牌可能存在的宽限期。建议采用以下策略:
- Confirm 返回新令牌后立即更新;
- 后续请求只使用最新保存的令牌;
- 不要在多个产品配置中长期保留不同版本的令牌;
- 遇到授权无效、授权关系不存在或权限不足等错误时,先核对商户与令牌的对应关系,再检查授权状态和产品签约状态;
- 不要通过反复重试旧令牌来规避重新授权。
注意事项
app_auth_token必须属于当前被代调用的商户。使用其他商户的令牌会导致授权校验失败。- 同一商户分别授权不同的服务商应用时,需要为每个应用单独保存令牌。
- 取得
app_auth_token不代表商户已经开通所有支付产品,各产品仍需核对签约结果和生效状态。 - 不要将
app_auth_token写死在代码或配置文件中。令牌应加密存储,并限制日志输出。 - Confirm 的业务提交应尽量保证幂等,避免网络重试造成难以判断的新旧令牌覆盖问题。
- 如果当前接入文档明确规定某种重新授权行为会使旧令牌失效,应以对应接口的最新官方文档和实际响应为准。
备注:内容仅供参考。
