不能直接用 github.com/boombuler/barcode 生成支付二维码,因为它仅生成静态图像,不参与业务逻辑,无法携带商户号、订单号、签名、时间戳等动态参数,也不符合微信(weixin://wxpay/bizpayurl?pr=xxx)或支付宝(https://qr.alipay.com/xxx)的URL规范,扫码会报Invalid sign或OUT_OF_DATE错误。

为什么不能直接用 github.com/boombuler/barcode 生成支付二维码
因为支付场景的动态二维码不是普通图像——它必须携带有效、有时效、可验证的业务参数(如商户号、订单号、金额、签名),且需符合支付宝/微信的 URL 规范。单纯用 barcode 库只生成静态图像,没签名、没时间戳、没回调地址,扫出来直接报错或跳转失败。
常见错误现象:Invalid sign、OUT_OF_DATE、扫码后提示“该链接无法访问”。
- 微信要求
weixin://wxpay/bizpayurl?pr=xxx格式,且pr参数是服务端调用微信统一下单接口后返回的预支付交易会话标识(prepay_id经签名拼接生成) - 支付宝要求
https://qr.alipay.com/xxx,但xxx不是随便编的,得调用alipay.trade.qr.pay接口获取真实跳转码,再转成短链或二维码 -
github.com/boombuler/barcode只能画图,不参与业务逻辑,没法替代支付网关调用
正确流程:先调支付 API,再用 qrcode 生成图像
Go 后端真正要做的,是两步:1)构造合法请求体并调用支付宝/微信下单接口;2)把返回的跳转 URL(或协议 scheme)喂给二维码生成库画图。中间签名、加密、时间戳都必须由 Go 代码完成。
推荐组合:github.com/smartwalle/alipay(支付宝 SDK) + github.com/skip2/go-qrcode(轻量、无依赖、支持 PNG 字节流)。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 不要用
github.com/boombuler/barcode:它不支持 QR Code 的标准纠错等级配置,且输出格式有限,go-qrcode支持qrcode.Low/qrcode.High,移动扫码更稳 - 签名密钥、证书、app_id 必须存在环境变量或配置文件中,绝不硬编码
- 微信下单返回的是
code_url字段(weixin://...协议),支付宝返回的是qr_code字段(https://qr.alipay.com/...),二者结构不同,别混用
示例(支付宝):
qr, err := qrcode.Encode(alipayQrCodeUrl, qrcode.Medium, 256)
if err != nil {
http.Error(w, "qrcode encode failed", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "image/png")
w.Write(qr)
动态性怎么实现:URL 要带唯一订单 ID + 过期控制
所谓“动态”,本质是每个二维码对应唯一订单、有明确失效时间(通常 2–15 分钟),且不能被重复使用。这靠的是后端生成时绑定订单状态,而非二维码本身可变。
- 生成二维码前,必须在 DB 插入订单记录,状态设为
pending,并设置expires_at(如time.Now().Add(5 * time.Minute)) - 二维码内容 URL 中必须包含该订单 ID(如
https://pay.example.com/callback?id=ord_abc123),支付平台回调时也带这个 ID,才能查到原订单 - 用户扫码后未支付,超时自动关单(调用
alipay.trade.close或微信close_order);若已支付,回调里更新 DB 状态,避免重复处理 - 别试图用前端 JS 刷新二维码——移动端扫码识别耗时不稳定,刷新反而导致旧码失效、新码还没加载完,用户扫空
生产环境必须注意的三个细节
本地跑通不等于线上可用。这三个点出问题,轻则扫码失败,重则资金风险。
- HTTPS 强制:微信/支付宝要求回调地址和二维码中的跳转地址必须是 HTTPS,HTTP 地址会被拒绝。Nginx 或 ALB 上必须配好证书,且 Go 服务不自行监听 HTTP 端口
- 域名白名单:支付宝需要在开放平台配置「签约域名」和「回调域名」;微信要求公众号/小程序后台填「支付授权目录」,否则扫码后提示“商户号无权限”
- 并发安全:如果多个请求同时为同一订单生成二维码,可能重复调用下单接口,造成多笔预下单。建议用
sync.Once或 Redis 锁(key ="qr_gen_lock:" + orderID)控制
最常被忽略的是回调验签——收到支付平台通知后,必须用官方 SDK 的 VerifySign 方法校验,而不是只比对订单 ID。漏掉这步,攻击者伪造回调就能“白嫖”商品。

















