聚合支付如何完成商户进件并通过h5支付结算
结论
这个场景通常适合使用支付宝开放平台的当面付服务商模式。服务商协助商户完成签约或进件,再通过应用授权代商户调用交易接口。
用户扫码进入页面后,如果页面运行在支付宝客户端内,服务端可以调用 alipay.trade.create 创建交易,H5 页面再通过支付宝 JSAPI tradePay 调起付款。收款主体必须是实际商户,资金才会按照该商户的签约结算规则进入其支付宝账户,或结算至绑定的银行账户。
这里需要区分两种“结算”需求:
- 如果只是要求每笔资金直接归属于对应商户,使用当面付服务商模式即可,不要先收进平台账户,再由平台自行转账。
- 如果平台还需要抽佣、分账、延迟结算或资金托管,当面付本身无法提供这些能力,需要另行申请支付宝当前开放的平台型资金产品。产品是否可用、支持哪些支付渠道,要以支付宝开放平台对具体应用和行业的审核结果为准。
为什么不能直接使用普通 H5 支付
“扫码进入 H5”和“手机网站支付”不是同一个场景。
如果用户使用支付宝扫描二维码,页面在支付宝 WebView 中打开,并通过 JSAPI 调起付款,典型流程如下:
支付宝扫码
→ 打开支付宝内 H5
→ 获取用户支付宝身份
→ 服务端创建当面付交易
→ H5 调用 tradePay
→ 支付宝异步通知
→ 服务端确认交易结果
alipay.trade.wap.pay 则用于手机浏览器网页支付,通常会跳转到支付宝客户端或支付宝收银台。它和客户端内的 JSAPI 支付在产品权限、调用方式及商户签约范围上并不完全相同,不能因为页面使用 H5 技术,就一律按照手机网站支付处理。
直付通主要用于平台型交易、二级商户管理和资金结算。如果当前直付通方案没有开放所需的 H5 或 JSAPI 支付渠道,更换前端调用方式也无法绕过产品权限。
商户接入流程
1. 创建服务商应用
服务商需要在支付宝开放平台创建第三方应用,并配置应用公钥、支付宝公钥、网关地址、回调地址及所需的产品权限。
私钥只能保存在服务端,不能写进 H5 页面或小程序代码。
2. 完成商户签约或进件
根据支付宝向服务商开放的能力,可以选择商户自主签约、服务商代签约,或使用支付宝提供的商户入驻接口。可用的进件接口、必填资质和审核流程取决于行业及应用权限,不能只根据通用接口名称判断。
进件完成后,至少需要保存以下信息:
- 商户支付宝
user_id,也常称 PID; - 商户授权产生的
app_auth_token; - 授权范围和授权状态;
- 产品签约状态;
- 商户主体与门店信息;
- 结算账户配置。
进件成功不代表商户已经取得支付权限。正式创建交易前,还要确认商户已经签约当面付,并且服务商应用获得了代调用权限。
3. 获取付款用户身份
调用 alipay.trade.create 时,通常需要付款人的支付宝 user_id。H5 页面可以通过支付宝网页授权获取 auth_code,再由服务端用它换取用户身份。
授权回调和用户信息换取必须在服务端完成,不能信任前端自行提交的 buyer_id。
4. 以实际商户身份创建交易
下面是服务端调用的示意代码。示例省略了部分配置和异常处理,实际字段应以当前支付宝 SDK 及开放平台文档为准。
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
serviceProviderAppId,
serviceProviderPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
request.setNotifyUrl("https://pay.example.com/alipay/notify");
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", orderNo);
bizContent.put("total_amount", "10.00");
bizContent.put("subject", "门店消费");
bizContent.put("buyer_id", buyerUserId);
bizContent.put("seller_id", merchantAlipayUserId);
request.setBizContent(bizContent.toJSONString());
AlipayTradeCreateResponse response =
alipayClient.execute(request, null, merchantAppAuthToken);
if (!response.isSuccess()) {
throw new IllegalStateException(
response.getCode() + ": " + response.getSubMsg()
);
}
String tradeNo = response.getTradeNo();
调用时要使用对应商户的 app_auth_token,收款主体也必须是已经完成签约的实际商户。是否需要显式传入 seller_id,要根据应用授权模式和支付宝当前的接口要求确定。
5. H5 调起支付宝支付
服务端创建交易后,只把支付宝交易号返回给前端:
<script>
function startAlipay(tradeNo) {
if (!window.AlipayJSBridge) {
document.addEventListener(
'AlipayJSBridgeReady',
function () {
startAlipay(tradeNo);
},
{ once: true }
);
return;
}
AlipayJSBridge.call(
'tradePay',
{ tradeNO: tradeNo },
function (result) {
console.log(result.resultCode);
// 此处只用于展示结果,不能据此确认订单已支付。
}
);
}
</script>
部分运行环境可能使用 ap.tradePay 等封装。具体调用方式应以支付宝客户端当前的 JSAPI 文档和应用接入方式为准,不要混用不同容器的调用示例。
6. 接收通知并确认订单
前端显示支付成功,不代表服务端已经确认收到资金。服务端必须完成以下处理:
- 验证异步通知签名;
- 核对
app_id、seller_id、out_trade_no和金额; - 检查
trade_status; - 保证订单更新操作具有幂等性;
- 必要时调用交易查询接口再次确认;
- 验证通过后,向支付宝返回规定的成功响应。
通知中的金额、商户号和订单状态都要与本地订单比对,不能直接采用。
资金如何到达商户账户
交易虽然由服务商应用代为创建,但收款主体应当是实际商户。支付宝会按照该商户签署的协议处理资金。服务商不能通过修改回调地址或业务参数来改变资金归属。
“资金进入商户支付宝账户”和“自动结算至银行卡”也不是一回事。是否自动结算及何时到账,取决于商户的结算协议、结算周期、银行卡配置、风险状态和支付宝实际开放的结算能力,业务代码不能自行假定资金会实时到账。
如果平台需要从每笔交易中收取技术服务费,应先确认是否具备合法且受支付宝支持的分账或服务费能力。不建议让平台统一收款后,再在线下向商户转账。这种方式可能带来二清、账务、税务和合规风险。
接入时容易忽略的问题
- 二维码应指向 HTTPS 页面,并配置支付宝要求的授权回调域名。
- 金额必须由服务端根据订单重新校验,不能直接信任 H5 提交的值。
- 每个
out_trade_no必须全局唯一,重复请求需要进行幂等处理。 app_auth_token是敏感凭证,需要加密存储,并处理失效、撤销和重新授权。- 测试环境与生产环境的应用、密钥、商户签约和网关地址不能混用。
- 服务商代调用成功,不代表商户进件、产品签约和收款权限都已经生效。
- 如果二维码还可能由微信或系统浏览器等环境扫描,需要识别运行环境并提供降级提示。支付宝 JSAPI 无法在普通浏览器中直接调用。
因此,如果业务流程是“支付宝扫码进入支付宝内 H5,再调用 JSAPI 付款,资金直接归属于各商户”,应优先申请并确认当面付服务商模式。如果还涉及分账、抽佣或平台统一结算,需要将资金方案单独提交支付宝评估,不能只靠当面付接口完成。
备注:内容仅供参考。
