支付宝服务商模式下APP支付如何直接入账子商户?
明确结论
在支付宝服务商模式下,如果 APP 支付的资金需要直接进入子商户账户,应采用以下方式:
服务商以第三方应用身份,携带子商户授权后取得的 app_auth_token,调用 alipay.trade.app.pay。
接口调用和签名由服务商完成,实际交易收款方是子商户。资金会按照支付宝的交易规则进入子商户账户,无需先进入服务商账户再转账。
只在支付参数中填写子商户名称、商户号或 seller_id,无法代替应用授权。
为什么需要 app_auth_token
服务商的应用私钥只能证明请求由服务商应用发起,不能证明服务商有权代某个子商户创建交易。
子商户完成第三方应用授权后,支付宝会签发对应的 app_auth_token。服务商调用支付接口时携带该令牌,支付宝才能确认:
- 接口由哪个服务商应用调用;
- 实际业务主体是哪个已授权的子商户;
- 交易应创建在哪个子商户名下;
- 支付结果、账单和退款权限应按哪一组授权关系处理。
如果没有传入 app_auth_token,订单通常会按服务商自身的签约身份创建,无法让子商户直接收款。
接入步骤
1. 创建并配置第三方应用
服务商需要在支付宝开放平台创建适用于代调用场景的第三方应用,并完成相关配置,包括:
- 应用签名方式及密钥或证书;
- APP 支付相关能力;
- 授权回调地址;
- 支付异步通知地址;
- 应用上线,以及支付宝要求的审核和签约流程。
实际可用的能力取决于服务商应用类型、子商户资质,以及支付宝开放平台当时的产品规则。
2. 让子商户完成应用授权
服务商生成授权链接,引导子商户使用具备相应权限的支付宝账号完成授权。授权回调通常会返回 app_auth_code。
app_auth_code 是一次性临时授权码,不能直接用于支付。服务商需要调用:
alipay.open.auth.token.app
使用 app_auth_code 换取:
app_auth_token
app_refresh_token
取得令牌后,服务商应将其与内部子商户编号、支付宝商户身份等信息准确关联,并妥善保存。
3. 服务端生成 APP 支付订单
APP 支付订单必须由服务端创建。调用 alipay.trade.app.pay 时,需要把目标子商户的 app_auth_token 作为接口级参数传入。
下面以 Java SDK 为例:
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
"服务商第三方应用APPID",
"服务商应用私钥",
"json",
"UTF-8",
"支付宝公钥",
"RSA2"
);
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setOutTradeNo("SUB202609090001");
model.setSubject("订单商品名称");
model.setTotalAmount("99.00");
model.setProductCode("QUICK_MSECURITY_PAY");
model.setTimeoutExpress("30m");
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl("https://example.com/alipay/notify");
request.setBizModel(model);
String appAuthToken = "目标子商户对应的app_auth_token";
AlipayTradeAppPayResponse response =
alipayClient.sdkExecute(request, appAuthToken);
if (!response.isSuccess()) {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
// 将订单字符串返回给客户端,由支付宝客户端 SDK 发起支付
String orderString = response.getBody();
不同版本的支付宝 Java SDK 可能提供不同的方法重载。如果当前版本没有 sdkExecute(request, appAuthToken),应按照该版本 SDK 的接口要求,把 app_auth_token 设置为请求的顶层公共参数,不能放入 biz_content。
各项身份关系如下:
签名应用:服务商第三方应用
签名私钥:服务商应用私钥
app_auth_token:当前子商户的授权令牌
实际收款方:该令牌对应的子商户
4. 客户端调起支付宝
服务端需要把 sdkExecute 返回的完整订单字符串原样交给 APP,再由 APP 通过支付宝客户端 SDK 调起支付。
客户端不能自行拼接或修改金额、收款方、订单号等参数。否则既可能导致签名校验失败,也会增加订单被篡改的风险。
5. 服务端处理异步通知
服务端收到支付宝异步通知后,至少应完成这些校验:
- 验证支付宝签名;
- 检查
app_id是否符合预期; - 检查
out_trade_no是否存在; - 检查
total_amount是否与本地订单一致; - 检查交易状态;
- 核对子商户与订单的绑定关系;
- 对同一通知进行幂等处理。
不能只根据客户端返回的”支付成功”更新订单状态。订单结果应以服务端验签后的异步通知或主动查询结果为准。
是否需要填写 seller_id
部分支付接口允许通过 seller_id 指定收款支付宝用户 ID,但在服务商代子商户调用的场景中,seller_id 不能代替 app_auth_token。
交易主体应优先通过授权关系确定。如果业务确实需要传入 seller_id,必须确认:
- 该值是目标子商户正确的支付宝用户 ID,不是登录账号或应用 APPID;
- 该值与
app_auth_token指向同一商户; - 当前签约产品明确支持这组参数。
如果 seller_id 与 app_auth_token 指向的商户不一致,支付宝可能拒绝创建交易。是否必须填写该参数,应以当前接入产品的接口文档和签约配置为准。
常见错误
把子商户号放进业务参数,但没有传授权令牌
普通业务字段不会改变接口调用主体。缺少 app_auth_token 时,支付宝无法根据第三方应用的授权关系识别子商户。
使用服务商自己的 app_auth_token
每个令牌都对应特定的授权商户。多商户系统必须根据订单所属商户读取正确的令牌,不能让多个商户共用同一个令牌。
在客户端生成支付参数
私钥和授权令牌不能放进 APP。签名、金额计算、订单创建和令牌读取都应在服务端完成。
混淆 app_auth_code 和 app_auth_token
app_auth_code 用于换取令牌,真正用于代商户调用接口的是 app_auth_token。
忽略授权失效
子商户撤销授权、令牌失效,或者相关产品权限发生变化后,代调用会失败。系统应保存令牌的有效期信息,并根据令牌接口的返回结果刷新令牌或要求子商户重新授权,不能写死有效期限。
还需要注意什么
- 子商户需要具备相应的 APP 支付签约能力和收款资质。
- 服务商应用必须取得对应的接口权限。完成应用授权,并不代表相关产品已经签约。
out_trade_no应在相应商户维度内保持唯一,避免不同商户之间发生订单串用。- 退款、交易查询和关闭订单时,通常也需要携带创建原交易时所用的同一子商户
app_auth_token。 - 系统应保存订单对应的子商户、授权令牌标识和支付宝交易号,避免后续查询或退款时使用错误的商户身份。
- 如果业务需要服务商抽佣,应采用支付宝明确支持的分账或服务费方案,不能用”先收进服务商账户再人工转账”的方式模拟子商户直接收款。
要让资金直接进入子商户账户,无需修改 APP 端的收款逻辑。服务商需要在服务端以第三方应用身份调用支付接口,并为每笔订单传入该子商户有效的 app_auth_token。
备注:内容仅供参考。
