PAYATHON 2026

支付宝扫码打开H5页面收款应选择哪种支付产品?

支付阿杰

结论

这种场景通常适合接入支付宝的手机网站支付(WAP 支付),对应接口是:

alipay.trade.wap.pay

用户虽然通过支付宝“扫一扫”进入页面,但二维码只是 H5 页面的入口,并不意味着业务属于“扫码支付”。支付产品应根据后续流程来判断:用户在手机浏览器或支付宝内置浏览器中打开商户 H5 页面,再跳转至支付宝收银台完成付款。这属于典型的手机网站支付场景。

如果希望在支付宝内置浏览器中直接唤起客户端支付组件,而不经过普通 WAP 收银台跳转,则可以进一步评估 JSAPI 支付。使用这种方案时,页面通常需要运行在支付宝客户端中,同时满足产品签约、域名配置和接口调用等条件。

推荐的实现流程

手机网站支付的标准流程如下:

  1. 商户生成收款 H5 页面的地址。
  2. 将该地址制作成二维码。
  3. 用户使用支付宝扫一扫打开商户 H5 页面。
  4. 用户点击“立即支付”。
  5. H5 页面请求商户服务端创建支付。
  6. 服务端调用 alipay.trade.wap.pay。
  7. 前端提交支付宝返回的跳转表单,进入支付宝收银台。
  8. 支付完成后,支付宝向商户的 notify_url 发送异步通知。
  9. 商户验签并更新订单状态。

二维码中可以直接放置业务页面地址,例如:

https://pay.example.com/order/202609090001

不要把这个二维码入口当成支付宝“当面付”的付款码或扫码支付接口。只有当二维码本身承载支付宝交易链接,用户扫码后直接进入支付宝收银台时,才更接近当面付的扫码支付模式。

服务端调用示例

下面是支付宝 Java SDK 的常见调用方式。具体类名和配置方式可能随 SDK 版本变化,请以当前接入文档和实际使用的 SDK 为准。

AlipayClient alipayClient = new DefaultAlipayClient(
    gatewayUrl,
    appId,
    merchantPrivateKey,
    "json",
    "UTF-8",
    alipayPublicKey,
    "RSA2"
);

AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();

AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo("202609090001");
model.setSubject("订单付款");
model.setTotalAmount("99.00");
model.setProductCode("QUICK_WAP_WAY");
model.setQuitUrl("https://pay.example.com/order/202609090001");
request.setBizModel(model);

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

AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);

if (response.isSuccess()) {
    String paymentForm = response.getBody();
    // 将 paymentForm 返回给浏览器,由页面提交并跳转到支付宝收银台
} else {
    throw new RuntimeException(
        "创建支付宝支付失败:" + response.getSubMsg()
    );
}

pageExecute 通常会返回一段用于跳转至支付宝收银台的 HTML 表单。服务端可以直接输出这段表单,也可以先将它返回给前端,再由前端写入页面并提交。

如果由服务端直接返回 HTML,需要正确设置响应类型:

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(paymentForm);

支付结果处理

不要只根据 return_url 页面的跳转结果判断付款是否成功。

return_url 是用户支付后浏览器跳转的地址。用户可能在支付后关闭页面、遇到网络中断,或者重复访问该地址。因此,订单状态应以支付宝发送至 notify_url 的异步通知为准。

处理异步通知时,至少需要完成以下检查:

  1. 使用支付宝公钥验证签名。
  2. 检查 app_id 是否属于当前应用。
  3. 检查 out_trade_no 是否存在。
  4. 核对 total_amount 是否与商户订单一致。
  5. 核对收款方身份信息。
  6. 判断 trade_status。
  7. 以幂等方式更新订单。
  8. 处理成功后返回纯文本 success。

常见的成功状态包括:

TRADE_SUCCESS
TRADE_FINISHED

实际业务中,还要根据退款能力和订单生命周期等要求,确定不同状态的处理方式。

什么情况下选择 JSAPI 支付

同时满足以下条件时,可以考虑使用支付宝 JSAPI 支付:

  • 页面明确运行在支付宝客户端的 WebView 中;
  • 希望通过页面脚本直接唤起支付宝支付组件;
  • 已开通对应产品并完成必要配置;
  • 服务端能够先创建支付宝交易;
  • 页面能够调用 AlipayJSBridge。

常见的前端调用形式如下:

function invokeAlipay(tradeNo) {
  AlipayJSBridge.call(
    "tradePay",
    {
      tradeNO: tradeNo
    },
    function (result) {
      console.log(result);
    }
  );
}

if (window.AlipayJSBridge) {
  invokeAlipay(tradeNo);
} else {
  document.addEventListener(
    "AlipayJSBridgeReady",
    function () {
      invokeAlipay(tradeNo);
    },
    false
  );
}

这里的 tradeNo 是支付宝交易号,通常由服务端通过相应的交易创建接口获取。前端回调可以用于改善页面交互,但最终支付结果仍要由服务端查询或通过异步通知确认。

如果页面还可能在微信、系统浏览器或其他应用中打开,手机网站支付通常兼容性更好。使用 JSAPI 支付时,则要检测当前是否处于支付宝客户端环境,并准备无法调用时的降级方案。

注意事项

  • 支付宝扫一扫打开普通 H5 URL,不等于使用“当面付”。
  • 支付宝接口应由商户服务端调用,私钥不能放在 H5 页面或 JavaScript 中。
  • out_trade_no 必须由商户生成并保持唯一。
  • 金额必须由服务端根据订单计算,不能直接采用前端提交的金额。
  • notify_url 必须是支付宝服务器可以访问的 HTTPS 地址,不能使用 localhost 或局域网地址。
  • 支付宝可能重复发送异步通知,因此订单更新必须保证幂等。
  • 用户付款前,需要检查订单是否过期、是否已经支付,以及金额是否发生变化。
  • 产品开通条件、接口权限和域名要求可能随支付宝开放平台规则调整。正式接入前,请以商户账号后台显示的可签约产品和当前官方文档为准。

如果需求只是“扫码进入收款 H5,再从页面跳转至支付宝付款”,应优先选择 alipay.trade.wap.pay 手机网站支付。只有明确需要在支付宝客户端内原生唤起支付组件时,再考虑 JSAPI 支付。

备注:内容仅供参考。