PAYATHON 2026

支付宝扫码打开H5页面后付款应接入哪种支付方式?

支付老李

明确结论

用户扫描二维码进入 H5 页面,选择商品后使用支付宝付款,并不代表这笔支付自动属于“当面付”。具体应接入哪种产品,要看付款是如何发起的:

  • H5 提交订单后跳转到支付宝收银台,通常应接入手机网站支付,对应接口为 alipay.trade.wap.pay。这个流程一般不需要获取用户的 auth_code。
  • 如果要在支付宝内置浏览器中直接通过支付宝 JSAPI 完成付款,应接入支付宝提供的 JSAPI 支付能力。服务端通常需要先取得用户的 user_id,因此可能要通过支付宝 OAuth 获取 auth_code,再用它换取 user_id。
  • 经典的“当面付扫码支付”通常由商户调用 alipay.trade.precreate 创建支付订单并生成付款二维码,再让用户扫码付款。普通的 H5 入口二维码并不是当面付的付款二维码。

支付宝开放平台可能调整产品名称和开放权限,接入时应以应用后台当前可签约的产品及相应文档为准。

推荐方案:手机网站支付

如果业务流程是:

  1. 用户使用支付宝扫描入口二维码;
  2. 在支付宝内置浏览器中打开 H5;
  3. 选择商品并提交订单;
  4. 跳转到支付宝收银台付款;
  5. 支付完成后返回 H5;

最直接的方案是接入手机网站支付,也就是 alipay.trade.wap.pay。

这种方案不需要事先识别支付宝用户,也不必为了完成支付而获取 auth_code。服务端创建业务订单后,调用支付接口生成跳转表单或支付地址,浏览器再进入支付宝收银台。

示意代码:

AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();

request.setReturnUrl("https://example.com/pay/return");
request.setNotifyUrl("https://example.com/pay/notify");

request.setBizContent("""
{
  "out_trade_no": "ORDER_202609090001",
  "total_amount": "99.00",
  "subject": "商品订单",
  "product_code": "QUICK_WAP_WAY"
}
""");

AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);

if (response.isSuccess()) {
    String paymentForm = response.getBody();
    // 将 paymentForm 返回给浏览器,由浏览器自动提交或直接输出。
}

前端收到支付表单后,应使用 SDK 返回的完整内容完成跳转,不要自行拼接支付宝网关参数。

需要原生支付体验时使用 JSAPI

如果不想跳转到普通 H5 收银台,而是要在支付宝客户端内直接唤起支付面板,可以采用 JSAPI 支付流程。

通常按以下步骤处理:

  1. 用户扫描入口二维码,进入支付宝内的 H5。
  2. H5 通过支付宝 OAuth 获取临时 auth_code。
  3. 服务端使用 auth_code 换取用户 user_id。
  4. 服务端创建支付订单,取得支付宝交易号 trade_no。
  5. H5 调用 AlipayJSBridge 的 tradePay。
  6. 服务端通过异步通知确认最终支付结果。

前端调用示例:

<script>
function ready(callback) {
  if (window.AlipayJSBridge) {
    callback();
  } else {
    document.addEventListener('AlipayJSBridgeReady', callback, false);
  }
}

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

        // 此处结果只适合更新页面交互状态。
        // 是否支付成功,应由服务端查询或异步通知确认。
      }
    );
  });
}
</script>

这里的 tradeNO 指支付宝侧的交易号,不是商户自己的 out_trade_no,不要混用。

是否必须获取 auth_code

是否需要获取 auth_code,取决于采用的支付方式。

手机网站支付

调用 alipay.trade.wap.pay 时,通常不需要获取 auth_code。支付宝收银台会处理用户身份和付款账户。

如果业务还要识别支付宝用户,例如绑定会员或识别回访用户,则需要单独设计 OAuth 授权流程。这属于用户身份识别需求,并不是手机网站支付的必要步骤。

JSAPI 支付

如果创建交易的接口要求传入付款用户的 buyer_id,通常要先获取用户的 user_id。常见流程是:

  1. 将用户跳转到支付宝 OAuth 授权地址;
  2. 支付宝回跳业务页面,并携带临时 auth_code;
  3. 服务端调用 alipay.system.oauth.token;
  4. 从响应中取得 user_id;
  5. 使用该 user_id 创建交易。

auth_code 是一次性且短时有效的临时凭证,前端不应长期保存,也不能将其当作用户 ID。

如果只需要识别用户,不需要读取昵称、头像等信息,通常应优先使用基础或静默授权范围。具体授权范围是否可用、需要传入哪些参数,应以应用签约能力和当前官方文档为准。

为什么不建议直接认定为“当面付”

选择支付产品时,要看支付订单如何创建、付款如何完成,而不是用户是否扫描过二维码。

这两种二维码的用途不同:

  • 入口二维码:内容通常是商户 H5 地址,例如 https://example.com/shop,只用于打开页面。
  • 付款二维码:由支付订单生成,通常对应 alipay.trade.precreate 返回的 qr_code,用于直接发起某一笔交易。

用户先扫描入口二维码进入商城,选好商品后再跳转到支付宝收银台,这更符合手机网站支付流程。只有服务端先创建付款订单,再生成订单二维码供用户扫描时,才属于典型的当面付扫码支付模式。

服务端异步通知处理

无论使用手机网站支付还是 JSAPI 支付,都不能只根据前端回调认定付款成功。服务端必须验证支付宝发送的异步通知,至少包括:

  • 验证通知签名;
  • 校验 app_id;
  • 校验 out_trade_no;
  • 校验订单金额和币种;
  • 检查交易状态;
  • 保证订单更新具有幂等性;
  • 成功处理后按协议返回确认内容。

伪代码示例:

@PostMapping("/pay/notify")
public String notify(HttpServletRequest request) {
    Map<String, String> params = extractAlipayParams(request);

    boolean valid = AlipaySignature.rsaCheckV1(
        params,
        alipayPublicKey,
        "UTF-8",
        "RSA2"
    );

    if (!valid) {
        return "failure";
    }

    String outTradeNo = params.get("out_trade_no");
    String tradeStatus = params.get("trade_status");
    String totalAmount = params.get("total_amount");

    Order order = orderService.findByOrderNo(outTradeNo);
    if (order == null) {
        return "failure";
    }

    if (!order.getAmount().toPlainString().equals(totalAmount)) {
        return "failure";
    }

    if ("TRADE_SUCCESS".equals(tradeStatus)
            || "TRADE_FINISHED".equals(tradeStatus)) {
        orderService.markPaidIdempotently(
            outTradeNo,
            params.get("trade_no")
        );
    }

    return "success";
}

实际需要校验哪些字段,应结合所接产品的通知协议确定,不能只凭 trade_status 更新订单。

实施建议

如果业务不需要识别支付宝用户,也不要求原生唤起支付面板,优先使用 alipay.trade.wap.pay。它的流程较简单,也不需要处理 OAuth auth_code。

如果要在支付宝内置浏览器中结合会员识别和 JSAPI 支付,应先确认应用已经取得相应产品权限,再实现 OAuth、服务端创建交易以及 AlipayJSBridge.call('tradePay') 流程。

不要混淆“扫码进入页面”和“扫描付款二维码”。前者只是页面入口,仅凭这一点无法判断应该接入哪种支付产品。

备注:内容仅供参考。