PAYATHON 2026

网站接入支付宝扫码支付是否需要开通“当面付”

支付小周

结论

需要。

如果网站的支付流程是“服务端创建订单 → 生成支付宝付款二维码 → 用户使用支付宝扫码支付”,一般需要签约并开通支付宝的“当面付”产品,再调用 alipay.trade.precreate 接口生成二维码。

APP 已上线,只代表应用已经创建或发布,不会自动获得“当面付”权限。支付宝的 APP 支付、手机网站支付、电脑网站支付和当面付是不同的支付产品,需要分别签约和配置。

如果网站不直接展示二维码,而是将用户跳转到支付宝收银台,则应根据终端选择“电脑网站支付”或“手机网站支付”,不一定需要开通当面付。

为什么需要开通当面付

alipay.trade.precreate 是支付宝的预创建交易接口,返回结果中包含 qr_code。商户可以将这段内容生成二维码,供用户扫码付款。

常见流程如下:

  1. 用户点击“开通 VIP”。
  2. 网站服务端创建本地订单。
  3. 服务端调用 alipay.trade.precreate。
  4. 支付宝返回 qr_code。
  5. 前端根据 qr_code 生成二维码。
  6. 用户扫码付款。
  7. 支付宝通过异步通知发送支付结果。
  8. 网站完成验签并确认订单金额后,为用户开通 VIP。

APP 是否上线与这套流程没有直接关系。接入前需要确认:

  • 商户账号是否已经完成实名认证;
  • 商户是否具备所需的经营资质;
  • 是否已经签约当面付;
  • 当前支付宝应用是否已经配置相应能力;
  • 应用公钥、支付宝公钥或证书是否配置正确。

支付宝开放平台可能会调整准入条件和后台菜单名称,最终应以商户后台显示的产品签约状态为准。

接入步骤

1. 申请支付产品

登录支付宝开放平台或商家平台,在支付产品签约入口申请“当面付”。

申请通过后,还要确认接口使用的 app_id 已经具备当面付能力。如果只签约了商户账号,但应用没有正确关联,调用接口时仍可能出现“无权限调用接口”等错误。

2. 配置应用密钥

建议使用支付宝官方 SDK,并按照开放平台的要求配置:

  • app_id
  • 应用私钥
  • 支付宝公钥,或者支付宝公钥证书
  • 应用公钥证书
  • 支付宝根证书
  • 签名算法,通常为 RSA2

私钥只能保存在服务端,不能写入网页 JavaScript、APP 安装包或公开仓库。

3. 创建本地订单

调用支付宝接口前,应先在自己的数据库中创建订单。订单至少需要包含:

  • 商户订单号;
  • 用户 ID;
  • 商品或会员套餐;
  • 应付金额;
  • 支付状态;
  • 创建时间和过期时间。

商户订单号 out_trade_no 必须唯一。不能直接采用前端提交的金额,服务端应根据会员套餐重新计算应付金额。

4. 调用预创建交易接口

下面以 Java 和支付宝 SDK 的常见调用方式为例。不同版本 SDK 的构造方法可能不同,实际项目应以当前所用 SDK 的官方文档为准。

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

AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
request.setNotifyUrl("https://www.example.com/api/alipay/notify");

AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo("VIP202609090001");
model.setTotalAmount("99.00");
model.setSubject("VIP会员服务");
model.setTimeoutExpress("15m");

request.setBizModel(model);

AlipayTradePrecreateResponse response = alipayClient.execute(request);

if (response.isSuccess()) {
    String qrCodeContent = response.getQrCode();
    // 将 qrCodeContent 返回给前端,由前端生成二维码
} else {
    String subCode = response.getSubCode();
    String subMsg = response.getSubMsg();
    // 记录错误码和错误信息,便于排查
}

response.getQrCode() 返回的是二维码内容,不一定是图片地址。前端可以使用二维码组件将其渲染成图片:

new QRCode(document.getElementById("pay-qrcode"), {
  text: qrCodeContent,
  width: 240,
  height: 240
});

二维码内容应由后端接口返回。前端不能自行拼接支付链接,也不能持有支付宝应用私钥。

5. 处理异步通知

支付完成后,支付宝会向 notify_url 发送异步通知。服务端至少需要执行以下处理:

  1. 使用支付宝公钥或证书验证签名;
  2. 检查 app_id 和商户身份;
  3. 根据 out_trade_no 查询本地订单;
  4. 校验 total_amount 是否与本地订单金额一致;
  5. 判断 trade_status;
  6. 以幂等方式更新订单并开通 VIP;
  7. 处理成功后,按照支付宝协议返回成功响应。

不能仅凭前端显示“支付成功”就开通会员。前端跳转、轮询结果以及用户提交的交易号,都不能代替服务端验签。

前端如何获知支付结果

扫码支付通常不会像网页收银台一样自动跳回当前页面,可以选择以下方式:

  • 后端收到支付宝异步通知后,通过 WebSocket 或 SSE 通知页面;
  • 前端定时查询本站的订单状态,由本站后端判断是否需要调用 alipay.trade.query 进一步确认。

前端应轮询本站的订单查询接口,不建议让浏览器直接请求支付宝接口。

const timer = setInterval(async () => {
  const response = await fetch("/api/orders/VIP202609090001/status");
  const order = await response.json();

  if (order.status === "PAID") {
    clearInterval(timer);
    window.location.href = "/vip/success";
  }
}, 2000);

轮询需要设置最长持续时间,以免页面长期发送无效请求。

哪些情况不需要当面付

如果业务流程不是展示二维码,而是跳转到支付宝收银台,就需要选择其他支付产品:

  • PC 浏览器跳转支付宝收银台:通常使用电脑网站支付;
  • 手机浏览器内发起支付:通常使用手机网站支付;
  • 原生 APP 拉起支付宝客户端:通常使用 APP 支付;
  • 网站展示二维码供用户使用支付宝扫码:通常使用当面付的 alipay.trade.precreate。

因此,支付产品的选择与“有没有 APP”无关,应根据用户发起支付的终端,以及最终采用二维码、网页跳转还是客户端唤起进行判断。

注意事项

  • 为二维码设置合理的订单有效期,过期后重新创建订单。
  • 不要让同一个 out_trade_no 对应不同的金额或商品。
  • 异步通知可能重复发送,开通 VIP 的操作必须支持幂等处理。
  • 除了检查 trade_status,还要校验签名、订单号、金额和商户身份。
  • 支付金额应使用十进制字符串处理,避免用浮点数计算。
  • 测试环境和生产环境的网关、账号、密钥及产品权限不能混用。
  • notify_url 必须能被支付宝服务器通过公网访问,不能使用 localhost。
  • 日志中不能记录应用私钥、完整支付凭证或其他敏感信息。
  • 如果接口返回产品未签约、应用无权限或商户权限不足,应先检查当面付的签约状态和应用关联关系,不要反复修改代码。

备注:内容仅供参考。