PAYATHON 2026

支付宝订单支付动态二维码如何生成

支付小周

结论

不能从支付 URL 中直接”提取”支付宝动态二维码。二维码只是 URL 或支付凭证的图形编码,URL 本身通常不包含二维码图片。

如果要为每笔线上订单生成可供支付宝扫码支付的动态二维码,应调用支付宝当面付的预创建接口 alipay.trade.precreate。接口调用成功后会返回 qr_code。商户将这个字符串编码成二维码图片并展示,用户扫码后即可进入该订单的支付宝支付流程,不需要先跳转到商户网页。

推荐实现流程

  1. 商户系统创建订单,并生成唯一的 out_trade_no。
  2. 调用 alipay.trade.precreate 创建支付宝预支付订单。
  3. 读取接口响应中的 qr_code。
  4. 使用二维码组件将 qr_code 编码成二维码图片。
  5. 由前端定时查询订单状态,或者等待支付宝发送异步通知。
  6. 确认交易状态为 TRADE_SUCCESS 后,再更新业务订单。

qr_code 是二维码中需要编码的原始内容,不一定是普通网页 URL。请按原值生成二维码,不要修改、解析或拼接其中的参数。

Java 调用示例

下面的示例使用支付宝 Java 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 AlipayQrCodeService {

    private static final String GATEWAY_URL =
            "https://openapi.alipay.com/gateway.do";

    public static String createQrCode(
            String appId,
            String merchantPrivateKey,
            String alipayPublicKey,
            String outTradeNo,
            String subject,
            String totalAmount) throws AlipayApiException {

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

        AlipayTradePrecreateRequest request =
                new AlipayTradePrecreateRequest();

        AlipayTradePrecreateModel model =
                new AlipayTradePrecreateModel();

        model.setOutTradeNo(outTradeNo);
        model.setSubject(subject);
        model.setTotalAmount(totalAmount);
        model.setTimeoutExpress("15m");

        request.setBizModel(model);

        // 支付宝异步通知地址,必须是公网可访问的 HTTPS 地址
        request.setNotifyUrl(
                "https://example.com/api/alipay/notify"
        );

        AlipayTradePrecreateResponse response =
                alipayClient.execute(request);

        if (!response.isSuccess()) {
            throw new IllegalStateException(
                    "创建支付宝二维码失败,code="
                            + response.getCode()
                            + ", subCode="
                            + response.getSubCode()
                            + ", message="
                            + response.getSubMsg()
            );
        }

        return response.getQrCode();
    }
}

支付宝返回的 qr_code 可以通过 ZXing 等二维码库生成图片:

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;

import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

public class QrCodeWriter {

    public static void write(
            String content,
            OutputStream outputStream) throws Exception {

        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1);

        BitMatrix matrix = new MultiFormatWriter().encode(
                content,
                BarcodeFormat.QR_CODE,
                320,
                320,
                hints
        );

        MatrixToImageWriter.writeToStream(
                matrix,
                "PNG",
                outputStream
        );
    }
}

content 必须直接使用支付宝返回的 qr_code,不要对它进行 URL 解码、截取或参数重组。

查询支付结果

成功生成二维码不等于支付成功。可以调用 alipay.trade.query 查询交易状态:

import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;

public static String queryTrade(
        AlipayClient alipayClient,
        String outTradeNo) throws AlipayApiException {

    AlipayTradeQueryRequest request =
            new AlipayTradeQueryRequest();

    AlipayTradeQueryModel model =
            new AlipayTradeQueryModel();

    model.setOutTradeNo(outTradeNo);
    request.setBizModel(model);

    AlipayTradeQueryResponse response =
            alipayClient.execute(request);

    if (!response.isSuccess()) {
        return "QUERY_FAILED";
    }

    return response.getTradeStatus();
}

常见的交易状态有:

  • WAIT_BUYER_PAY:订单已创建,等待付款。
  • TRADE_SUCCESS:付款成功。
  • TRADE_CLOSED:交易关闭。
  • TRADE_FINISHED:交易结束,不可退款。

业务系统不能根据”用户已扫码”或前端跳转结果认定付款成功。最终结果应以支付宝异步通知或服务端主动查询的结果为准。

与现有 URL 支付方式的区别

如果当前调用的是手机网站支付接口,例如 alipay.trade.wap.pay,返回内容主要用于唤起支付宝或打开收银台页面。把对应的 URL 再生成二维码,虽然可能可以扫码访问,但本质上是”扫码打开网页”,并非标准的当面付扫码模式。

应根据支付场景选择对应产品:

  • PC 网站跳转支付:通常使用 alipay.trade.page.pay。
  • 手机浏览器内支付:通常使用 alipay.trade.wap.pay。
  • 展示订单二维码供支付宝扫码:通常使用 alipay.trade.precreate。

这些接口对应不同的支付宝产品能力和签约权限。应用能否直接调用 alipay.trade.precreate,取决于是否已开通并签约相应产品,以及是否具备所需权限。

注意事项

  • 每个 out_trade_no 都应保持唯一,不能在不同业务订单之间重复使用。
  • 金额必须由服务端确定,不能直接信任前端传入的金额。
  • 私钥只能保存在服务端,不能放入网页、App 或小程序前端。
  • 收到异步通知后必须验签,同时核对 app_id、out_trade_no、金额、商户身份和交易状态。
  • 支付宝可能重复发送异步通知,因此订单更新逻辑必须保证幂等。
  • 二维码应设置合理的有效期。二维码过期后,应关闭旧订单或重新创建支付订单,不能只替换二维码图片。
  • 不建议长期保存二维码图片。保存 qr_code 和订单状态即可,需要展示时再即时生成。
  • 沙箱环境和生产环境使用不同的网关、应用标识及密钥,不能混用。
  • 支付接口名称、可用参数和签约条件可能发生调整。上线前请以支付宝开放平台当前文档及应用后台显示的权限为准。

备注:内容仅供参考。