接收普通微信消息

核心原理

用户给公众号发消息 → 微信服务器POST XML数据推送至你配置的回调URL(WeiXinTokenApi.aspx)。

同一个页面,要同时处理两种请求:

  • GET:微信后台配置时的Token签名校验(验证服务器地址)
  • POST:用户发消息时,微信推送XML消息数据

页面入口代码 WeiXinTokenApi.aspx.cs

if ("POST" == Request.RequestType)
{
    // POST:接收微信推送消息
    ResponseMsg();
}
else
{
    // GET:微信服务器Token校验
    CheckSignature();
}
Code language: JavaScript (javascript)

ResponseMsg() 接收消息方法

private void ResponseMsg()
{
    string postString = string.Empty;
    using (Stream stream = HttpContext.Current.Request.InputStream)
    {
        Byte[] postBytes = new Byte[stream.Length];
        stream.Read(postBytes, 0, (Int32)stream.Length);
        // 微信推送XML编码:GBK
        postString = Encoding.GetEncoding("GBK").GetString(postBytes);
    }

    // 加载XML文档
    XmlDocument xmldoc = new XmlDocument();
    xmldoc.Load(new MemoryStream(Encoding.GetEncoding("GB2312").GetBytes(postString)));
    
    // 读取消息类型 MsgType
    XmlNode MsgType = xmldoc.SelectSingleNode("/xml/MsgType");

    if(MsgType.InnerText == "text")
    {
        // 文本消息,在这里写业务逻辑:保存数据库、自动回复等
    }

    // 处理完成后,返回响应XML给微信服务器
    string responseContent = ReturnMessage(postString);
    Response.Write(responseContent);
    Response.End();
}
Code language: PHP (php)

CheckSignature() 校验方法

微信在配置回调地址时GET请求进来,校验签名,返回随机字符串 echostr

流程拆解

  1. 用户发消息 → 微信服务器 POST XML 到你的 WeiXinTokenApi.aspx
  2. 读取 Request.InputStream 获取原始报文,编码GBK
  3. XmlDocument解析XML
  4. 读取节点 /xml/MsgType 判断消息类型:text文本消息,还有image、voice等类型
  5. 业务处理:存入缓存/数据库、自动回复
  6. 拼接回复XML字符串,Response.Write 返回给微信服务器

XML消息示例(用户发文本消息)

<xml>
  <ToUserName><![CDATA[公众号ID]]></ToUserName>
  <FromUserName><![CDATA[用户OpenId]]></FromUserName>
  <CreateTime>1726789012</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[你好]]></Content>
  <MsgId>2481234567890123</MsgId>
</xml>
Code language: HTML, XML (xml)

关键点

  1. 同一个URL同时支持GET和POST,通过Request.RequestType区分
  2. 微信推送的消息XML编码是 GBK/GB2312,读取流的时候编码不能错,否则中文乱码
  3. 必须给微信服务器返回响应XML,微信才认为消息推送成功;超时会重试推送
  4. 本课程示例:把收到的XML放到缓存,直接访问页面就能查看收到的消息内容

配套 ReturnMessage 函数(构造回复xml)

private string ReturnMessage(string postXml)
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(postXml);
    string fromUser = doc.SelectSingleNode("//FromUserName").InnerText;
    string toUser = doc.SelectSingleNode("//ToUserName").InnerText;
    string replyContent = "收到消息啦";
    // 组装回复文本消息xml
    string replyXml = $"<xml><ToUserName><![CDATA[{fromUser}]]></ToUserName><FromUserName><![CDATA[{toUser}]]></FromUserName><CreateTime>{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{replyContent}]]></Content></xml>";
    return replyXml;
}
Code language: HTML, XML (xml)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注