微信公众号服务器验证必须用 GET 请求处理 signature 参数,路由需显式声明 engine.GET,禁用中间件和绑定方法,验签时按字典序拼接 token、timestamp、nonce 后 SHA1 比对,并原样返回 echostr。

微信公众号服务器验证必须用 GET 请求处理 signature 参数
微信后台配置服务器 URL 后,会向你的接口发起一个 GET 请求,带四个 query 参数:signature、timestamp、nonce、echostr。Gin 路由必须明确声明为 engine.GET("/wx/callback", handler),写成 POST 或忽略 method 直接用 Any 都会失败。
常见错误是把该接口当成普通业务接口,加了中间件(比如 JWT 验证、CORS 预检拦截),导致微信请求被 401/403 拦截或 405 Method Not Allowed;也有人在 handler 里调用了 c.ShouldBindJSON,但这是 XML/JSON 绑定逻辑,对 GET 查询参数完全无效。
- 路由注册必须显式用
GET,不能依赖泛匹配 - handler 内不要调用任何绑定方法(
ShouldBind系列) - 不要加鉴权中间件——微信不带 token,也不走你定义的 header 规则
- 确保该路径未被反向代理或 CDN 缓存(
echostr必须原样返回,不能被改写或压缩)
signature 验证逻辑:token + timestamp + nonce 拼接后 SHA1
微信要求你将自己配置的 token(字符串)、请求中的 timestamp、nonce 这三个值按字典序排序(不是时间序),拼成一个字符串,再做 SHA1 哈希,与请求里的 signature 字段比对。顺序错、大小写错、多空格、漏参数都会导致验签失败。
注意:这个 token 是你在微信公众平台「服务器配置」里填的那个字符串,必须和代码里硬编码或从配置读取的一致;它**不是** AppID、AppSecret,也不是加密用的密钥。
- 排序必须用
sort.Strings([]string{token, timestamp, nonce}),别手写 if 判断 - 拼接时不用分隔符,直接
str1 + str2 + str3 - SHA1 输出必须转成小写十六进制字符串(
hex.EncodeToString返回的就是) - 对比前建议先
strings.TrimSpace清掉signature可能带的空白符
验签通过后必须原样返回 echostr,且仅此一个字符串
验签成功后,Gin handler 必须调用 c.String(200, echostr),且不能有任何额外字符(包括换行、空格、JSON 包裹、HTML 标签)。微信会严格校验响应体是否**完全等于**传入的 echostr 值。哪怕多一个 \n,也会显示“配置失败”。
常见翻车点:用 c.JSON(200, gin.H{"data": echostr})、c.String(200, "success")、或 handler 最后忘了 return 导致走 Gin 默认 200 空响应。
- 只允许一次
c.String调用,且参数必须是echostr变量本身 - 不要在前面打印日志(
log.Println)后还继续执行,避免意外写入 response body - 确保没有全局中间件(如 logger、recovery)往 response writer 写东西
- 本地调试时可用
curl -v "https://your-domain/wx/callback?signature=xxx×tamp=xxx&nonce=xxx&echostr=xxx"手动验证
线上部署必须用 HTTPS,且域名需与公众号后台一致
微信强制要求服务器 URL 使用 HTTPS 协议,且证书必须有效(不能是自签名、过期或域名不匹配)。即使你在测试号环境,也不能用 http://localhost 或 http://127.0.0.1 —— 微信服务器根本不会发起请求。
如果你用内网穿透(frp/ngrok),务必确认穿透后的公网域名已填入公众号后台「服务器配置」,且 DNS 解析正常、端口可达。微信不会告诉你“连接超时”,只会静默失败。
- 证书建议用 Let’s Encrypt,避免使用二级域名泛解析导致 SNI 不匹配
- 公众号后台填写的 URL 必须和实际请求的 Host header 完全一致(
https://api.example.com/wx/callback≠https://www.example.com/wx/callback) - 如果用云厂商 SLB 或 API 网关,确认其透传了原始 query 参数,没做过滤或重写
- 首次配置后,微信可能缓存旧结果,改完配置要等 1–2 分钟再点“提交”
Gin 对接微信公众号服务器验证看着简单,但卡在 signature 不一致、echostr 返回不对、HTTP 协议或域名不合规这三点上的人最多。真正难的不是写代码,而是让微信的请求完整、干净地落到你的 handler 里,并原模原样吐回去。



















