PAYATHON 2026

支付宝 App 内打开 H5 页面应接入哪种支付方式?

支付阿杰

结论

如果 H5 页面确定运行在支付宝 App 内,建议优先接入支付宝的 JSAPI 支付,不要把“手机网站支付”作为首选。

典型流程如下:

  1. H5 请求商户服务端创建订单。
  2. 服务端调用 alipay.trade.create。
  3. 服务端将支付宝交易号 trade_no 返回给 H5。
  4. H5 通过 AlipayJSBridge.call('tradePay', ...) 唤起支付宝收银台。
  5. 服务端根据异步通知确认最终支付结果。

用户已经在支付宝客户端内时,JSAPI 支付会直接调用客户端内的收银台,一般不会再次要求用户“打开支付宝 App”。支付过程中可能出现收银台切换、支付确认或验证页面,但这不代表系统重新调起了另一个客户端。

为什么不优先使用手机网站支付

手机网站支付通常通过 alipay.trade.wap.pay 生成跳转页面,主要用于手机浏览器中的支付场景。用户从普通浏览器发起支付时,页面可能尝试唤起支付宝 App,也可能进入支付宝提供的中间页面。

如果 H5 已经运行在支付宝 App 的 WebView 中,再使用手机网站支付通常会增加一层跳转,返回路径和用户体验也更难控制。手机网站支付并非完全不可用,只是 JSAPI 支付更适合支付宝内嵌 H5。

可根据页面的运行环境选择支付方式:

页面运行环境建议支付方式
支付宝 App 内的 H5JSAPI 支付
微信、Safari、Chrome 等普通移动浏览器手机网站支付
商户自己的原生 AppApp 支付
PC 网站电脑网站支付
线下扫码、商家动态收款码当面付等扫码产品

如果同一个链接既可能在支付宝内打开,也可能在普通浏览器中打开,可以按运行环境分流:支付宝内使用 JSAPI 支付,外部浏览器使用手机网站支付。

接入流程

1. 开通并配置对应产品

先在支付宝开放平台创建应用,确认应用已具备 JSAPI 支付所需的产品权限。通常还需要完成商户签约、应用上线、密钥或证书配置,并设置业务域名和授权回调地址等信息。

开放平台的产品名称和控制台入口可能发生调整,具体应以当前应用控制台展示的可签约产品和接入文档为准。

2. 在服务端创建订单

支付金额、订单号和商品信息必须由服务端生成或校验,不能直接信任前端提交的数据。

下面是简化后的伪代码。SDK 类名和初始化方式需要根据实际使用的支付宝 SDK 调整:

AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();

JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", orderNo);
bizContent.put("total_amount", "9.90");
bizContent.put("subject", "测试商品");
bizContent.put("buyer_id", alipayUserId);

request.setBizContent(bizContent.toJSONString());

AlipayTradeCreateResponse response = alipayClient.execute(request);

if (!response.isSuccess()) {
    throw new RuntimeException(
        response.getCode() + ": " + response.getSubMsg()
    );
}

String tradeNo = response.getTradeNo();

其中,alipayUserId 一般通过支付宝网页授权获得。是否必须传入该参数,以及具体的获取方式,应以当前 alipay.trade.create 接口要求和已签约产品的规则为准。

创建订单必须在服务端完成,因为调用支付宝接口时需要使用应用私钥签名。不要把应用私钥、证书私钥或服务端 SDK 配置放入 H5。

3. 在 H5 中调用支付宝收银台

H5 获得服务端返回的 trade_no 后,通过 AlipayJSBridge 发起支付:

<script>
function ready(callback) {
  if (window.AlipayJSBridge) {
    callback();
    return;
  }

  document.addEventListener(
    'AlipayJSBridgeReady',
    callback,
    false
  );
}

async function pay() {
  const response = await fetch('/api/payment/alipay/create', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      orderId: 'ORDER_202609090001'
    })
  });

  const result = await response.json();

  if (!result.tradeNo) {
    throw new Error(result.message || '创建支付订单失败');
  }

  ready(function () {
    AlipayJSBridge.call(
      'tradePay',
      {
        tradeNO: result.tradeNo
      },
      function (payResult) {
        console.log('tradePay result:', payResult);

        // 此处只能用于更新页面提示。
        // 最终支付状态必须向服务端查询。
        window.location.href =
          '/payment/result?orderId=' +
          encodeURIComponent('ORDER_202609090001');
      }
    );
  });
}
</script>

<button type="button" onclick="pay()">立即支付</button>

这里要注意字段名称:JSAPI 的参数通常是 tradeNO,支付宝创建订单接口返回的字段通常是 trade_no。两者名称相似,但不能直接把整个响应对象原样传入。

4. 通过服务端确认支付结果

前端 tradePay 的回调只能表示客户端支付流程已经结束,不能单独作为发货或开通服务的依据。用户可能关闭页面,网络也可能中断,而且前端返回值存在被伪造的可能。

服务端需要:

  1. 接收支付宝异步通知并验证签名。
  2. 校验 app_id、out_trade_no、金额、币种和商户身份等字段。
  3. 对订单状态更新进行幂等处理。
  4. 必要时调用 alipay.trade.query 主动查询交易状态。
  5. 服务端确认支付成功后,再执行发货、充值或开通权益。

同一页面兼容支付宝内外环境

可以先对运行环境做简单判断:

function isAlipayClient() {
  return /AlipayClient/i.test(navigator.userAgent);
}

if (isAlipayClient()) {
  // 调用服务端创建 JSAPI 支付订单
} else {
  // 请求服务端生成手机网站支付跳转地址或表单
}

User-Agent 只能用来选择页面交互流程,不能用于安全校验。服务端仍然需要校验订单、支付渠道和回调签名。

如果业务只允许用户在支付宝内付款,还需要处理页面在非支付宝环境中打开的情况:

if (!isAlipayClient()) {
  document.body.innerHTML =
    '<p>请使用支付宝扫描二维码后完成支付。</p>';
}

常见注意事项

  • 不要在 H5 中保存支付宝应用私钥,也不要让前端自行计算支付金额。
  • 商户订单号 out_trade_no 应当唯一且可追踪,重复请求需要进行幂等处理。
  • 不要只根据前端回调中的“成功”信息发货。
  • 调用 JSAPI 前应等待 AlipayJSBridgeReady,否则可能出现对象未定义的问题。
  • 支付宝网页授权的 auth_code 有有效期,而且通常只能使用一次,应由服务端及时换取用户身份信息。
  • 支付授权域名、回调地址、应用模式和签约主体必须与实际环境匹配。
  • 沙箱环境与正式环境的应用、网关、密钥和账号不能混用。
  • 用户取消支付并不代表订单已经关闭。是否关闭订单,应由服务端按照业务规则决定。
  • 支付完成后的页面跳转只负责展示,最终订单状态仍需从服务端获取。

如果二维码打开的链接确定运行在支付宝 App 内,推荐使用 JSAPI 支付:服务端通过 alipay.trade.create 创建交易,H5 再调用 AlipayJSBridge.tradePay 发起支付。只有页面还要兼容支付宝之外的手机浏览器时,才需要同时接入手机网站支付,并按照运行环境分流。

备注:内容仅供参考。