.net实现微信公众账号接口开发

说起微信公众帐号,大家都不会陌生,使用这个平台能给网站或系统增加一个新亮点,直接进入正题吧,在使用之前一定要仔细阅读官方API文档。

API文档地址:http://mp.weixin.qq.com/wiki/index.php
 
使用.net实现的方法:

//微信接口地址 页面代码:

  1. weixin _wx = new weixin();  
  2. string postStr = "";  
  3. if (Request.HttpMethod.ToLower() == "post")  
  4. {  
  5. Stream s = System.Web.HttpContext.Current.Request.InputStream;  
  6. byte[] b = new byte[s.Length];  
  7. s.Read(b, 0, (int)s.Length);  
  8. postStr = Encoding.UTF8.GetString(b);  
  9. if (!string.IsNullOrEmpty(postStr)) //请求处理  
  10. {  
  11. _wx.Handle(postStr);   
  12. }  
  13. }  
  14. else 
  15. {  
  16. _wx.Auth();  

具体处理类

  1. /// <summary>  
  2. /// 微信公众平台操作类  
  3. /// </summary>  
  4. public class weixin  
  5. {  
  6. private string Token = "my_weixin_token"; //换成自己的token  
  7. public void Auth()  
  8. {  
  9. string echoStr = System.Web.HttpContext.Current.Request.QueryString["echoStr"];  
  10. if (CheckSignature()) //校验签名是否正确  
  11. {  
  12. if (!string.IsNullOrEmpty(echoStr))  
  13. {  
  14. System.Web.HttpContext.Current.Response.Write(echoStr); //返回原值表示校验成功  
  15. System.Web.HttpContext.Current.Response.End();  
  16. }  
  17. }  
  18. }  
  19.  
  20.  
  21. public void Handle(string postStr)  
  22. {  
  23. //封装请求类  
  24. XmlDocument doc = new XmlDocument();  
  25. doc.LoadXml(postStr);  
  26. XmlElement rootElement = doc.DocumentElement;  
  27. //MsgType  
  28. XmlNode MsgType = rootElement.SelectSingleNode("MsgType");  
  29. //接收的值--->接收消息类(也称为消息推送)  
  30. RequestXML requestXML = new RequestXML();  
  31. requestXML.ToUserName = rootElement.SelectSingleNode("ToUserName").InnerText;  
  32. requestXML.FromUserName = rootElement.SelectSingleNode("FromUserName").InnerText;  
  33. requestXML.CreateTime = rootElement.SelectSingleNode("CreateTime").InnerText;  
  34. requestXML.MsgType = MsgType.InnerText;  
  35.  
  36. //根据不同的类型进行不同的处理  
  37. switch (requestXML.MsgType)  
  38. {  
  39. case "text": //文本消息  
  40. requestXML.Content = rootElement.SelectSingleNode("Content").InnerText;  
  41. break;  
  42. case "image": //图片  
  43. requestXML.PicUrl = rootElement.SelectSingleNode("PicUrl").InnerText;  
  44. break;  
  45. case "location": //位置  
  46. requestXML.Location_X = rootElement.SelectSingleNode("Location_X").InnerText;  
  47. requestXML.Location_Y = rootElement.SelectSingleNode("Location_Y").InnerText;  
  48. requestXML.Scale = rootElement.SelectSingleNode("Scale").InnerText;  
  49. requestXML.Label = rootElement.SelectSingleNode("Label").InnerText;  
  50. break;  
  51. case "link": //链接  
  52. break;  
  53. case "event": //事件推送 支持V4.5+  
  54. break;  
  55. }  
  56.  
  57. //消息回复  
  58. ResponseMsg(requestXML);  
  59. }  
  60.  
  61.  
  62. /// <summary>  
  63. /// 验证微信签名  
  64. /// * 将token、timestamp、nonce三个参数进行字典序排序  
  65. /// * 将三个参数字符串拼接成一个字符串进行sha1加密  
  66. /// * 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。  
  67. /// </summary>  
  68. /// <returns></returns>  
  69. private bool CheckSignature()  
  70. {  
  71. string signature = System.Web.HttpContext.Current.Request.QueryString["signature"];  
  72. string timestamp = System.Web.HttpContext.Current.Request.QueryString["timestamp"];  
  73. string nonce = System.Web.HttpContext.Current.Request.QueryString["nonce"];  
  74. //加密/校验流程:  
  75. //1. 将token、timestamp、nonce三个参数进行字典序排序  
  76. string[] ArrTmp = { Token, timestamp, nonce };   
  77. Array.Sort(ArrTmp);//字典排序  
  78. //2.将三个参数字符串拼接成一个字符串进行sha1加密  
  79. string tmpStr = string.Join("", ArrTmp);  
  80. tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");  
  81. tmpStr = tmpStr.ToLower();  
  82. //3.开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。  
  83. if (tmpStr == signature)  
  84. {  
  85. return true;  
  86. }  
  87. else 
  88. {  
  89. return false;  
  90. }  
  91. }  
  92.  
  93. /// <summary>  
  94. /// 消息回复(微信信息返回)  
  95. /// </summary>  
  96. /// <param name="requestXML">The request XML.</param>  
  97. private void ResponseMsg(RequestXML requestXML)  
  98. {  
  99. try 
  100. {  
  101. string resxml = "";  
  102. //主要是调用数据库进行关键词匹配自动回复内容,可以根据自己的业务情况编写。  
  103. //1.通常有,没有匹配任何指令时,返回帮助信息  
  104. AutoResponse mi = new AutoResponse(requestXML.Content, requestXML.FromUserName);  
  105.  
  106. switch (requestXML.MsgType)  
  107. {  
  108. case "text":  
  109. //在这里执行一系列操作,从而实现自动回复内容.   
  110. string _reMsg = mi.GetReMsg();  
  111. if (mi.msgType == 1)  
  112. {  
  113. resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[news]]></MsgType><Content><![CDATA[]]></Content><ArticleCount>2</ArticleCount><Articles>";  
  114. resxml += mi.GetRePic(requestXML.FromUserName);  
  115. resxml += "</Articles><FuncFlag>1</FuncFlag></xml>";  
  116. }  
  117. else 
  118. {  
  119. resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[" + _reMsg + "]]></Content><FuncFlag>1</FuncFlag></xml>";  
  120. }  
  121. break;  
  122. case "location":  
  123. string city = GetMapInfo(requestXML.Location_X, requestXML.Location_Y);  
  124. if (city == "0")  
  125. {  
  126. resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[好啦,我们知道您的位置啦。您可以:" + mi.GetDefault() + "]]></Content><FuncFlag>1</FuncFlag></xml>";  
  127. }  
  128. else 
  129. {  
  130. resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[好啦,我们知道您的位置啦。您可以:" + mi.GetDefault() + "]]></Content><FuncFlag>1</FuncFlag></xml>";  
  131. }  
  132. break;  
  133. case "image":  
  134. //图文混合的消息 具体格式请见官方API“回复图文消息”   
  135. break;  
  136. }  
  137.  
  138. System.Web.HttpContext.Current.Response.Write(resxml);  
  139. WriteToDB(requestXML, resxml, mi.pid);  
  140. }  
  141. catch (Exception ex)  
  142. {  
  143. //WriteTxt("异常:" + ex.Message + "Struck:" + ex.StackTrace.ToString());  
  144. //wx_logs.MyInsert("异常:" + ex.Message + "Struck:" + ex.StackTrace.ToString());  
  145. }  
  146. }  
  147.  
  148.  
  149. /// <summary>  
  150. /// unix时间转换为datetime  
  151. /// </summary>  
  152. /// <param name="timeStamp"></param>  
  153. /// <returns></returns>  
  154. private DateTime UnixTimeToTime(string timeStamp)  
  155. {  
  156. DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));  
  157. long lTime = long.Parse(timeStamp + "0000000");  
  158. TimeSpan toNow = new TimeSpan(lTime);  
  159. return dtStart.Add(toNow);  
  160. }  
  161.  
  162.  
  163. /// <summary>  
  164. /// datetime转换为unixtime  
  165. /// </summary>  
  166. /// <param name="time"></param>  
  167. /// <returns></returns>  
  168. private int ConvertDateTimeInt(System.DateTime time)  
  169. {  
  170. System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));  
  171. return (int)(time - startTime).TotalSeconds;  
  172. }  
  173.  
  174.  
  175. /// <summary>  
  176. /// 调用百度地图,返回坐标信息  
  177. /// </summary>  
  178. /// <param name="y">经度</param>  
  179. /// <param name="x">纬度</param>  
  180. /// <returns></returns>  
  181. public string GetMapInfo(string x, string y)  
  182. {  
  183. try 
  184. {  
  185. string res = string.Empty;  
  186. string parame = string.Empty;  
  187. string url = "http://maps.googleapis.com/maps/api/geocode/xml";  
  188.  
  189. parame = "latlng=" + x + "," + y + "&language=zh-CN&sensor=false";//此key为个人申请  
  190. res = webRequestPost(url, parame);  
  191.  
  192. XmlDocument doc = new XmlDocument();  
  193. doc.LoadXml(res);  
  194.  
  195. XmlElement rootElement = doc.DocumentElement;  
  196. string Status = rootElement.SelectSingleNode("status").InnerText;  
  197.  
  198. if (Status == "OK")  
  199. {  
  200. //仅获取城市  
  201. XmlNodeList xmlResults = rootElement.SelectSingleNode("/GeocodeResponse").ChildNodes;  
  202. for (int i = 0; i < xmlResults.Count; i++)  
  203. {  
  204. XmlNode childNode = xmlResults[i];  
  205. if (childNode.Name == "status") {  
  206. continue;  
  207. }  
  208. string city = "0";  
  209. for (int w = 0; w < childNode.ChildNodes.Count; w++)  
  210. {  
  211. for (int q = 0; q < childNode.ChildNodes[w].ChildNodes.Count; q++)  
  212. {  
  213. XmlNode childeTwo = childNode.ChildNodes[w].ChildNodes[q];  
  214. if (childeTwo.Name == "long_name")  
  215. {  
  216. city = childeTwo.InnerText;  
  217. }  
  218. else if (childeTwo.InnerText == "locality")  
  219. {  
  220. return city;  
  221. }  
  222. }  
  223. }  
  224. return city;  
  225. }  
  226. }  
  227. }  
  228. catch (Exception ex)  
  229. {  
  230. //WriteTxt("map异常:" + ex.Message.ToString() + "Struck:" + ex.StackTrace.ToString());  
  231. return "0";  
  232. }   
  233. return "0";  
  234. }  
  235.  
  236.  
  237. /// <summary>  
  238. /// Post 提交调用抓取  
  239. /// </summary>  
  240. /// <param name="url">提交地址</param>  
  241. /// <param name="param">参数</param>  
  242. /// <returns>string</returns>  
  243. public string webRequestPost(string url, string param)  
  244. {  
  245. byte[] bs = System.Text.Encoding.UTF8.GetBytes(param);  
  246. HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url + "?" + param);  
  247. req.Method = "Post";  
  248. req.Timeout = 120 * 1000;  
  249. req.ContentType = "application/x-www-form-urlencoded;";  
  250. req.ContentLength = bs.Length;  
  251.  
  252. using (Stream reqStream = req.GetRequestStream())  
  253. {  
  254. reqStream.Write(bs, 0, bs.Length);  
  255. reqStream.Flush();  
  256. }  
  257.  
  258. using (WebResponse wr = req.GetResponse())  
  259. {  
  260. //在这里对接收到的页面内容进行处理  
  261. Stream strm = wr.GetResponseStream();  
  262. StreamReader sr = new StreamReader(strm, System.Text.Encoding.UTF8);  
  263.  
  264. string line;  
  265. System.Text.StringBuilder sb = new System.Text.StringBuilder();  
  266. while ((line = sr.ReadLine()) != null)  
  267. {  
  268. sb.Append(line + System.Environment.NewLine);  
  269. }  
  270. sr.Close();  
  271. strm.Close();  
  272. return sb.ToString();  
  273. }  
  274. }  
  275.  
  276. /// <summary>  
  277. /// 将本次交互信息保存至数据库中  
  278. /// </summary>  
  279. /// <param name="requestXML"></param>  
  280. /// <param name="_xml"></param>  
  281. /// <param name="_pid"></param>  
  282. private void WriteToDB(RequestXML requestXML, string _xml, int _pid)  
  283. {  
  284. WeiXinMsg wx = new WeiXinMsg();  
  285. wx.FromUserName = requestXML.FromUserName;  
  286. wx.ToUserName = requestXML.ToUserName;  
  287. wx.MsgType = requestXML.MsgType;  
  288. wx.Msg = requestXML.Content;  
  289. wx.Creatime = requestXML.CreateTime;  
  290. wx.Location_X = requestXML.Location_X;  
  291. wx.Location_Y = requestXML.Location_Y;  
  292. wx.Label = requestXML.Label;  
  293. wx.Scale = requestXML.Scale;  
  294. wx.PicUrl = requestXML.PicUrl;  
  295. wx.reply = _xml;  
  296. wx.pid = _pid;  
  297. try 
  298. {  
  299. wx.Add();  
  300. }  
  301. catch (Exception ex)  
  302. {  
  303. //wx_logs.MyInsert(ex.Message);  
  304. //ex.message;  
  305. }  
  306. }  

