PAYATHON 2026

支付宝如何生成消费者无需填写金额的定额收款码?

支付阿杰

结论

可以使用支付宝当面付的 alipay.trade.precreate 接口实现。

商户服务端先创建一笔指定金额的交易,支付宝会返回 qr_code。商户将这段内容生成二维码后,消费者使用支付宝扫码确认付款,不需要手动填写金额。

消费者扫码后如何验证身份,由支付宝客户端和风控策略决定。验证方式可能是支付密码、指纹、人脸识别或免密支付,商户无法强制消费者只使用支付密码。

实现流程

具体流程如下:

  1. 商户系统生成唯一订单号,并确定收款金额。
  2. 服务端调用 alipay.trade.precreate 创建预下单交易。
  3. 接口返回 qr_code。
  4. 商户端将 qr_code 渲染为二维码并展示。
  5. 消费者使用支付宝扫码并确认付款。
  6. 支付宝向商户配置的 notify_url 发送异步通知。
  7. 商户完成验签,核对订单号、金额、商户身份和交易状态后更新订单。

qr_code 是需要写入二维码的原始字符串,不是图片地址。商户需要通过二维码组件将其生成 PNG、SVG 或前端二维码。

Java 调用示例

下面使用支付宝 Java SDK 的常见调用方式。不同 SDK 版本和密钥模式的构造参数可能有所不同,请以当前接入版本的 SDK 文档为准。

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;

public class AlipayPrecreateExample {

    public static void main(String[] args) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(
                "https://openapi.alipay.com/gateway.do",
                "YOUR_APP_ID",
                "YOUR_APP_PRIVATE_KEY",
                "json",
                "UTF-8",
                "ALIPAY_PUBLIC_KEY",
                "RSA2"
        );

        String outTradeNo = "ORDER_202609090001";

        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setOutTradeNo(outTradeNo);
        model.setTotalAmount("19.90");
        model.setSubject("门店商品");
        model.setTimeoutExpress("10m");

        AlipayTradePrecreateRequest request =
                new AlipayTradePrecreateRequest();

        request.setBizModel(model);
        request.setNotifyUrl(
                "https://merchant.example.com/alipay/notify"
        );

        AlipayTradePrecreateResponse response =
                alipayClient.execute(request);

        if (response.isSuccess()) {
            String qrCode = response.getQrCode();

            System.out.println("预下单成功");
            System.out.println("二维码内容:" + qrCode);

            // 将 qrCode 交给二维码组件生成二维码图片。
        } else {
            System.err.println("预下单失败");
            System.err.println("code: " + response.getCode());
            System.err.println("subCode: " + response.getSubCode());
            System.err.println("subMsg: " + response.getSubMsg());
        }
    }
}

主要业务参数包括:

  • out_trade_no:商户订单号,在商户系统内必须唯一。
  • total_amount:订单总金额,单位为元,例如 19.90。
  • subject:订单标题。
  • timeout_express:二维码对应交易的有效期,例如 10m。
  • notify_url:支付宝异步通知地址,必须能够被支付宝服务器通过公网访问。

生产环境应使用应用私钥以及支付宝公钥或证书完成签名和验签。私钥不能放在浏览器、小程序或其他客户端中。

将返回内容生成二维码

假设接口返回:

https://qr.alipay.com/xxxxxxxxxxxxxxxx

应将整个字符串原样编码到二维码中,不要自行修改、拼接或解析该地址。

前端可以使用二维码组件生成图片,例如:

<div id="qrcode"></div>

<script src="https://cdn.example.com/qrcode.min.js"></script>
<script>
  const qrCodeContent = "服务端返回的 qr_code";

  new QRCode(document.getElementById("qrcode"), {
    text: qrCodeContent,
    width: 240,
    height: 240
  });
</script>

实际项目中,应由商户自己的服务端创建订单,再将 qr_code 返回给受控前端展示。不要从前端直接调用支付宝预下单接口,以免暴露签名密钥。

支付结果处理

二维码展示成功并不表示支付已经完成。最终支付结果应以支付宝异步通知或主动查询结果为准。

收到异步通知后,至少要完成以下校验:

  1. 使用支付宝公钥或支付宝证书验证通知签名。
  2. 检查 app_id 是否属于当前应用。
  3. 检查 seller_id 是否为预期收款方。
  4. 检查 out_trade_no 是否存在且尚未处理。
  5. 检查 total_amount 是否与本地订单金额一致。
  6. 确认 trade_status 为可确认收款的状态。
  7. 以幂等方式更新订单,避免重复通知引起重复发货。

处理成功后,通知接口应按照支付宝要求返回:

success

如果页面需要及时显示支付结果,可以定时调用 alipay.trade.query 查询订单。查询只能作为辅助机制,异步通知和验签仍然不能省略。

常见误区

收款码和预下单二维码不是一回事

使用普通支付宝收款码时,通常需要付款人输入金额。alipay.trade.precreate 返回的是针对某笔订单生成的动态二维码,订单中已经包含金额,消费者扫码后无需再次填写。

不能由商户控制密码验证方式

商户可以创建指定金额的交易,但不能要求消费者必须输入支付密码。支付宝会根据消费者设置和风控策略,决定使用密码、指纹、人脸或免密支付。

二维码不应长期重复使用

预下单二维码通常对应一笔具体交易。每笔订单都应使用新的 out_trade_no 重新预下单,不能将某次返回的二维码作为永久定额收款码反复使用。

如果业务需要长期展示固定金额二维码,可以在消费者扫码后,由商户页面实时创建新订单,再跳转到支付流程。已经支付过的交易二维码不能直接复用。

必须开通相应产品能力

调用接口前,应用和商户账号需要具备当面付及相应接口权限。调用失败时,可以结合 code、sub_code 和 sub_msg 判断问题来自签约权限、密钥配置、参数还是商户状态。

实现这一需求时,应调用 alipay.trade.precreate 获取二维码内容,再由商户系统自行渲染和展示,无需寻找单独的二维码图片接口。

备注:内容仅供参考。