C#微信公众号开发 -- (三)用户关注之后自动回复
通过了上一篇文章之后的微信开发者验证之后,我们就可以做微信公众号的代码开发了。
当我们点击关注某个公众号的时候,有时候会发现他会自动给我们回复一条消息,比如欢迎关注XXX公众号。这个功能其实是在点击关注的时候,用户触发了微信定义的事件,同时微信会返回给我们一个XML数据包,微信官方的解释如下:
推送XML数据包示例:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[subscribe]]></Event> </xml>
参数说明:
参数 | 描述 |
---|---|
ToUserName | 开发者微信号 |
FromUserName | 发送方帐号(一个OpenID) |
CreateTime | 消息创建时间 (整型) |
MsgType | 消息类型,event |
Event | 事件类型,subscribe(订阅)、unsubscribe(取消订阅) |
从示例中可以看出,如果我们想要处理用户点击的关注事件,那么必须要知道消息类型MsgType,事件类型Event。所以我们可以仿照着微信给我们的XML示例用C#建立一下事件接受的类,具体代码如下:
public class wxmessage { /// <summary> /// 本公众帐号 /// </summary> public string ToUserName { get; set; } /// <summary> /// 用户帐号 /// </summary> public string FromUserName { get; set; } /// <summary> /// 发送时间戳 /// </summary> public string CreateTime { get; set; } /// <summary> /// 发送的文本内容 /// </summary> public string Content { get; set; } /// <summary> /// 消息的类型 /// </summary> public string MsgType { get; set; } /// <summary> /// 事件名称 /// </summary> public string EventName { get; set; } //这两个属性会在后面的讲解中提到 public string Recognition { get; set; } public string EventKey { get; set; } }
事件类建立完成之后,我们就可以在wxapi.aspx页面中做事件处理的逻辑操作了,请看下面的代码:
public partial class wxapi : System.Web.UI.Page { const string _token = "在微信公众测试号后台写的那个Token"; private const string _myOpenid = "你自己微信公众测试号的appID"; string postStr = ""; protected void Page_Load(object sender, EventArgs e) { //************** 验证成为开发者的时候将此代码注释 ***********// //对微信的信息进行处理和应用 WXOpera(); //*********** 验证成为开发者之后将此代码注释 *************// //string httpMethod = Request.HttpMethod.ToLower(); //if (httpMethod == "post") //{ // //第一次验证的时候开启 // FirstValid(); //} //else //{ // Valid(); //如果不是post请求就去做开发者验证 //} } /// <summary> /// 验证成为开发者 /// </summary> private void Valid() { string echoStr = Request.QueryString["echoStr"].ToString(); if (CheckSignature()) { if (!string.IsNullOrEmpty(echoStr)) { Response.Write(echoStr); Response.End(); } } } /// <summary> /// 验证微信签名 /// </summary> /// * 将token、timestamp、nonce三个参数进行字典序排序 /// * 将三个参数字符串拼接成一个字符串进行sha1加密 /// * 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。 /// <returns></returns> private bool CheckSignature() { string signature = Request.QueryString["signature"].ToString(); string timestamp = Request.QueryString["timestamp"].ToString(); string nonce = Request.QueryString["nonce"].ToString(); string[] ArrTmp = { _token, timestamp, nonce }; Array.Sort(ArrTmp); //字典排序 string tmpStr = string.Join("", ArrTmp); tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1"); tmpStr = tmpStr.ToLower(); if (tmpStr == signature) { return true; } else { return false; } } /// <summary> /// 第一次验证配置 /// </summary> private void FirstValid() { Stream s = System.Web.HttpContext.Current.Request.InputStream; byte[] b = new byte[s.Length]; s.Read(b, 0, (int)s.Length); postStr = Encoding.UTF8.GetString(b); if (!string.IsNullOrEmpty(postStr)) { ResponseMsg(postStr); } } /// <summary> /// 返回信息结果(微信信息返回) /// </summary> /// <param name="weixinXML"></param> private void ResponseMsg(string weixinXML) { //回复消息的部分:你的代码写在这里 } /// <summary> /// 微信操作 /// </summary> private void WXOpera() { wxmessage wx = GetWxMessage(); string res = ""; if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "subscribe") { //刚关注时的时间,用于欢迎词 string content = ""; content = "您好,欢迎关注XXX公众号";
res = sendTextMessage(wx, content); HttpContext.Current.Response.Write(res); HttpContext.Current.Response.End(); } } /// <summary> /// 获取和设置微信类中的信息 /// </summary> /// <returns></returns> private wxmessage GetWxMessage() { wxmessage wx = new wxmessage(); StreamReader str = new StreamReader(Request.InputStream, Encoding.UTF8); XmlDocument xml = new XmlDocument(); xml.Load(str); str.Close(); str.Dispose(); wx.ToUserName = xml.SelectSingleNode("xml").SelectSingleNode("ToUserName").InnerText; wx.FromUserName = xml.SelectSingleNode("xml").SelectSingleNode("FromUserName").InnerText; wx.MsgType = xml.SelectSingleNode("xml").SelectSingleNode("MsgType").InnerText; if (wx.MsgType.Trim() == "text") { wx.Content = xml.SelectSingleNode("xml").SelectSingleNode("Content").InnerText; } if (wx.MsgType.Trim() == "event") { wx.EventName = xml.SelectSingleNode("xml").SelectSingleNode("Event").InnerText; wx.EventKey = xml.SelectSingleNode("xml").SelectSingleNode("EventKey").InnerText; } return wx; } /// <summary> /// 发送文字消息 /// </summary> /// <param name="wx" />获取的收发者信息 /// <param name="content" />内容 /// <returns></returns> private string sendTextMessage(wxmessage wx, string content) { string res = string.Format(Message_Text, wx.FromUserName, wx.ToUserName, DateTime.Now.Ticks, content); return res; } /// <summary> /// 普通文本消息 /// </summary> private static string Message_Text { get { return @"<xml> <ToUserName><![CDATA[{0}]]></ToUserName> <FromUserName><![CDATA[{1}]]></FromUserName> <CreateTime>{2}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{3}]]></Content> </xml>"; } } }
其中:Message_Text属性,是微信定义的发送文本消息格式,下面是微信官方给出的解释:
文本消息格式:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[你好]]></Content> </xml>
文本消息格式说明:
参数 | 是否必须 | 描述 |
---|---|---|
ToUserName | 是 | 接收方帐号(收到的OpenID) |
FromUserName | 是 | 开发者微信号 |
CreateTime | 是 | 消息创建时间 (整型) |
MsgType | 是 | text |
Content | 是 | 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示) |
注:有的朋友可能会将这里的ToUserName和FromUserName,与接收事件的ToUserName和FromUserName混淆,可能你看出来了sendTextMessage()方法中参数顺序与Message_Text属性中的顺序不一致。
然后重新将wxapi.aspx页面发布到服务器上面,随后用自己的微信号关注测试公众号(扫描测试公众号的二维码),关注完成之后,如果你能看到:您好,欢迎关注XXX公众号 ,则说明自动回复设置成功!