PAYATHON 2026

支付宝APP扫码进入H5缴费应选择哪种支付产品?

支付小周

结论

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

alipay.trade.wap.pay

二维码只是 H5 页面的入口。用户扫码进入页面,输入车牌号、确认金额并发起支付,实际交易仍属于移动端网页支付,不是“当面付”中的用户付款码支付。

为什么选择手机网站支付

选择支付产品时,主要看用户在哪里确认订单、发起付款,不能只看流程中有没有二维码:

  • 二维码中存放的是停车缴费 H5 页面的 URL。
  • 用户进入 H5 后输入车牌号、查询费用并确认订单。
  • 服务端根据订单动态确定支付金额。
  • H5 页面调用支付宝收银台完成付款。

这里的二维码只负责打开页面,后续支付应按手机网站支付接入。

“当面付”更适合商家展示收款码、用户出示付款码,或收银设备扫码等线下收银场景。如果二维码只是业务页面的入口,就不应因为存在扫码动作而选择当面付。

接入流程

1. 开通手机网站支付能力

先在支付宝开放平台创建应用,再按平台当前要求完成应用签约、密钥配置和上线审核。

通常需要保存和配置以下内容:

  • 应用 app_id
  • 应用私钥
  • 支付宝公钥或支付宝公钥证书
  • 支付异步通知地址 notify_url
  • 支付完成后的页面跳转地址 return_url

开放平台可能调整签约条件和配置入口,具体应以应用后台当前显示的产品能力为准。

2. 二维码指向业务 H5 页面

二维码中可以放入类似下面的 HTTPS 地址:

https://pay.example.com/parking

用户使用支付宝 APP 扫码进入页面后,输入车牌号并查询待缴费用。

不要将订单金额等关键交易信息直接写入二维码,也不要信任前端提交的金额。服务端应根据车牌号、停车记录和计费规则生成订单。

3. 服务端创建支付请求

服务端确认订单后,调用 alipay.trade.wap.pay。下面是使用支付宝 Java SDK 的示意代码:

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi.alipay.com/gateway.do",
    appId,
    merchantPrivateKey,
    "json",
    "UTF-8",
    alipayPublicKey,
    "RSA2"
);

AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setNotifyUrl("https://pay.example.com/alipay/notify");
request.setReturnUrl("https://pay.example.com/payment/result");

AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(orderNo);
model.setTotalAmount(totalAmount);
model.setSubject("停车缴费");
model.setProductCode("QUICK_WAP_WAY");

request.setBizModel(model);

AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);

if (!response.isSuccess()) {
    throw new IllegalStateException(
        "创建支付宝支付请求失败:" + response.getSubMsg()
    );
}

String paymentForm = response.getBody();

response.getBody() 通常是支付宝返回的自动提交表单。服务端可以将其作为 HTML 响应返回给浏览器,让页面跳转到支付宝收银台。

这段代码只展示核心调用方式。支付宝 SDK 的不同版本可能在类结构或证书配置方式上有所差异,实际接入时应以所用版本的接口定义为准。

4. 处理异步通知

支付结果必须以支付宝服务端发送的异步通知为准,不能只依赖 return_url 页面显示的结果。

收到通知后,应完成以下处理:

  1. 验证支付宝签名。
  2. 核对 app_id 和商户订单号 out_trade_no。
  3. 核对金额 total_amount。
  4. 检查交易状态,例如 TRADE_SUCCESS。
  5. 以幂等方式更新停车订单。
  6. 处理成功后,按支付宝要求返回成功响应。

示意逻辑如下:

Map<String, String> params = extractRequestParams(request);

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

if (!valid) {
    response.getWriter().write("failure");
    return;
}

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

ParkingOrder order = orderService.findByOrderNo(outTradeNo);

if (order == null || !order.getAmount().toPlainString().equals(totalAmount)) {
    response.getWriter().write("failure");
    return;
}

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

response.getWriter().write("success");

生产环境中,还应根据支付宝当前文档核验通知里的商户身份、交易归属等字段。

特殊情况

如果 H5 页面明确运行在支付宝客户端容器中,并希望通过支付宝 JSAPI 直接唤起支付,也可以评估 JSAPI 支付方案。一般由服务端创建交易,再由页面调用支付宝提供的客户端支付能力。

JSAPI 支付对页面运行环境、授权方式和产品权限还有额外要求。如果页面需要同时兼容普通手机浏览器,手机网站支付通常更合适。

注意事项

  • 二维码应使用可信的 HTTPS 域名,不要使用随时可能变化的临时地址。
  • 订单号 out_trade_no 必须由商户系统生成,并保证唯一。
  • 金额必须由服务端计算,不能直接采用前端传入的值。
  • return_url 只用于改善用户体验,不能证明订单已经支付成功。
  • 异步通知可能重复发送,因此订单更新必须具备幂等性。
  • 确认支付成功后,再执行抬杆、放行或销账等业务操作。
  • 如果放行前需要即时确认,可以结合异步通知和主动查单处理,但不能只根据前端回跳结果放行。
  • 如果二维码不是业务 H5 地址,而是支付宝预下单生成的收款二维码,则应按照当面付等线下支付场景重新评估。

备注:内容仅供参考。