這兩天項目需要在微信上面開一個接口,就研究了一下,過程很艱難,結果很理想,下面我就介紹一下微信開發需要注意的地方。
1,賬號問題
/* 首先說第一個你得選擇公眾平台(開放平台貌似是做應用集成的,這個沒有仔細研究,如果有誰了解,希望告訴我一聲),在公眾平台我們需要注冊賬號,賬號還分兩種,個人類型和企業類型,其中個人類型的只能申請訂閱號,而企業類型的才可以搞到服務號,訂閱號只能手工或者配置一些關鍵詞去做事情,服務號才能部署一些智能的東東,需要高級開發權限只能是服務號,所以如果你是個人,想要針對用戶發過來的消息去回復不同的內容,洗洗睡吧。 */
搞開發的都知道上面那段話的意思,是的,我給注釋了,我今天在登陸訂閱號的時候,發現訂閱號也有高級功能的,可能我那個時候沒有通過審核吧,OK,不妨礙下面的分享。
2,開發模式
很簡單,當你拿到你的服務賬號的時候,你會發現,在功能中有個高級功能(在訂閱賬號里面是沒有高級功能這個選項的),之后你可以選擇開通哪種方式。目前開發和編輯只能啟動一個。
3,配置服務器
微信接口只有一個URL,任何數據都是通過這個URL和你的服務器進行連接的(GET或者POST)都需要走這個接口,下面會說說兩個用到的地方。
4,驗證服務器
在填寫你的服務器URL之后,微信會帶上幾個參數去訪問你的URL,你只需要返回特定的數據就OK了,具體方法也可以查看此鏈接:http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
在連接中有部分php的代碼可以參考,下面我將我的代碼貼一下,在這邊我走了很多彎路,所以我盡量貼的全一點
1 /// <summary> 2 /// 驗證微信簽名 3 /// </summary> 4 /// <param name="sigNature">微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。</param> 5 /// <param name="timestamp">時間戳</param> 6 /// <param name="nonce">隨機數</param> 7 /// <param name="echoStr">隨機字符串</param> 8 /// <returns>開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務器,請原樣返回echostr參數內容,則接入生效,成為開發者成功,否則接入失敗。</returns> 9 [System.Web.Http.AcceptVerbs("GET")] 10 [System.Web.Http.ActionName("Api")] 11 [ApiExplorerSettings(IgnoreApi = false)] 12 public HttpResponseMessage CheckSignature(string sigNature, string timestamp, string nonce, string echoStr) 13 { 14 var content = 15 string.Format("SigNature:{0}\nTimestamp:{1}\nNonce:{2}\nEchoStr:{3}", 16 sigNature, timestamp, nonce, echoStr); 17 logger.Debug(content); // 此處的log你可以刪掉 18 19 var list = new string[] { timestamp, nonce, TOKEN }; 20 Array.Sort(list); 21 var tmpArr = string.Join("", list); 22 var tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpArr, "SHA1").ToLower(); 23 24 if (tmpStr == sigNature && !string.IsNullOrEmpty(echoStr)) //根據微信的驗證規則做判斷 25 return Tools.GetReturn(echoStr); 26 27 return Tools.GetReturn("error"); 28 }
之所以寫了GetReturn這個函數是因為MVC給我的結果封裝了,每次我返回一個字符串的時候他都會在外層添加一對引號,微信還傻不愣登的不認識。。。。這個函數主要就是給我去除MVC封裝的
1 public static HttpResponseMessage GetReturn(string message) 2 { 3 return new HttpResponseMessage 4 { 5 Content = new StringContent(message, Encoding.UTF8, "text/html") 6 }; 7 }
上面的CheckSignature是一個GET的接口,主要就是驗證微信服務的,當然,你仔細研究下微信說的也可以發現,當你收到echoStr的時候,直接return其實就OK了,不必多出驗證的步驟。
5,消息接收接口
我只關注了一個功能,當用戶發送消息的時候我要回復用戶消息,而且只關注文本消息就OK了(其實別的類型的消息原理都差不多)。
我們需要注意這邊的幾點:
a,此接口的ActionName和上面驗證的接口是一樣的,這樣,他們在外面訪問就是相同的URL,只是訪問的Method不同罷了。
1 [System.Web.Http.AcceptVerbs("POST")] 2 [System.Web.Http.ActionName("Api")] 3 [ApiExplorerSettings(IgnoreApi = false)] 4 public HttpResponseMessage ReceiveMessage()
b,這種獲取消息內容的方法我也是研究了好久才找到的,費死勁了。
1 var message = Request.Content.ReadAsStringAsync().Result;
c,在這個接口他POST過來很多的變量,我都用正則給他搞到了
1 var toUserName = GetItemValue(message, ToUserNameReg); 2 var fromUserName = GetItemValue(message, FromUserNameReg); 3 var createTime = GetItemValue(message, CreateTimeReg); 4 var msgType = GetItemValue(message, MsgTypeReg); 5 var content = GetItemValue(message, ContentReg); 6 var msgId = GetItemValue(message, MsgIdReg); 7 var eventStr = GetItemValue(message, EventReg); 8 var eventKey = GetItemValue(message, EventKeyReg);
d,我只關注其中兩種類型的事件:event and text,event值得是關注和解除關注,在關注的時候要表示感謝不是;發過來的text,我需要找到回復的內容。
switch (msgType) { case "text": { } case "event": { } default: return Tools.GetReturn("error"); }
e,全部代碼在這里:
1 private static readonly Regex ToUserNameReg = new Regex(@"(?<=<ToUserName><!\[CDATA\[).*?(?=\]\]></ToUserName>)", RegexOptions.Compiled); 2 private static readonly Regex FromUserNameReg = new Regex(@"(?<=<FromUserName><!\[CDATA\[).*?(?=\]\]></FromUserName>)", RegexOptions.Compiled); 3 private static readonly Regex CreateTimeReg = new Regex(@"(?<=<CreateTime>)\d*?(?=</CreateTime>)", RegexOptions.Compiled); 4 private static readonly Regex MsgTypeReg = new Regex(@"(?<=<MsgType><!\[CDATA\[).*?(?=\]\]></MsgType>)", RegexOptions.Compiled); 5 private static readonly Regex ContentReg = new Regex(@"(?<=<Content><!\[CDATA\[).*?(?=\]\]></Content>)", RegexOptions.Compiled); 6 private static readonly Regex MsgIdReg = new Regex(@"(?<=<MsgId>)\d*?(?=</MsgId>)", RegexOptions.Compiled); 7 private static readonly Regex EventReg = new Regex(@"(?<=<Event><!\[CDATA\[).*?(?=\]\]></Event>)", RegexOptions.Compiled); 8 private static readonly Regex EventKeyReg = new Regex(@"(?<=<EventKey><!\[CDATA\[).*?(?=\]\]></EventKey>)", RegexOptions.Compiled);
1 /// <summary> 2 /// 接受微信消息,如果需要反饋,則調用回復接口進行答復 3 /// </summary> 4 /// <param name="ToUserName">開發者微信號</param> 5 /// <param name="FromUserName">發送方帳號(一個OpenID)</param> 6 /// <param name="CreateTime">消息創建時間 (整型)</param> 7 /// <param name="MsgType">text</param> 8 /// <param name="Content">文本消息內容</param> 9 /// <param name="MsgId">消息id,64位整型</param> 10 /// <returns>successful or not</returns> 11 [System.Web.Http.AcceptVerbs("POST")] 12 [System.Web.Http.ActionName("Api")] 13 [ApiExplorerSettings(IgnoreApi = false)] 14 public HttpResponseMessage ReceiveMessage() 15 { 16 var message = Request.Content.ReadAsStringAsync().Result; 17 18 var toUserName = GetItemValue(message, ToUserNameReg); 19 var fromUserName = GetItemValue(message, FromUserNameReg); 20 var createTime = GetItemValue(message, CreateTimeReg); 21 var msgType = GetItemValue(message, MsgTypeReg); 22 var content = GetItemValue(message, ContentReg); 23 var msgId = GetItemValue(message, MsgIdReg); 24 var eventStr = GetItemValue(message, EventReg); 25 var eventKey = GetItemValue(message, EventKeyReg); 26 27 var logStr = string.Format("Message:{8}\n\nToUserName:{0}\nFromUserName:{1}\nCreateTime:{2}\nMsgType:{3}\nContent:{4}\nMsgId:{5}\nEvent:{6}\nEventKey:{7}", 28 toUserName, fromUserName, createTime, msgType, content, msgId, eventStr, eventKey, message); 29 logger.Debug(logStr); 30 31 switch (msgType) 32 { 33 case "text": 34 { 35 var returnMessage = Tools.GetCategory(content); // 這塊是獲取反饋信息的方法,你的和我的應該不一樣,所以這塊你得修改一下。 36 var sendMessage = GetSendMessage(fromUserName, returnMessage, toUserName); 37 logger.Debug("MsgId:" + msgId + Environment.NewLine + sendMessage); 38 39 return Tools.GetReturn(sendMessage); // 這個函數在上面已經貼出來了,在這塊就不在貼了 40 } 41 case "event": 42 { 43 if (eventStr == "subscribe") // 關注事件 44 { 45 var returnMessage = "歡迎關注**賬號 [微笑]"; 46 var sendMessage = GetSendMessage(fromUserName, returnMessage, toUserName); 47 return Tools.GetReturn(sendMessage); 48 } 49 return Tools.GetReturn("error"); 50 } 51 default: 52 return Tools.GetReturn("error"); 53 } 54 }
1 /// <summary> 2 /// 獲取消息體中正則所能匹配到的內容 3 /// </summary> 4 /// <param name="message">消息內容</param> 5 /// <param name="regex">正則</param> 6 /// <returns>返回正則匹配的所有內容</returns> 7 [ApiExplorerSettings(IgnoreApi = true)] 8 private string GetItemValue(string message, Regex regex) 9 { 10 if(regex.IsMatch(message)) 11 return regex.Match(message).Value; 12 return ""; 13 }
1 /// <summary> 2 /// 發送被動響應消息 3 /// </summary> 4 /// <param name="ToUserName">接收方帳號(收到的OpenID)</param> 5 /// <param name="Content">回復的消息內容(換行:在content中能夠換行,微信客戶端就支持換行顯示)</param> 6 /// <param name="FromUserName">開發者微信號</param> 7 /// <param name="CreateTime">消息創建時間 (整型)</param> 8 /// <param name="MsgType">text</param> 9 /// <returns></returns> 10 [System.Web.Http.AcceptVerbs("POST")] 11 [System.Web.Http.ActionName("GetSendMessage")] 12 [ApiExplorerSettings(IgnoreApi = false)] 13 public string GetSendMessage(string ToUserName, string Content, string FromUserName = Developer, 14 string MsgType = "text") 15 { 16 var createTime = Tools.ConvertDateTimeToInt(DateTime.Now); 17 18 return 19 string.Format(@"<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>{2}</CreateTime><MsgType><![CDATA[{3}]]></MsgType><Content><![CDATA[{4}]]></Content></xml>", ToUserName, FromUserName, createTime, MsgType, Content); 20 }
現在能想到的地方就是這些了,如果有什么問題歡迎留言。
記在這里,以后學習。