小程序接入支付宝支付时如何绑定其他商户?
结论
普通自研小程序开通“小程序支付”时,通常只能绑定与应用主体一致的支付宝商户,不能直接填写其他公司的商户号(PID)。
如果小程序需要代指定商户收款,应接入支付宝开放平台的第三方应用或服务商模式。目标商户先完成支付产品签约,再授权第三方应用代为调用支付接口。创建交易时,服务端需要使用该商户对应的 app_auth_token。仅修改 seller_id、PID 或前端参数,无法代替正式的商户授权。
如果“其他商户”是同一集团内的另一主体,可以先确认支付宝后台是否支持应用迁移、主体关联或集团商户绑定。具体入口和适用范围可能随账号类型和平台规则调整,以当前开放平台控制台显示的内容为准。
为什么能力列表里只能选择本公司
“小程序支付”涉及应用主体、商户身份、结算账户和资金安全。普通应用开通该能力时,平台会校验应用与商户的主体关系,因此开发者不能随意绑定没有授权关系的商户。
这里需要区分两个概念:
- 小程序运营主体:负责发布和管理小程序。
- 实际收款商户:交易、账单、退款和资金结算所归属的商户。
两者不一致时,必须建立支付宝认可的授权关系,不能只通过技术参数指定收款方。
推荐方案:由目标商户授权第三方应用
1. 确认目标商户具备收款资格
目标商户需要完成支付宝商家认证,并根据业务场景签约“小程序支付”等必要产品。即使已经授权应用,未完成产品签约的商户也可能无法创建交易。
还需确认以下事项:
- 商户经营范围符合支付宝的相关规则。
- 小程序展示的经营主体、商品与实际收款商户之间存在合理关系。
- 目标商户同意由当前系统代为发起支付、查询和退款。
- 如果业务涉及多商户平台、分账或二清风险,应使用相应的平台型产品,不能通过普通支付接口自行归集资金。
2. 创建或配置第三方应用
在支付宝开放平台中,以第三方应用或服务商模式接入,并配置以下内容:
- 应用密钥,以及支付宝公钥或支付宝公钥证书。
- 授权回调地址。
- 支付结果通知地址。
- 支付、查询、退款等所需的接口权限。
- 与小程序支付场景匹配的产品能力。
控制台菜单名称可能因应用类型或平台改版而变化。如果现有小程序应用中没有“商户授权”“第三方应用”或类似能力,一般不能直接改成代商户调用模式,需要在服务商账号下创建符合要求的第三方应用。
3. 让目标商户完成授权
服务端生成商户授权地址或二维码,目标商户使用自己的支付宝商家账号登录并确认授权。授权成功后,支付宝会向配置的回调地址返回一次性的 app_auth_code。
app_auth_code 不能作为长期令牌使用,需要在有效期内换取:
app_auth_tokenapp_refresh_token- 授权商户相关标识
- 令牌有效期
换取令牌通常使用以下接口:
alipay.open.auth.token.app
请求中的授权类型为:
authorization_code
令牌到期后,应使用 app_refresh_token 刷新。系统还需要处理商户取消授权、授权失效和产品解约等情况。
4. 使用商户的 app_auth_token 创建交易
服务端调用支付接口时,网关签名仍使用第三方应用的私钥,同时必须传入目标商户对应的 app_auth_token。支付宝通过该令牌识别本次调用所代表的商户。
下面是支付宝 Java SDK 的示意代码。具体类名和重载方法以项目实际使用的 SDK 版本为准:
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
isvAppId,
isvPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
request.setNotifyUrl("https://example.com/alipay/notify");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "99.00",
"subject": "订单支付",
"buyer_id": "2088xxxxxxxxxxxx"
}
""");
/*
* accessToken 通常传 null。
* appAuthToken 必须是当前收款商户授权后取得的令牌。
*/
AlipayTradeCreateResponse response =
alipayClient.execute(request, null, appAuthToken);
if (!response.isSuccess()) {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
String tradeNo = response.getTradeNo();
buyer_id 是付款用户在相应支付宝应用上下文中的用户标识,不能填写商户 PID。具体应使用哪一种用户标识,需要结合当前接口文档和应用授权关系确认。
小程序取得服务端返回的 trade_no 后,再调用支付能力:
my.tradePay({
tradeNO: tradeNo,
success: (result) => {
console.log(result);
},
fail: (error) => {
console.error(error);
}
});
前端回调只能说明用户端的调用结果,不能作为最终入账依据。订单的最终状态应由服务端查询交易,或在验签并处理支付宝异步通知后确认。
多商户场景下的服务端处理
系统需要分别保存每个已授权商户的授权信息,并根据订单所属商户读取相应的 app_auth_token:
订单
→ 确定实际收款商户
→ 读取该商户的 app_auth_token
→ 调用 alipay.trade.create
→ 返回 trade_no 给小程序
→ 验签并处理支付通知
至少需要维护以下数据:
- 内部商户编号与支付宝商户标识的对应关系。
- 加密保存的
app_auth_token和app_refresh_token。 - 令牌有效期和刷新状态。
- 商户授权状态及支付产品签约状态。
- 每笔订单对应的实际收款商户。
创建交易、查询和退款时,应始终使用同一商户的授权上下文,避免支付属于商户 A,退款却以商户 B 的身份发起。
不可行的做法
以下方式通常无法接入其他商户:
- 在普通小程序的能力列表中直接填写其他公司的 PID。
- 只在支付请求中修改
seller_id。 - 使用目标商户的账号密码或私钥代替正式授权。
- 让多个商户共用一个
app_auth_token。 - 先统一收款,再由系统私下向其他商户结算。
- 直接使用小程序前端传入的商户编号,不在服务端校验实际收款商户。
“统一收款后再结算”可能涉及二清、分账和合规问题。如果业务实质上是平台撮合多个商户交易,应向支付宝确认是否需要使用服务商、平台商户、分账或其他行业解决方案。
注意事项
app_auth_token决定接口调用所代表的商户,不能由前端提交或保存。- 每次创建订单前,服务端都应校验商品、订单与收款商户之间的归属关系。
- 支付异步通知必须验签,并核对
app_id、订单号、金额、交易状态和实际收款方信息。 - 商户撤销授权后,应立即停止以该商户身份创建新交易。
- 系统应具备令牌刷新和失败重试机制,但不能无条件重试支付创建请求,以免生成重复订单。
- 沙箱环境与正式环境的应用、商户、密钥和令牌不能混用。
- 如果只有一个固定的外部商户,而且小程序实际由该商户经营,可以优先考虑由该商户主体创建或接收迁移后的应用。这通常比搭建完整的服务商授权体系更简单。
- 如果开放平台后台没有第三方应用或代商户调用入口,需要联系支付宝开放平台,确认当前账号是否具备服务商资格,以及该业务是否允许应用主体与收款主体不一致。
备注:内容仅供参考。
