支付宝 H5 调用 ap.tradePay 提示支付唤起方式不正确
结论
这段 ap.tradePay 前端代码没有明显的语法问题。报错 商家支付唤起方式不正确,通常是因为传入的 tradeNO 不是为支付宝客户端 JSAPI 支付创建的交易号,或者交易使用的支付产品、应用身份与当前唤起方式不一致。
resultCode 为 6001,只表示弹窗出现后交易流程被取消,并不是最初的失败原因。排查重点应放在服务端创建交易的接口和参数上,不要把 6001 当成根因。
正确的调用流程
支付宝客户端内的 H5 页面使用 ap.tradePay 时,调用流程如下:
- H5 页面运行在支付宝客户端内。
- 服务端调用适合该场景的交易创建接口,例如
alipay.trade.create。 - 服务端完成签名,并向支付宝创建交易。
- 服务端取得支付宝返回的
trade_no。 - 服务端将
trade_no返回给 H5。 - H5 将其作为
tradeNO传给ap.tradePay。
这里的 tradeNO 是支付宝交易号,通常来自接口响应中的 trade_no,不是商户订单号 out_trade_no。
常见错误原因
1. 把商户订单号当成 tradeNO
下面的传值方式是错误的:
ap.tradePay({
tradeNO: outTradeNo
});
out_trade_no 是商户系统生成的订单号,而 tradeNO 必须是支付宝创建交易后返回的 trade_no。
正确写法是:
ap.tradePay({
tradeNO: alipayTradeNo
});
2. 使用其他支付产品创建订单
如果服务端通过以下接口创建支付,再把相关订单号交给 ap.tradePay,可能会出现支付场景不匹配的问题:
alipay.trade.wap.pay:手机网站支付alipay.trade.app.pay:App 支付alipay.trade.precreate:扫码支付- 其他仅适用于特定收银台或扫码场景的接口
这些接口生成的交易不一定能通过 ap.tradePay 唤起。支付宝会校验订单对应的支付产品、创建方式和当前客户端场景。如果校验未通过,就可能提示 支付唤起方式不正确。
如果业务场景是在支付宝客户端内打开 H5,并通过 JSAPI 唤起支付,服务端需要按照对应的支付宝内支付方案创建交易。可以使用哪些接口、需要传入哪些参数,还要看商户签约的产品和应用配置。
3. 创建订单和调用支付时使用了不同的应用身份
还要确认以下信息一致:
- 创建交易时使用的
app_id - 当前商户签约支付产品对应的应用
- 商户账号及收款主体
- 服务端签名使用的应用私钥
- 支付宝公钥或证书配置
- 创建订单时声明的支付场景
如果订单由应用 A 创建,却在应用 B 对应的业务环境中尝试唤起,支付宝也可能拒绝这次支付。
前端调用示例
发起支付前,应等待支付宝 JSAPI 初始化完成,并检查服务端是否返回了交易号:
<script src="https://appx/web-view.min.js"></script>
<script>
document.addEventListener('AlipayJSBridgeReady', function () {
// 此值必须由服务端创建交易后返回
var tradeNO = '支付宝返回的 trade_no';
if (!tradeNO) {
ap.alert({
title: '支付失败',
content: '未取得支付宝交易号'
});
return;
}
ap.tradePay(
{
tradeNO: tradeNO
},
function (res) {
console.log('tradePay result:', res);
if (String(res.resultCode) === '9000') {
console.log('客户端支付流程完成');
} else {
console.log('支付未完成,resultCode:', res.resultCode);
}
}
);
}, false);
</script>
如果已经正确加载 alipayjsapi.min.js,可以继续使用现有的引入方式。问题的关键不在脚本文件名,而在于调用时支付宝客户端的 JSBridge 是否就绪,以及 tradeNO 的来源是否正确。
服务端需要核对的内容
服务端创建交易后,应保留完整的支付宝响应日志,重点检查以下字段:
app_id
method
out_trade_no
trade_no
code
sub_code
sub_msg
接口调用成功并返回有效的 trade_no 后,才能将它传给前端:
{
"code": "10000",
"trade_no": "支付宝交易号",
"out_trade_no": "商户订单号"
}
前端取值时要注意字段映射:
const tradeNO = response.trade_no;
不要写成:
const tradeNO = response.out_trade_no;
关于 6001
6001 通常表示用户取消了支付流程,或者客户端将流程判定为已取消。在这个场景中,支付宝先弹出 支付唤起方式不正确,用户关闭弹窗后,回调才返回 6001,所以它只是后续结果。
排查时应先确认:
- 服务端通过哪个接口创建了交易;
tradeNO是否确实是支付宝返回的trade_no;- 创建交易所用的产品是否支持
ap.tradePay; - 创建交易和唤起支付是否使用同一个
app_id、商户和签约产品。
支付结果处理注意事项
即使 ap.tradePay 返回 9000,也不应只根据前端回调将订单直接标记为支付成功。客户端回调只能反映客户端支付流程的结果,最终状态应由服务端通过支付宝异步通知或主动查询交易来确认。
可以按以下流程处理:
前端收到 9000
→ 请求业务服务端查询订单
→ 服务端调用支付宝交易查询接口或检查异步通知
→ 确认交易状态后更新业务订单
当前问题的修复重点是调整服务端的下单方式,并向前端传递正确的支付宝 trade_no。如果已经确认 tradeNO 无误,再检查创建交易时使用的接口、app_id 和商户签约产品是否支持支付宝客户端内的 JSAPI 唤起场景。
备注:内容仅供参考。
