H5 调用 ap.tradePay 时为何提示需在 Alipay 中运行?
支付阿杰
结论
ap.tradePay 是支付宝客户端提供的 JSAPI,只能在支付宝 App 的内置 WebView 中调用。如果页面是在微信、普通浏览器、应用自带的 WebView 或电脑端调试环境中运行,就会出现以下提示:
Run alipayjsapi.js in Alipay please!
这类报错通常与支付参数无关,而是因为页面的运行环境不符合要求。普通浏览器中的 H5 支付需要接入支付宝手机网站支付等网页支付产品,不能直接调用 ap.tradePay。
原因
alipayjsapi.js 封装了支付宝客户端提供的能力,支付操作实际由支付宝 App 注入的 JSBridge 执行。普通浏览器中没有这个桥接环境。
即使相关 JavaScript 文件已经成功加载,只要页面不是从支付宝 App 内打开,客户端桥接能力就不存在,ap.tradePay 也无法正常工作。
以下情况也可能引发同样的问题:
- 直接在 Chrome、Safari 或桌面浏览器中测试页面。
- 页面在手机上打开,但使用的不是支付宝 App。
- 调用接口时,支付宝 JSBridge 尚未完成初始化。
- 引入了错误或来源不明的 JSAPI 脚本。
- 服务端返回的不是
tradeNO所要求的支付宝交易号。
正确调用方式
1. 确认页面从支付宝 App 内打开
可以先判断当前运行环境:
function isAlipayClient() {
return /AlipayClient/i.test(navigator.userAgent);
}
if (!isAlipayClient()) {
alert('请在支付宝 App 中打开此页面');
}
这个判断仅用于改善页面提示,不能作为安全校验。支付金额、订单状态和支付结果仍需由服务端验证。
2. 等待支付宝 JSAPI 初始化
加载项目实际使用的支付宝 JSAPI 脚本后,需要等初始化完成再调用支付接口:
function startPay(tradeNO) {
if (typeof ap === 'undefined') {
alert('支付宝 JSAPI 尚未加载,请确认页面在支付宝 App 中打开');
return;
}
ap.ready(function () {
ap.tradePay(
{
tradeNO: tradeNO
},
function (result) {
console.log('tradePay result:', result);
// 此处只能用于更新前端提示,
// 不能仅凭回调结果认定订单已经支付成功。
}
);
});
}
如果当前使用的 JSAPI 版本不提供 ap.ready,可以等待 AlipayJSBridgeReady 事件:
function ready(callback) {
if (window.AlipayJSBridge) {
callback();
return;
}
document.addEventListener(
'AlipayJSBridgeReady',
callback,
false
);
}
ready(function () {
ap.tradePay(
{
tradeNO: '服务端返回的支付宝交易号'
},
function (result) {
console.log(result);
}
);
});
应根据项目引入的 JSAPI 版本及对应文档,选择 ap.ready 或 AlipayJSBridgeReady,不要通过两种方式重复发起支付。
3. 由服务端创建交易
通常的调用流程是:
- H5 页面向业务服务端提交下单请求。
- 服务端调用支付宝交易创建接口。
- 服务端将支付宝返回的交易号传给 H5 页面。
- H5 页面在支付宝客户端中调用
ap.tradePay。 - 服务端通过异步通知或主动查询确认最终支付状态。
示例:
async function createOrderAndPay() {
if (!/AlipayClient/i.test(navigator.userAgent)) {
alert('请在支付宝 App 中打开后支付');
return;
}
const response = await fetch('/api/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
productId: 'PRODUCT_001'
})
});
if (!response.ok) {
throw new Error('创建订单失败');
}
const data = await response.json();
ap.ready(function () {
ap.tradePay(
{
tradeNO: data.tradeNO
},
function (result) {
console.log('客户端支付回调:', result);
// 建议继续向服务端查询订单状态,
// 页面展示以服务端确认结果为准。
queryOrderStatus(data.orderId);
}
);
});
}
普通浏览器应如何支付
如果用户需要直接通过手机浏览器访问 H5 页面,就不应使用 ap.tradePay。服务端应接入适用于浏览器环境的支付宝网页支付能力,并把用户跳转至支付宝返回的支付页面。
不同入口需要使用对应的支付方式:
- 支付宝 App 内的 H5 页面:满足接入条件时,可以使用
ap.tradePay。 - 手机浏览器中的 H5 页面:使用手机网站支付等网页支付方案。
- 微信内置浏览器:通常需要提示用户跳转至浏览器,具体处理方式取决于采用的支付产品和接入方案。
- 自有 App:使用对应的支付宝 App 支付能力,不要将 H5 JSAPI 用作原生 App 支付接口。
注意事项
tradeNO通常指支付宝侧的交易号,不能直接用商户自己的out_trade_no代替。具体字段要求以所接入接口的文档为准。- 不要在前端生成签名、保存应用私钥,也不要从前端直接调用需要私钥签名的支付宝服务端接口。
- 用户关闭页面或网络中断都可能影响
ap.tradePay的前端回调,因此不能将其作为最终入账依据。 - 最终支付结果应以支付宝异步通知或服务端主动查询为准,同时校验商户号、订单号、金额和交易状态。
- 发起支付后可以暂时禁用支付按钮,避免用户连续点击导致重复调用。
- 如果页面已经在支付宝 App 中打开,但仍然出现警告,可依次检查 JSAPI 脚本来源、加载时机、页面协议、客户端版本,以及调用时
ap和AlipayJSBridge是否存在。
备注:内容仅供参考。
