PAYATHON 2026

不同产品代签约返回的app_auth_token是否一致

支付老李

结论

app_auth_token 表示商户对服务商应用的授权关系,并非某个支付产品或支付场景的专用凭证。

具体来说:

  1. 同一服务商应用代表同一商户调用当面付、JSAPI、H5 支付或网站支付等接口时,通常不需要按产品区分 app_auth_token,使用该商户当前有效的授权令牌即可。
  2. 不要假定不同签约流程返回的 app_auth_token 字符串始终相同。重复签约、重新授权或令牌更新后,接口可能返回新的令牌。
  3. 收到新的 app_auth_token 后,应及时覆盖保存并改用最新值。不要继续依赖旧令牌,也不要只比较令牌字符串来判断授权关系是否发生变化。
  4. 不同商户的 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 应使用能够稳定标识商户的字段,例如支付宝商户账号对应的唯一标识。不要只用店铺名称或签约产品名称作为键。

处理流程如下:

  1. 调用 alipay.open.agent.create 创建代签约事务。
  2. 根据产品调用对应的签约接口:
    • 当面付:alipay.open.agent.facetoface.sign
    • 通用产品:alipay.open.agent.common.sign
  3. 调用对应的 Confirm 接口提交。
  4. Confirm 成功后,保存响应中最新的 app_auth_token。
  5. 后续代表该商户调用支付接口时,统一从这条授权记录中读取当前令牌。
  6. 同时检查目标产品是否已经成功开通,不能将“取得令牌”理解为“所有产品均已开通”。

如果再次 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 的业务提交应尽量保证幂等,避免网络重试造成难以判断的新旧令牌覆盖问题。
  • 如果当前接入文档明确规定某种重新授权行为会使旧令牌失效,应以对应接口的最新官方文档和实际响应为准。

备注:内容仅供参考。