微信支付v3接口需严格遵循https、平台证书校验、请求签名、响应验签四重机制;推荐使用官方wechatpay-go sdk,因其内置证书自动刷新、响应自动验签、authorization头生成等能力,而wxpay或go-pay等非官方库仍基于v2,不支持v3的aes-gcm解密与证书序列号校验。

微信支付 v3 接口不是“配好参数发个 POST 就完事”的事,必须走 HTTPS + 平台证书校验 + 请求签名 + 响应验签四重关卡,缺一不可。用错库、漏验签、证书路径错、时间戳偏差超 5 分钟,都会直接返回 401 Unauthorized 或 422 Unprocessable Entity。
为什么用 wechatpay-go 而不是 wxpay 或 go-pay
wechatpay-go(github.com/wechatpay-apiv3/wechatpay-go)是微信官方推荐的 Go SDK,v0.2.17+ 版本已内置平台证书自动刷新、响应自动验签、Authorization 头自动生成等关键能力;而 wxpay 和部分 go-pay 分支仍基于 API v2,不支持 v3 的 AES-GCM 回调解密和证书序列号校验逻辑,容易在回调验签环节静默失败。
- wechatpay-go 的
core.Client初始化时强制要求传入平台证书(*x509.Certificate),否则AutoVerifySign()会 panic - 它把签名原文拼接、Base64 编码、RSA-SHA256 签名封装进
option.WithMerchant(),避免手写出错 - 回调通知解密必须用
DecryptNotification,该函数依赖平台证书公钥 + resource.nonce + resource.ciphertext + resource.associated_data,手动实现极易丢字段或顺序错
初始化 client 必须加载两个证书文件
不是只读 apiclient_cert.pem,而是要分别加载:apiclient_cert.pem(含私钥的 PKCS#12 或 PEM 格式)用于请求签名,wechatpay_cert.pem(微信平台证书,从商户平台下载)用于响应验签和回调解密。常见错误是把两者混用,或只加载了前者。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 用
utils.LoadPrivateKeyWithPath("apiclient_key.pem")加载商户私钥(注意:不是apiclient_cert.pem里塞私钥,微信已弃用该方式) - 用
utils.LoadCertificateWithPath("wechatpay_cert.pem")加载平台证书,返回*x509.Certificate切片 -
mchCertSerialNumber必须与平台证书中Subject.SerialNumber完全一致,大小写敏感,不能从配置硬编码,应从证书解析获取
统一下单后返回的 code_url 不能直接跳转
Native 支付返回的 code_url 是一个 long polling URL,前端需用 QRCode 库渲染成二维码供用户扫码;若误当跳转链接重定向,微信会拒绝并返回 {"code":"PARAM_ERROR","message":"无效的参数"}。
- 后端不要做
http.Redirect,只返回 JSON:{"code_url": "weixin://wxpay/bizpayurl?pr=xxx"} - 小程序场景必须调用
/v3/pay/transactions/jsapi,传openid,返回payment字段供wx.requestPayment使用 - 金额单位是分,
TotalFee字段在 v3 接口已改为amount.total(int),且必须为整数,传"100"而非1.00
回调通知处理最易被忽略的三件事
微信回调不是“收个 POST 解析 JSON 就更新订单”,漏掉任一环都可能造成资金损失或重复发货。
- 必须先用
core.ParseNotifyRequest解析原始 body + header,提取resource.encrypted_message,再交由DecryptNotification解密,不能直接json.Unmarshal(r.Body) - 解密后得到的 JSON 中,
resource.algorithm必须是"AEAD_AES_256_GCM",否则拒绝处理(防降级攻击) - 验签前必须检查
event_type == "TRANSACTION.SUCCESS",且out_trade_no对应本地未完成订单;同时用 RedisSETNX notify_id 1 EX 300去重,防止同一通知因网络问题多次到达
平台证书有效期 2 年,但微信可能提前 30 天轮换;wechatpay-go 的 core.AutoRefreshCertificate() 需配合定时任务触发,否则某天凌晨突然所有请求变 401——这个点没日志、不报错、只静默失败,最容易被忽略。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










