本章的內容來源是有朋友咨詢怎麼做微信公眾號信息的收發消息功能,因此本著為社區做貢獻的態度申請了個人公眾號,然後嘗試對接了一下接收公眾號內容信息的流程;要說對接其實呢也算不上,因為個人賬號只有簡單的一些接收,被動回覆等功能信息,不能群發和使用客服介面,所以本章主要分享的是怎麼接受信息和被動發送回覆信息 ...
本章的內容來源是有朋友咨詢怎麼做微信公眾號信息的收發消息功能,因此本著為社區做貢獻的態度申請了個人公眾號,然後嘗試對接了一下接收公眾號內容信息的流程;要說對接其實呢也算不上,因為個人賬號只有簡單的一些接收,被動回覆等功能信息,不能群發和使用客服介面,所以本章主要分享的是怎麼接受信息和被動發送回覆信息的實例;
在公眾平臺上綁定消息通知接收地址
這種設置的東西,其實跟著官網設置就行了,不過本人根據官網文檔一步一步設置的時候,還是遇到一些問題,因此這裡需要記錄下註意的關鍵點;首先我們登陸公眾平臺-》開發-》基本配置-》點擊“修改配置”-》這個時候會出現以下截圖:
填寫上面內容的時候需要註意以下幾點:
1. 接收的url地址必須外網能訪問並且在80埠上
2. 第一次保存“伺服器配置”時,必須在接收地址中以get方式獲取的公眾平臺通知的“echostr”參數,然後返回輸出這個“echostr”值給平臺(這樣你在公眾平臺保存服務配置的時候才能成功),這個地方官網文字描述不是很突出,不重點看的話很難發現
到此,只要做到上面兩點那麼您“伺服器配置”才能保存成功,千萬仔細哦;
分享接收公眾平臺通知信息的代碼
1 /// <summary> 2 /// 接收“服務配置”時通知的信息 格式如:signature=08c66dd8b2fd8fe43118965b336d6098642607f3&echostr=6917887702473243501×tamp=1491458849&nonce=1123949701 3 /// </summary> 4 /// <returns></returns> 5 [HttpGet] 6 public string Get() 7 { 8 9 var echostr = Request.Query["echostr"]; 10 if (string.IsNullOrWhiteSpace(echostr)) { return "別瞎搞。"; } 11 12 var sbLog = new StringBuilder(string.Empty); 13 sbLog.Append($"method:get->echostr:{echostr}->"); 14 try 15 { 16 sbLog.Append($"QueryString:{Request.QueryString.Value}->"); 17 } 18 catch (Exception ex) 19 { 20 sbLog.Append($"異常信息:{ex.Message}->"); 21 } 22 finally 23 { 24 PublicTool.WriteLog(sbLog.ToString()); 25 } 26 return echostr; 27 }
接收post過來的用戶發送的內容信息,目前公眾平臺通知的類型有: text:文本消息 image:圖形消息 voice:語音消息 video:視頻消息 shortvideo:小視頻消息 location:地理位置 link:鏈接消息;
1 /// <summary> 2 /// 接收post過來的用戶發送的內容信息 3 /// </summary> 4 /// <returns></returns> 5 [HttpPost] 6 public string Post() 7 { 8 var sbLog = new StringBuilder(string.Empty); 9 var now = DateTime.Now; 10 var reStr = string.Empty; //返回信息,1.空表示不需要再通知 2.返回正規文本內容表示回覆消息 3.其他信息表示需要再次通知內容 11 sbLog.Append($"method:post->"); 12 try 13 { 14 var str = string.Empty; 15 using (var stream = Request.Body) 16 { 17 using (var reader = new StreamReader(stream)) 18 { 19 str = reader.ReadToEnd(); 20 } 21 } 22 sbLog.Append($"str:{str}->"); 23 if (string.IsNullOrWhiteSpace(str)) { return reStr; } 24 25 var data = PublicTool._XmlDeserialize<xml>(str); 26 if (data == null) { return reStr; } 27 sbLog.Append($"ToUserName:{data.ToUserName},FromUserName:{data.FromUserName},MsgType:{data.MsgType},CreateTime:{data.CreateTime}->"); 28 29 //消息類型 對應枚舉 MsgTypeEm 30 switch (data.MsgType) 31 { 32 case "text": 33 34 break; 35 case "image": 36 break; 37 case "voice": 38 break; 39 case "video": 40 break; 41 case "shortvideo": 42 break; 43 44 case "location": 45 break; 46 case "link": 47 break; 48 } 49 50 //自動回覆信息(暫時:只有文字內容) 51 var reHuaYu = string.Empty; 52 if (data.Content.Contains("測試") || data.Content.Contains("ceshi")) 53 { 54 reHuaYu = "請儘量發一些有用的信息!"; 55 } 56 else if (data.Content.Contains("你好") || data.Content.Contains("您好") || data.Content.Contains("群主") || data.Content.Contains("在麽")) 57 { 58 reHuaYu = "您好,謝謝您的支持!"; 59 } 60 61 if (!string.IsNullOrWhiteSpace(reHuaYu)) 62 { 63 reStr = string.Format(@"<xml> 64 <ToUserName><![CDATA[{0}]]></ToUserName> 65 <FromUserName><![CDATA[{1}]]></FromUserName> 66 <CreateTime>{2}</CreateTime> 67 <MsgType><![CDATA[{3}]]></MsgType> 68 <Content><![CDATA[{4}]]></Content> 69 </xml>", 70 data.FromUserName, 71 data.ToUserName, 72 now, 73 "text", 74 reHuaYu); 75 } 76 } 77 catch (Exception ex) 78 { 79 sbLog.Append($"異常信息:{ex.Message}->"); 80 } 81 finally 82 { 83 if (!string.IsNullOrEmpty(sbLog.ToString())) 84 { 85 PublicTool.WriteLog(sbLog.ToString()); 86 } 87 } 88 return reStr; 89 }
iis和Kestrel監聽項目埠引發的一些思考,待解惑
本次我使用的是.netcore的webapi來接收通知消息,但是當公眾平臺有80埠限制的時候,頓時我蒙了,因為我伺服器iis上有一個項目是綁定了80埠的,這個時候如果使用Kestrel再綁定一個埠那肯定不行的;想到iis可以創建虛擬子應用程式(多個子應用程式對應一個大的網站配置,這樣80埠就可以共用了),思考著Kestrel是不是也可以呢,失望的是查了很多資料都暫時沒有涉及到或者是我沒有找到這方面的資料,因此只好放棄了;
下麵分享下.netcore中我操作xml序列化和反序列方法,首先需要引入 System.Xml.Serialization :
1 /// <summary> 2 /// xml字元串反序列化 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <param name="xml"></param> 6 /// <returns></returns> 7 public static T _XmlDeserialize<T>(string xml) where T : class, new() 8 { 9 T t = default(T); 10 if (string.IsNullOrEmpty(xml)) return t; 11 12 XmlSerializer serializer = new XmlSerializer(typeof(T)); 13 using (var reader = new StringReader(xml)) 14 { 15 t = (T)serializer.Deserialize(reader); 16 } 17 return t; 18 } 19 20 /// <summary> 21 /// xml序列化 22 /// </summary> 23 /// <param name="obj"></param> 24 /// <returns></returns> 25 public static string _XMLSerialize(object obj) 26 { 27 XmlSerializer xs = new XmlSerializer(obj.GetType()); 28 StringBuilder strBuidler = new StringBuilder(); 29 XmlWriterSettings setting = new XmlWriterSettings(); 30 setting.OmitXmlDeclaration = true;//去掉xml版本聲明 31 using (System.Xml.XmlWriter xw = System.Xml.XmlWriter.Create(strBuidler, setting)) 32 { 33 XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces(); 34 xmlns.Add(string.Empty, string.Empty); 35 xs.Serialize(xw, obj, xmlns); 36 } 37 return strBuidler.ToString(); 38 }
文本日誌
1 /// <summary> 2 /// 文本日誌 3 /// </summary> 4 /// <param name="content"></param> 5 /// <param name="basePath"></param> 6 public static async void WriteLog(string content, string basePath = null) 7 { 8 basePath = basePath ?? AppContext.BaseDirectory; 9 var now = DateTime.Now; 10 11 var year = now.ToString("yyyy"); 12 var month = now.ToString("MM"); 13 var date = now.ToString("dd"); 14 15 var fileName = $"{now.ToString("HH")}.txt"; 16 var path = Path.Combine(basePath, year, month, date, fileName); 17 if (!System.IO.File.Exists(path)) 18 { 19 20 basePath = Path.Combine(basePath, year); 21 if (!Directory.Exists(basePath)) { Directory.CreateDirectory(basePath); } 22 23 basePath = Path.Combine(basePath, month); 24 if (!Directory.Exists(basePath)) { Directory.CreateDirectory(basePath); } 25 26 basePath = Path.Combine(basePath, date); 27 if (!Directory.Exists(basePath)) { Directory.CreateDirectory(basePath); } 28 29 path = Path.Combine(basePath, fileName); 30 } 31 using (FileStream stream = new FileStream(path, FileMode.Append, FileAccess.Write)) 32 { 33 using (var writer = new StreamWriter(stream)) 34 { 35 await writer.WriteLineAsync($"{now.ToString("yyyy-MM-dd HH:mm:ss.fff")}:{content}"); 36 } 37 } 38 }
總結一下吧:
有點好奇為什麼微信公眾平臺使用的是xml格式數據來交互,不知道是出於什麼考慮;從介面對接上來說很簡單,就是平長的get,post方式來傳遞數據,需要註意的應該是一些細節上的問題吧;還有待解決Kestrel部署netcore時是否能創建多個子虛擬目錄問題(如果您已經知道了這個答案,請不吝賜教,謝謝);最後發一張測試的公眾號二維碼,關註後輸入:測試 或 您好,群主等信息會有我介面返回的自動回覆信息;