PAYATHON 2026

商家扣款、扫码支付及免密签约如何获取QRCODE二维码

支付小周

结论

接口在 QRCODE 模式下返回 orderStr 后,通常无需再调用接口获取二维码图片。orderStr 是二维码承载的原始内容,商户端可以用二维码生成库将其编码为 QR Code 图片,再展示给用户扫码。

请直接使用接口返回的 orderStr,不要解析、拼接、修改,也不要预先进行 URL Decode。扫码得到的内容必须与接口原始返回值完全一致。

处理步骤

  1. 调用签约或支付接口,将渠道设置为 QRCODE。
  2. 确认接口的业务响应成功。
  3. 读取响应中的 orderStr。
  4. 使用 ZXing、QRCode.js 等二维码库生成图片。
  5. 向用户展示二维码,并通过查询接口或异步通知确认最终的签约、支付结果。

生成二维码只是将字符串转换为图形,不会改变订单或签约状态。

Java 示例

下面使用 ZXing 将 orderStr 生成为 PNG 二维码:

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>${zxing.version}</version>
</dependency>

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>${zxing.version}</version>
</dependency>

请将 ${zxing.version} 替换为项目已经验证并统一管理的版本。

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

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

public class QrCodeUtils {

    public static void writeQrCode(
            String orderStr,
            int width,
            int height,
            OutputStream outputStream) throws Exception {

        if (orderStr == null || orderStr.isBlank()) {
            throw new IllegalArgumentException("orderStr must not be empty");
        }

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

        QRCodeWriter writer = new QRCodeWriter();
        BitMatrix matrix = writer.encode(
                orderStr,
                BarcodeFormat.QR_CODE,
                width,
                height,
                hints
        );

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

也可以在 Web 接口中直接输出二维码:

@GetMapping(value = "/sign/qrcode", produces = "image/png")
public void getSignQrCode(HttpServletResponse response) throws Exception {
    String orderStr = callSignApi();

    response.setContentType("image/png");
    QrCodeUtils.writeQrCode(
            orderStr,
            320,
            320,
            response.getOutputStream()
    );
}

前端示例

如果后端将 orderStr 返回给前端,也可以由前端二维码组件生成:

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

<script src="qrcode.min.js"></script>
<script>
  const orderStr = response.orderStr;

  new QRCode(document.getElementById("qrcode"), {
    text: orderStr,
    width: 320,
    height: 320,
    correctLevel: QRCode.CorrectLevel.M
  });
</script>

即使 orderStr 包含 &、+、=、% 等字符,也应将它作为普通字符串直接传给二维码组件,不要手工拆分参数。

为什么只返回 orderStr

二维码是对字符串的图形编码。许多支付或签约接口只生成可供扫码的业务内容,并不提供 PNG、JPEG 等图片文件,所以接口返回的是 orderStr,二维码图片需要由商户自行生成。

不同接口对返回字段的定义可能有所区别:

  • 如果接口文档明确将 orderStr 定义为 QRCODE 渠道的二维码内容,可以直接编码。
  • 如果调用预创建类扫码支付接口,文档可能约定使用 qr_code 字段,此时应优先读取 qr_code。
  • 如果调用 App 支付接口,返回的 orderStr 可能是提供给客户端支付 SDK 的订单参数,未必能用作二维码内容。

具体用法应以当前接口文档对 orderStr 的字段说明为准,不能只根据字段名称判断。

注意事项

  • 生成二维码前,必须确认接口返回了业务成功结果,不要将错误报文生成二维码。
  • 必须保持 orderStr 原样不变。重新编码、解码、插入换行或调整参数顺序,都可能导致验签失败。
  • 不要在公开日志中输出完整的 orderStr,其中可能包含订单、签约或授权相关信息。
  • 二维码可能有有效期。过期后应重新调用接口生成,不要长期缓存或重复使用。
  • 用户扫码只表示进入了签约或支付流程,并不代表操作已经成功。最终状态应以服务端查询结果或经过验签的异步通知为准。
  • 如果生成的二维码无法识别,可以先用扫码工具检查扫描结果是否与原始 orderStr 逐字符一致,再排查应用、环境和接口渠道配置。

备注:内容仅供参考。