PAYATHON 2026

支付宝当面付如何通过三方应用授权收款到同主体账号

支付老李

结论

可以采用三方应用授权模式,由商户账号 B 收款。

调用 alipay.trade.create 时:

  • app_id 使用商户账号 A 创建的三方应用 APPID;
  • 请求使用三方应用私钥签名;
  • 验签使用该三方应用配置对应的支付宝公钥;
  • app_auth_token 必须是商户账号 B 授权后生成的有效令牌;
  • 商户账号 B 需要签约并开通当面付产品权限;
  • 三方应用需要接入当面付功能包,并取得调用接口所需的权限。

满足这些条件后,三方应用只是代商户 B 发起交易。交易归属、收款以及后续的退款、查询、对账等业务,主体都是商户 B,而不是创建三方应用的商户账号 A。

小程序应用 A 取得服务端返回的支付宝交易号后,可以调用 my.tradePay 唤起支付。不过,小程序能否支付这笔交易,仍取决于支付宝开放平台对应用关联关系、支付场景和当前产品权限的校验。即使两个账号属于同一主体,也不能绕过产品或应用权限限制。

实现流程

1. 商户账号 A 创建三方应用

在支付宝开放平台创建三方应用,配置应用密钥,并为应用添加当面付相关功能包。

服务端需要保存:

  • 三方应用 APPID;
  • 三方应用私钥;
  • 三方应用对应的支付宝公钥;
  • 支付宝网关地址;
  • 商户授权后获得的 app_auth_token。

三方应用私钥只能保存在服务端,不能放进小程序前端。

2. 商户账号 B 完成产品签约和应用授权

商户账号 B 应先确认已经签约当面付,并且账号状态、结算能力和接口权限均正常。

随后,商户 B 通过三方应用提供的授权链接完成授权。授权成功后,三方应用服务端使用授权码换取:

  • app_auth_token;
  • app_refresh_token;
  • 授权商户身份信息;
  • 令牌有效期等信息。

创建交易时使用的是 app_auth_token,不是授权过程中取得的一次性授权码。

3. 服务端以商户 B 的身份创建交易

各项请求参数和配置应按下表使用:

参数或配置应使用的值
app_id商户账号 A 创建的三方应用 APPID
请求签名三方应用私钥
验签公钥三方应用配置对应的支付宝公钥
app_auth_token商户账号 B 授权后生成的令牌
当面付签约主体商户账号 B
out_trade_no三方应用为商户 B 生成的唯一订单号

app_auth_token 决定了三方应用代哪个商户调用接口。如果不传这个参数,请求通常会按三方应用自身的业务身份处理,无法达到代商户 B 收款的目的。

下面是一个 Java SDK 示例。支付宝 SDK 版本不同,具体类名和构造方式可能略有差异:

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi.alipay.com/gateway.do",
    ISV_APP_ID,
    ISV_APP_PRIVATE_KEY,
    "json",
    "UTF-8",
    ALIPAY_PUBLIC_KEY,
    "RSA2"
);

AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();

JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", "B202609090001");
bizContent.put("total_amount", "0.01");
bizContent.put("subject", "门店订单");

// alipay.trade.create 通常需要提供付款用户标识。
// 实际使用 buyer_id、buyer_open_id 或其他字段,应以当前接口文档和应用模式为准。
bizContent.put("buyer_id", buyerId);

request.setBizContent(bizContent.toJSONString());

// 必须使用商户账号 B 授权产生的 app_auth_token
AlipayTradeCreateResponse response =
    alipayClient.execute(request, null, merchantBAppAuthToken);

if (!response.isSuccess()) {
    throw new IllegalStateException(
        "创建交易失败:" + response.getCode()
        + " / " + response.getSubCode()
        + " / " + response.getSubMsg()
    );
}

String tradeNo = response.getTradeNo();

部分 SDK 也支持通过请求对象或通用请求参数设置 app_auth_token。无论使用哪种写法,都要确认它最终出现在支付宝开放平台请求的公共参数中,不能放进 biz_content。

4. 小程序使用 tradeNO 唤起支付

服务端成功创建交易后,只向小程序返回支付宝交易号和必要的业务状态,不要返回私钥或 app_auth_token。

my.tradePay({
  tradeNO: tradeNo,
  success: (result) => {
    console.log("支付调用完成", result);

    // 前端结果仅用于页面展示。
    // 最终支付状态应由服务端主动查询或异步通知确认。
  },
  fail: (error) => {
    console.error("支付调用失败", error);
  }
});

参数名应为 tradeNO,其值来自 alipay.trade.create 返回的支付宝交易号 trade_no。

如何确认实际收款方

不能只根据小程序所属账号判断收款方。应由服务端查询交易,并核对授权商户和交易归属。

查询时仍然需要使用:

  • 三方应用 APPID;
  • 三方应用私钥;
  • 商户 B 的 app_auth_token;
  • 创建交易时的 out_trade_no 或支付宝 trade_no。

退款、撤销、关闭交易和账单处理也需要继续携带商户 B 对应的 app_auth_token。如果查询或退款时误用了其他商户的令牌,可能会出现“交易不存在”“无权限操作该交易”等错误。

注意事项

app_auth_token 必须与商户 B 对应

不能使用商户 A 的令牌,也不能把 app_refresh_token 当作调用令牌。建议在数据库中建立清晰的映射关系:

merchant_b_id -> app_auth_token
merchant_b_id -> app_refresh_token
merchant_b_id -> token_expire_time
merchant_b_id -> authorization_status

如果系统接入了多个商户,需要根据订单所属商户选择对应的令牌,避免串户收款。

同一主体不是唯一判断条件

三方应用授权主要取决于商户授权关系、产品签约和接口权限。即使 A、B 属于同一主体,商户 B 仍需完成应用授权和当面付签约。至于是否允许非同主体商户授权,则要以应用类型、开放平台准入要求和实际审核结果为准。

小程序与三方应用是两个应用身份

小程序应用 A 的 APPID 与三方应用 APPID 不能混用:

  • 服务端调用 alipay.trade.create 时,使用三方应用 APPID;
  • 小程序只接收服务端返回的 tradeNO,并调用 my.tradePay;
  • 不能使用小程序私钥代替三方应用私钥签名;
  • 不能在前端创建交易或保存授权令牌。

如果客户端提示交易与小程序不匹配,应重点检查三方应用功能包、商户授权范围、小程序支付场景,以及开放平台要求的应用关联配置。

以服务端支付结果为准

不能直接把 my.tradePay 的成功回调作为发货或核销依据。服务端应通过支付宝异步通知或交易查询确认:

  • 通知签名是否有效;
  • app_id 是否符合预期;
  • out_trade_no 是否存在且属于商户 B;
  • 订单金额是否一致;
  • 交易状态是否已成功;
  • 通知是否已被重复处理。

做好授权失效处理

如果商户 B 取消授权、令牌到期、产品解约或账号受限,代调用可能失败。服务端需要保存授权状态,妥善保管 app_refresh_token,并按照当前开放平台规则刷新令牌。收到授权取消通知后,应立即停止为该商户创建新交易。

这套参数配置方向是正确的:三方应用负责签名,并携带商户 B 的 app_auth_token 调用 alipay.trade.create,再把返回的 tradeNO 交给小程序调用 my.tradePay。能否稳定运行,取决于商户 B 的当面付签约状态、三方应用的功能包和授权范围,以及小程序支付场景能否通过支付宝侧校验。

备注:内容仅供参考。