第一句话都会这么去写:程序猿就是苦逼,除了开发还要会写博文!哎,继上次写了C#成为微信开发者后,博友们积极查看本篇博客,在此深表感谢。顺便报一下上篇博客的网址:http://www.cnblogs.com/chenwolong/articles/4344175.html#3142905,我写的博客,还是非常希望大家多多的进行评论,有问题,大家及时沟通。嘻嘻。步入正题,本次探讨下微信的发送消息和消息的回复机制。当然,懒虫们都希望要源代码,这里也会毫不保留的给大家奉上。嘻嘻。
接收消息原理如下图,参考网址:http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
其实原理很简单,就是用户向微信公众号发送一条消息时,微信官方服务器在接收到这条消息以后,会将此条消息封装成XML的数据包并以Post的方式推送给我们自己的服务器,也就是我们C#成为开发者时,填写的URL,即:一般处理程序。详情请参考上一篇博客:http://www.cnblogs.com/chenwolong/articles/4344175.html#3142905
在此,本人列举一种类型的消息:文本消息,其他几种消息原理相同,在此不做累述。嘻嘻,如下:
文本消息:推送到我们填写的一般处理程序(URL)的数据包格式如下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[this is a test]]></Content> <MsgId>1234567890123456</MsgId> </xml>
在此,上述各种参数都是微信封装好发给我们的,特别是消息Id,有人曾经问我,消息Id怎么来的,我说:我也不知道,其实我们没必要知道,微信给我们推送了这些数据,我们只需会读取就行。
那么读取这些消息的方法怎么写呢?
其实很简单,在此多的不罗嗦,只需把代码复制就行了。
#region 获取接收事件推送的XML结构 /// <summary> /// 获取接收事件推送的XML结构 例如:用户发送的文本消息,我们就会得到上述列举的XML结构 /// </summary> /// <returns></returns> public static XmlDocument GetMsgXML() { Stream stream = HttpContext.Current.Request.InputStream; byte[] byteArray = new byte[stream.Length]; stream.Read(byteArray, 0, (int)stream.Length); string postXmlStr = System.Text.Encoding.UTF8.GetString(byteArray); XmlDocument xmldoc = new XmlDocument(); xmldoc.LoadXml(postXmlStr); return xmldoc; } #endregion
上述红色字体中,大家会看到是以Post方式进行推送的,因此,在程序开口,我们应这样写:
#region 程序入口 /// <summary> /// 程序入口 /// </summary> /// <param name="context"></param> public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; try { if (HttpContext.Current.Request.HttpMethod.ToUpper() == "GET") { Auth(); //微信接入的测试 成为开发者第一步 详情请参考上一篇博客:http://www.cnblogs.com/chenwolong/articles/4344175.html#3142905 } if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST") { //创建菜单 if (!string.IsNullOrEmpty(accessToken)) { responseMsg(); } else { accessToken = IsExistAccess_Token(); responseMsg(); } } } catch(Exception ex) { LogHelper.WriteLog("系统故障。", ex); } } #endregion
至于里面Get方式中的代码,详情请参考上一篇博客:http://www.cnblogs.com/chenwolong/articles/4344175.html#3142905
凡是看过微信公众平台开发者文档的人都知道,微信的任何一个接口,都会用到一个叫做Token的东西,在此,分享获取Token的方法如下:
#region 获取access_token /// <summary> /// 根据当前日期 判断Access_Token 是否超期 如果超期返回新的Access_Token 否则返回之前的Access_Token /// </summary> /// <param name="datetime"></param> /// <returns></returns> public static string IsExistAccess_Token() { string Token = string.Empty; DateTime YouXRQ;//有效期 // 读取XML文件中的数据,并显示出来 ,注意文件路径 string filepath = HttpContext.Current.Server.MapPath(TokenXMLAdress); StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8); XmlDocument xml = new XmlDocument(); xml.Load(str); str.Close(); str.Dispose(); Token = xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText; YouXRQ = Convert.ToDateTime(xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText); if (DateTime.Now > YouXRQ) { DateTime _youxrq = DateTime.Now; FirstAccess_Token();//重新获取Access_Token xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText = accessToken; _youxrq = _youxrq.AddSeconds(7000); xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText = _youxrq.ToString(); xml.Save(filepath); Token = accessToken;//刷新返回值 } return Token; } /// <summary> /// 获取access_tokenaccess_token有效期目前为2个小时,需要定时去刷新,当调用微信公众平台的其他接口时,如果返回数值是:40001,即:获取access_token时AppSecret错误,或者access_token无效时,从新生成access_token /// </summary> /// <param name="Url">https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx624a3d3589940769&secret=d844f681fb40b7310745900bea4eff17</param> public static void FirstAccess_Token() { HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + GetXMLstr("appid") + "&secret=" + GetXMLstr("secret") + ""); req.Method = "GET"; using (WebResponse wr = req.GetResponse()) { HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse(); StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8); string Access_TokenJson = reader.ReadToEnd(); //获取的Json数据 JObject obj = JObject.Parse(Access_TokenJson); accessToken = obj["access_token"].ToString(); } } #endregion
消息回复代码如下:
public void responseMsg() { //生成二维码 //LogHelper.WriteLog(getusersummaryPostData("2015-03-01", "2015-03-03"));//{ "begin_date": "2015-03-01", "end_date": "2015-03-03"} XmlDocument EventOrNews_XML = GetMsgXML(); string content = "";//发送的内容 string errcodeMsg = "";//返回码 Dictionary<string, object> objUserInfo = new Dictionary<string, object>();//创建用户基本信息字典 string EventName = (object)EventOrNews_XML.SelectSingleNode("xml").SelectSingleNode("Event") == null ? "" : EventOrNews_XML.SelectSingleNode("xml").SelectSingleNode("Event").InnerText;//事件类型 string EventKey = (object)EventOrNews_XML.SelectSingleNode("xml").SelectSingleNode("EventKey") == null ? "" : EventOrNews_XML.SelectSingleNode("xml").SelectSingleNode("EventKey").InnerText;//事件KEY值,与自定义菜单接口中KEY值对应 string MsgType = (object)EventOrNews_XML.SelectSingleNode("xml").SelectSingleNode("MsgType") == null ? "" : EventOrNews_XML.SelectSingleNode("xml").SelectSingleNode("MsgType").InnerText;//消息类型 语音为voice 文本为 text string UserOpenId = EventOrNews_XML.SelectSingleNode("xml").SelectSingleNode("FromUserName").InnerText;
if (!string.IsNullOrEmpty(EventName) && EventName.Trim().ToLower() == "subscribe")
{
content = "/:rose陈卧龙万岁万岁万万岁。";
}
if (!string.IsNullOrEmpty(EventName) && EventName.Trim().ToUpper() == "SCAN")//扫描二维码事件 用户已关注时的事件推送
{
}
if (!string.IsNullOrEmpty(EventName) && EventName.Trim().ToLower() == "unsubscribe")
{
}
if (!string.IsNullOrEmpty(MsgType) && MsgType.Trim().ToLower() == "voice")
{
}
if (!string.IsNullOrEmpty(MsgType) && MsgType.Trim().ToLower() == "image")
{
}
if (!string.IsNullOrEmpty(MsgType) && MsgType.Trim().ToLower() == "text")
{
}
if (!string.IsNullOrEmpty(MsgType) && MsgType.Trim().ToLower() == "transfer_customer_service")
{
}
if (!string.IsNullOrEmpty(EventName) && EventName.Trim().ToUpper() == "LOCATION")
{
} }
注:本片博客中获取Token的方法,相信大家有很多疑问要问我,在此,不做解释,大家只需看一篇博客即可:http://blog.csdn.net/hechurui/article/details/22398849
本博客中牵涉到几个变量,如下:
#region 微信开发文档 参考
//微信开发文档:http://www.cnblogs.com/wuhuacong/p/3613826.html
//微信开发文档:http://blog.csdn.net/hechurui/article/details/22399421
//Json.Net参考文档:http://www.360doc.com/content/13/0328/22/11741424_274568564.shtml
#endregion
public static string accessToken = null;
public static string commUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=??自己的&secret=??自己的";
WeiXinDB wxdb = new WeiXinDB();
static string baiduAk = "O5R6ObuaqtaC1K9FUysGTbNx";//百度API 我的AK
static string WX_application = "jiuyuantang007";//开发者微信号
//
public static string TokenXMLAdress = @"\CommonCS\XMLFile.xml";
public static string Js_sdkXMLAdress = @"\CommonCS\XML_Ticket.xml";
不过,我将这些变量的值存在了XML文件中,大家只需把这些值拿出来就行了!还有最后一个方法,就是读取XML文件中的变量值的方法,如下:
#region XML KEY /// <summary> /// XML KEY /// </summary> /// <returns></returns> public static string GetXMLstr(string Key) { string filepath = HttpContext.Current.Server.MapPath(WeiXin.TokenXMLAdress); StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8); XmlDocument xml = new XmlDocument(); xml.Load(str); str.Close(); str.Dispose(); string strValue = xml.SelectSingleNode("xml").SelectSingleNode(Key).InnerText; return strValue; } #endregion
OK,至此,全部分享给了大家,希望大家多多评论,在此谢过。
有事情的QQ1429677330,或者TEL:18911695087,我很热心的哦。