商家扣款、扫码支付及免密签约如何获取QRCODE二维码
支付小周
结论
接口在 QRCODE 模式下返回 orderStr 后,通常无需再调用接口获取二维码图片。orderStr 是二维码承载的原始内容,商户端可以用二维码生成库将其编码为 QR Code 图片,再展示给用户扫码。
请直接使用接口返回的 orderStr,不要解析、拼接、修改,也不要预先进行 URL Decode。扫码得到的内容必须与接口原始返回值完全一致。
处理步骤
- 调用签约或支付接口,将渠道设置为
QRCODE。 - 确认接口的业务响应成功。
- 读取响应中的
orderStr。 - 使用 ZXing、QRCode.js 等二维码库生成图片。
- 向用户展示二维码,并通过查询接口或异步通知确认最终的签约、支付结果。
生成二维码只是将字符串转换为图形,不会改变订单或签约状态。
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逐字符一致,再排查应用、环境和接口渠道配置。
备注:内容仅供参考。
