記一次接收微信公衆平臺推送消息的實例

本章的內容來源是有朋友諮詢怎麼作微信公衆號信息的收發消息功能,所以本着爲社區作貢獻的態度申請了我的公衆號,而後嘗試對接了一下接收公衆號內容信息的流程;要說對接其實呢也算不上,由於我的帳號只有簡單的一些接收,被動回覆等功能信息,不能羣發和使用客服接口,因此本章主要分享的是怎麼接受信息和被動發送回覆信息的實例;web

在公衆平臺上綁定消息通知接收地址

這種設置的東西,其實跟着官網設置就好了,不過本人根據官網文檔一步一步設置的時候,仍是遇到一些問題,所以這裏須要記錄下注意的關鍵點;首先咱們登錄公衆平臺-》開發-》基本配置-》點擊「修改配置」-》這個時候會出現如下截圖:api

填寫上面內容的時候須要注意如下幾點:服務器

1. 接收的url地址必須外網能訪問而且在80端口微信

2. 第一次保存「服務器配置」時,必須在接收地址中以get方式獲取的公衆平臺通知的「echostr」參數,而後返回輸出這個「echostr」值給平臺(這樣你在公衆平臺保存服務配置的時候才能成功),這個地方官網文字描述不是很突出,不重點看的話很難發現微信公衆平臺

到此,只要作到上面兩點那麼您「服務器配置」才能保存成功,千萬仔細哦;async

 

分享接收公衆平臺通知信息的代碼

 1 /// <summary>
 2         /// 接收「服務配置」時通知的信息  格式如:signature=08c66dd8b2fd8fe43118965b336d6098642607f3&echostr=6917887702473243501&timestamp=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:連接消息;ide

 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是否是也能夠呢,失望的是查了不少資料都暫時沒有涉及到或者是我沒有找到這方面的資料,所以只好放棄了;post

下面分享下.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時是否能建立多個子虛擬目錄問題(若是您已經知道了這個答案,請不吝賜教,謝謝);最後發一張測試的公衆號二維碼,關注後輸入:測試 或 您好,羣主等信息會有我接口返回的自動回覆信息;

相關文章
相關標籤/搜索