PAYATHON 2026

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. 由服务端创建交易

通常的调用流程是:

  1. H5 页面向业务服务端提交下单请求。
  2. 服务端调用支付宝交易创建接口。
  3. 服务端将支付宝返回的交易号传给 H5 页面。
  4. H5 页面在支付宝客户端中调用 ap.tradePay。
  5. 服务端通过异步通知或主动查询确认最终支付状态。

示例:

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 是否存在。

备注:内容仅供参考。