响应类MODEL

  1. #region 微信请求类 RequestXML  
  2. /// <summary>  
  3. /// 微信请求类  
  4. /// </summary>  
  5. public class RequestXML  
  6. {  
  7. private string toUserName = "";  
  8. /// <summary>  
  9. /// 消息接收方微信号,一般为公众平台账号微信号  
  10. /// </summary>  
  11. public string ToUserName  
  12. {  
  13. get { return toUserName; }  
  14. set { toUserName = value; }  
  15. }  
  16.  
  17. private string fromUserName = "";  
  18. /// <summary>  
  19. /// 消息发送方微信号  
  20. /// </summary>  
  21. public string FromUserName  
  22. {  
  23. get { return fromUserName; }  
  24. set { fromUserName = value; }  
  25. }  
  26.  
  27. private string createTime = "";  
  28. /// <summary>  
  29. /// 创建时间  
  30. /// </summary>  
  31. public string CreateTime  
  32. {  
  33. get { return createTime; }  
  34. set { createTime = value; }  
  35. }  
  36.  
  37. private string msgType = "";  
  38. /// <summary>  
  39. /// 信息类型 地理位置:location,文本消息:text,消息类型:image  
  40. /// </summary>  
  41. public string MsgType  
  42. {  
  43. get { return msgType; }  
  44. set { msgType = value; }  
  45. }  
  46.  
  47. private string content = "";  
  48. /// <summary>  
  49. /// 信息内容  
  50. /// </summary>  
  51. public string Content  
  52. {  
  53. get { return content; }  
  54. set { content = value; }  
  55. }  
  56.  
  57. private string location_X = "";  
  58. /// <summary>  
  59. /// 地理位置纬度  
  60. /// </summary>  
  61. public string Location_X  
  62. {  
  63. get { return location_X; }  
  64. set { location_X = value; }  
  65. }  
  66.  
  67. private string location_Y = "";  
  68. /// <summary>  
  69. /// 地理位置经度  
  70. /// </summary>  
  71. public string Location_Y  
  72. {  
  73. get { return location_Y; }  
  74. set { location_Y = value; }  
  75. }  
  76.  
  77. private string scale = "";  
  78. /// <summary>  
  79. /// 地图缩放大小  
  80. /// </summary>  
  81. public string Scale  
  82. {  
  83. get { return scale; }  
  84. set { scale = value; }  
  85. }  
  86.  
  87. private string label = "";  
  88. /// <summary>  
  89. /// 地理位置信息  
  90. /// </summary>  
  91. public string Label  
  92. {  
  93. get { return label; }  
  94. set { label = value; }  
  95. }  
  96.  
  97. private string picUrl = "";  
  98. /// <summary>  
  99. /// 图片链接,开发者可以用HTTP GET获取  
  100. /// </summary>  
  101. public string PicUrl  
  102. {  
  103. get { return picUrl; }  
  104. set { picUrl = value; }  
  105. }  
  106. }  
  107. #endregion 
原文地址:https://www.cnblogs.com/Alex80/p/4236058.html