微信服务器get验证需原样返回echostr,且必须从request.querystring["echostr"]获取;checksignature需字典序排序三参数后拼接并sha1校验;post消息须用inputstream读取原始xml;access_token应使用concurrentdictionary缓存并防并发刷新。

微信服务器 GET 验证必须原样返回 echostr
接入失败最常见的原因是:收到微信 GET 请求后,没返回 echostr,或返回了带空格、换行、HTML 标签的字符串。微信只认纯文本且完全一致的 echostr 值。
关键点:
-
echostr必须从Request.QueryString["echoStr"]取,注意大小写(是echoStr,不是echostr或ECHOSTR) - 不能用
Response.Write("xxx")后再执行其他逻辑——必须立刻终止响应,推荐用Response.End()或HttpContext.Current.Response.SuppressContent = true防止后续输出污染 - 不要设置
Content-Type,微信不校验,但设成text/plain最稳妥;设成application/xml或text/html会导致验证失败 - 整个响应 body 必须只有
echostr字符串,不能有 BOM、UTF-8 签名、前后空格
CheckSignature 的三个参数排序必须严格字典序
签名验证不是简单拼接 token + timestamp + nonce,而是先排序再拼。错误写法如 string.Concat(token, timestamp, nonce) 会始终失败。
正确做法:
- 把
token、timestamp、nonce放入字符串数组,调用.OrderBy(x => x).ToArray() - 用
string.Join("", sortedArray)拼接,不是用+或string.Format - SHA1 计算前确保输入是 UTF-8 编码的 byte[],别用默认编码(尤其在中文 Windows 上)
- 计算出的哈希值转小写十六进制字符串后,与微信传来的
signature(也是小写)逐字符比对
POST 消息体解析必须用原始 XML 流,不能依赖表单解码
微信发来的消息是标准 XML,Content-Type 为 text/xml,但 ASP.NET 默认会尝试按 application/x-www-form-urlencoded 解析请求体,导致 Request.Form 为空、Request.InputStream 被提前读取而变空。
由于微信的大热,为了更好的方便使用微信的用户查询一些信息,这篇文章是入门级的微信公众平台开发教程,需要的朋友可以参考下 这篇入门教程将引导你完成如下任务: 创建百度云平台应用启用微信公众平台开发模式获取订阅、文字、图片、语音、视频消息回复文本、图文及音乐消息程序开发
安全读取方式:
- 用
HttpContext.Current.Request.InputStream,且必须在第一次访问前设置Request.InputStream.Position = 0 - 不要用
Request.BinaryRead或Request.GetBufferlessInputStream(.NET 4.5+ 中行为不稳定) - 推荐封装一个方法:
new StreamReader(Request.InputStream, Encoding.UTF8).ReadToEnd(),并确保Request.ContentLength > 0才读 - 如果用了 Web API 或 MVC,需禁用模型绑定对 XML 的自动处理,否则可能触发异常或截断数据
access_token 必须用 ConcurrentDictionary<string string></string> 缓存
微信接口要求每个 appid 共享同一个 access_token,且有效期 2 小时。多线程并发刷新时,若用普通 Dictionary + 手动锁,极易出现重复请求、token 覆盖、超限被封。
推荐方案:
- 声明静态字段:
private static readonly ConcurrentDictionary<string string> AccessTokenCache = new();</string> - 用
AccessTokenCache.GetOrAdd(appid, key => FetchNewToken(key))获取,FetchNewToken内部加分布式锁或使用内存栅栏保证单次刷新 - 缓存值建议附带过期时间戳(如
(token, expiresAt)元组),避免靠DateTime.Now判断时区/系统时间误差 - 不要用
MemoryCache,它不保证强一致性,且在 IIS 应用池回收后丢失,无跨实例同步能力
真正容易被忽略的是:微信对同一 appid 的 access_token 请求频率有限制,哪怕你缓存了,也要防止多个进程/实例同时发现过期、同时发起刷新请求——这正是 ConcurrentDictionary 的 GetOrAdd 能守住的关键防线。









