微信公衆號開發已經不在是新鮮事了,不過相信也有不少小夥伴和我同樣,沒有接觸過或者剛剛接觸不久。再此,記錄下學習經歷和一些比較坑的注意點。html
首先,微信公衆號分兩種類型和兩種狀況,兩種類型分別是訂閱號和服務號,兩種狀況是,已認證或未認證的公衆號。他們分別具體的接口權限你們能夠在微信後臺的「開發者中心-接口權限」看到。算法
顯示「未得到」的接口狀態,就是須要訂閱號或服務號微信認證以後纔有擁有的權限。數據庫
簡單說,未認證的訂閱號只有基礎支持、自動回覆和發送回覆消息的接口,只有實現一些較簡單的數據交互功能,瀏覽器
那麼,什麼是接口?微信接口又是什麼意思?安全
打個比方,若是一家公司是一個系統,創業之初,你可能一我的身兼多職,同時負責營銷、財務、研發等,發展到了必定規模後爲了提升公司總體的運行效率和服務水平,你就須要聘用不一樣的人才來幫你承擔相應的一部分工做,那麼同時,你也須要向這部分人提供對應的工做權限以知足他們的工做須要,這就相似於接口的概念。服務器
微信接口簡單說,是微信公衆平臺向第三方開發者提供的一個用戶資源數據及功能的訪問/使用權限。經過對開發者提供開放統一的API接口環境,來幫助微信第三方開發者訪問微信公衆平臺的功能和資源,以達到充分自由的運用微信公衆平臺用戶資源及功能的目的。微信
在微信上,要實現這一目的,須要開啓「服務器配置」以下圖所示:微信開發
如圖所示:你們須要注意的是,一旦開啓了服務器配置,微信平臺自帶的自動回覆、自定義菜單等功能所有失效,全部的事件推送都會被轉發到你所配置的服務器地址URL上。微信公衆平臺
簡單解釋下開發者ID和服務器配置各參數的做用:curl
AppID是應用ID,也就是微信開發者編號的意思,在微信中主要用於建立微信菜單等。
AppSecret是應用密匙,與AppID是相配合的,意思可理解爲這是私密的應用編號。
URL服務器地址是微信服務器像開發者服務器推送消息和事件的地址,可理解爲你家的住址。這裏沒什麼特別要求,不管你使用什麼語言開發,只要能經過HTTP服務的80端口返回符合微信要求的XML信息便可。
Token令牌可理解爲用來驗證安全接頭暗號,讓微信服務器知道對方就是我要找的人。
EncodingAESKey可理解爲暗語加密交流,以避免你與用戶之間的交互信息被第三方獲取到後泄露敏感數據。
微信服務器就至關於一個轉發服務器,終端(手機、Pad等)發起請求至微信服務器,而後微信服務器將請求轉發給自定義服務(也就是開發者服務器,url對應的服務器)。
服務處理完畢,而後回發給微信服務器,微信服務器再將具體響應回覆到終端。
通訊協議爲:HTTP
數據格式爲:XML
具體的流程以下圖所示:
其實,咱們須要作的事情,就是對HTTP請求,作出響應。
具體的請求內容,咱們按照特定的XML格式去解析,處理完畢後,也要按照特定的XML格式返回。
咱們只須要一個簡單的實現HttpHandler便可。
固然,微信平臺還能實現更加複雜的業務,好比微信能夠做爲內嵌的瀏覽器,咱們能夠經過微信的連接,打開htm界面,而後實現本身的邏輯。
當普通微信用戶向公衆帳號發消息時,微信服務器將POST該消息到填寫的URL上。結構以下
前面的註冊及消息接入就不過多贅述了,上面咱們已經初步講解了微信公衆帳號開發的基本原理,這裏咱們來探索設計實現
主要功能介紹以下:
1)請求接口層。處理HTTP請求,及響應
2)分發層。由接口層傳入請求,而後具體分析請求類型,分發至不一樣的處理器
3)業務邏輯層。這裏是咱們的具體業務邏輯了,根據請求,實現具體的業務邏輯。
4)數據層。咱們在實現某個應用時可能須要訪問數據,能夠是數據庫或者是文件。若是是簡單應用,可能沒有這一層。
其實,具體的應用能夠在這個結構上去擴展,能夠擴展消息對象層、業務對象層、數據訪問層、功能管理層等。這裏只是提供一種思路,不侷限於此。
根據層次圖,設計流程圖,具體講述實現的各個過程。以便了解整個處理過程。以下圖所示:
根據流程圖,咱們可以清晰的瞭解整個流程,消息處理的具體實現步驟。
下面咱們針對流程進行代碼實現。
此處我是以MVC作演示,新建了一個MVC項目,右鍵新建一個通常應用程序,以下圖所示
通常應用程序裏面代碼:
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; //context.Response.Write("Hello World"); //由微信服務接收請求,具體處理請求 WeiXinService wxService = new WeiXinService(context.Request); string responseMsg = wxService.Response(); context.Response.Clear(); context.Response.Charset = "UTF-8"; context.Response.Write(responseMsg); context.Response.End(); }
爲了能功能封裝,咱們也將此封裝在了處理組件中。其實能夠放置在通常應用程序中處理的。
1)驗證簽名
若是是首次請求,須要驗證簽名。就至關於一次HTTP握手。以前在上一章中,設置的服務器URL以及token值,這個功能就是檢驗是否連接成功。
這個請求是GET請求。如下具體說明(官方):
業務邏輯:
加密/校驗流程:
<1> 將token、timestamp、nonce三個參數進行字典序排序
<2> 將三個參數字符串拼接成一個字符串進行SHA1加密
<3> 開發者得到加密後的字符串可與signature對比,標識該請求來源於微信
而官方只提供了PHP的代碼示例,不少東西在C#中並不是直譯既得。因此這裏面也有一些具體處理。先看官方的代碼:
private function checkSignature() { $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $token = TOKEN; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr); $tmpStr = implode( $tmpArr ); $tmpStr = sha1( $tmpStr ); if( $tmpStr == $signature ){ return true; }else{ return false; } }
咱們將其翻譯成C#版本:
/// <summary> /// 檢查簽名 /// </summary> /// <param name="request"></param> /// <returns></returns> private bool CheckSignature() { string signature = Request.QueryString[SIGNATURE]; string timestamp = Request.QueryString[TIMESTAMP]; string nonce = Request.QueryString[NONCE]; List<string> list = new List<string>(); list.Add(TOKEN); list.Add(timestamp); list.Add(nonce); //排序 list.Sort(); //拼串 string input = string.Empty; foreach (var item in list) { input += item; } //加密 string new_signature = SecurityUtility.SHA1Encrypt(input); //驗證 if (new_signature == signature) { return true; } else { return false; } }
這裏須要SHA1加密,具體的算法以下:
/// <summary> /// SHA1加密 /// </summary> /// <param name="intput">輸入字符串</param> /// <returns>加密後的字符串</returns> public static string SHA1Encrypt(string intput) { byte[] StrRes = Encoding.Default.GetBytes(intput); HashAlgorithm mySHA = new SHA1CryptoServiceProvider(); StrRes = mySHA.ComputeHash(StrRes); StringBuilder EnText = new StringBuilder(); foreach (byte Byte in StrRes) { EnText.AppendFormat("{0:x2}", Byte); } return EnText.ToString(); }
2)分發請求
接下來就是具體的消息請求了,這裏都是POST請求。
由於有多種消息類型,咱們經過工廠類來進行封裝,而後每種消息都有專門的處理器來進行處理。具體實現邏輯
/// <summary> /// 處理請求 /// </summary> /// <returns></returns> private string ResponseMsg() { string requestXml = Common.ReadRequest(this.Request); IHandler handler = HandlerFactory.CreateHandler(requestXml); if (handler != null) { return handler.HandleRequest(); } return string.Empty; }
處理請求的對外方法(通常應用程序中調用的方法就是這個了),即:
/// <summary> /// 處理請求,產生響應 /// </summary> /// <returns></returns> public string Response() { string method = Request.HttpMethod.ToUpper(); //驗證簽名 if (method == "GET") { if (CheckSignature()) { return Request.QueryString[ECHOSTR]; } else { return "error"; } } //處理消息 if (method == "POST") { return ResponseMsg(); } else { return "沒法處理"; } }
1)消息類型
請求的消息類型有哪些?回覆的消息類型有哪些等。
千萬要注意,請求的消息是文本類型,回覆的消息,不必定也是文本哦,能夠是圖文、音樂等任意一種可回覆的消息。具體見下表所示。
2)根據具體的消息接口,設計消息類。
這裏給出類圖,供參考。
3)針對不一樣的消息,會有不一樣的處理器,來看下具體的類圖。
4)具體業務處理
每一個handler裏面就是能夠處理具體請求。輸入的什麼消息,訪問那些數據,調用服務等,都在這裏處理。
仍是建議你們對具體的業務進行單獨封裝,在Handler中,只提供調用的接口。
由於隨着業務的增長,一個Handler可能要處理不少業務,若是全部的操做邏輯都寫在這裏,勢必影響閱讀,也不易於維護與擴展。
5)產生回覆消息
在處理完請求後,須要生成回覆消息,響應到終端。消息格式,就是咱們介紹那些消息類型,但必須是可用於回覆的,當前支持的有:文本、圖文、音樂等。
必定要明確:回覆的消息類型不必定要與請求的消息類型同樣,好比,請求是文本,回覆的能夠是圖文、音樂。
產生回覆消息的過程,其實,就是特定的消息對象格式化爲對應的XML的過程,而後將XML響應至微信服務器。
6)實例
這裏以微信用戶關注公衆帳號,而後服務端處理處理事件請求,登記用戶,並提示歡迎信息。
class EventHandler : IHandler { /// <summary> /// 請求的xml /// </summary> private string RequestXml { get; set; } /// <summary> /// 構造函數 /// </summary> /// <param name="requestXml"></param> public EventHandler(string requestXml) { this.RequestXml = requestXml; } /// <summary> /// 處理請求 /// </summary> /// <returns></returns> public string HandleRequest() { string response = string.Empty; EventMessage em = EventMessage.LoadFromXml(RequestXml); if (em.Event == EventType.Subscribe) { //註冊用戶 User user = new User(); user.OpenID = em.FromUserName; UserManager.Regester(user); //回覆歡迎消息 TextMessage tm = new TextMessage(); tm.ToUserName = em.FromUserName; tm.FromUserName = em.ToUserName; tm.CreateTime = Common.GetNowTime(); tm.Content = "歡迎您關注咱們,我是服務小二。有事兒您說話~"; response = tm.GenerateContent(); } return response; } }
當普通微信用戶向公衆帳號發消息時,微信服務器將POST該消息到填寫的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>
參數 | 描述 |
---|---|
ToUserName | 開發者微信號 |
FromUserName | 發送方賬號(一個OpenID) |
CreateTime | 消息建立時間 (整型) |
MsgType | text |
Content | 文本消息內容 |
MsgId | 消息id,64位整型 |
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[image]]></MsgType> <PicUrl><![CDATA[this is a url]]></PicUrl> <MsgId>1234567890123456</MsgId> </xml>
參數 | 描述 |
---|---|
ToUserName | 開發者微信號 |
FromUserName | 發送方賬號(一個OpenID) |
CreateTime | 消息建立時間 (整型) |
MsgType | image |
PicUrl | 圖片連接 |
MsgId | 消息id,64位整型 |
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1351776360</CreateTime> <MsgType><![CDATA[location]]></MsgType> <Location_X>23.134521</Location_X> <Location_Y>113.358803</Location_Y> <Scale>20</Scale> <Label><![CDATA[位置信息]]></Label> <MsgId>1234567890123456</MsgId> </xml>
參數 | 描述 |
---|---|
ToUserName | 開發者微信號 |
FromUserName | 發送方賬號(一個OpenID) |
CreateTime | 消息建立時間 (整型) |
MsgType | location |
Location_X | 地理位置緯度 |
Location_Y | 地理位置經度 |
Scale | 地圖縮放大小 |
Label | 地理位置信息 |
MsgId | 消息id,64位整型 |
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1351776360</CreateTime> <MsgType><![CDATA[link]]></MsgType> <Title><![CDATA[公衆平臺官網連接]]></Title> <Description><![CDATA[公衆平臺官網連接]]></Description> <Url><![CDATA[url]]></Url> <MsgId>1234567890123456</MsgId> </xml>
參數 | 描述 |
---|---|
ToUserName | 接收方微信號 |
FromUserName | 發送方微信號,若爲普通用戶,則是一個OpenID |
CreateTime | 消息建立時間 |
MsgType | 消息類型,link |
Title | 消息標題 |
Description | 消息描述 |
Url | 消息連接 |
MsgId | 消息id,64位整型 |
事件推送只支持微信4.5版本,目前開啓自定義菜單接口事件推送、關注與取消關注事件推送。其他功能即將開放,敬請期待。
<xml><ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[EVENT]]></Event> <EventKey><![CDATA[EVENTKEY]]></EventKey> </xml>
參數 | 描述 |
---|---|
ToUserName | 接收方微信號 |
FromUserName | 發送方微信號,若爲普通用戶,則是一個OpenID |
CreateTime | 消息建立時間 |
MsgType | 消息類型,event |
Event | 事件類型,subscribe(訂閱)、unsubscribe(取消訂閱)、CLICK(自定義菜單點擊事件) |
EventKey | 事件KEY值,與自定義菜單接口中KEY值對應 |
對於每個POST請求,開發者在響應包中返回特定xml結構,對該消息進行響應(現支持回覆文本、圖文、語音、視頻、音樂)。
微信服務器在五秒內收不到響應會斷掉鏈接。
回覆xml結構以下:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[content]]></Content> </xml>
參數 | 描述 |
---|---|
ToUserName | 接收方賬號(收到的OpenID) |
FromUserName | 開發者微信號 |
CreateTime | 消息建立時間 |
MsgType | text |
Content | 回覆的消息內容,長度不超過2048字節 |
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[music]]></MsgType> <Music> <Title><![CDATA[TITLE]]></Title> <Description><![CDATA[DESCRIPTION]]></Description> <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl> <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl> </Music> </xml>
參數 | 描述 |
---|---|
ToUserName | 接收方賬號(收到的OpenID) |
FromUserName | 開發者微信號 |
CreateTime | 消息建立時間 |
MsgType | music |
MusicUrl | 音樂連接 |
HQMusicUrl | 高質量音樂連接,WIFI環境優先使用該連接播放音樂 |
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>2</ArticleCount> <Articles> <item> <Title><![CDATA[title1]]></Title> <Description><![CDATA[description1]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> <item> <Title><![CDATA[title]]></Title> <Description><![CDATA[description]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> </Articles> </xml>
參數 | 描述 |
---|---|
ToUserName | 接收方賬號(收到的OpenID) |
FromUserName | 開發者微信號 |
CreateTime | 消息建立時間 |
MsgType | news |
ArticleCount | 圖文消息個數,限制爲10條之內 |
Articles | 多條圖文消息信息,默認第一個item爲大圖 |
Title | 圖文消息標題 |
Description | 圖文消息描述 |
PicUrl | 圖片連接,支持JPG、PNG格式,較好的效果爲大圖640*320,小圖80*80。 |
Url | 點擊圖文消息跳轉連接 |
更多詳細內容請參考官網開發文檔:官方開發文檔
當新用戶關注的時候,首先會收到Http請求,以後根據上文中提到的相關步驟便可完成操做,對於調試操做可參考第一篇文章:微信公衆號開發之VS遠程調試
下一篇咱們將介紹如何自定義文本消息回覆和自定義菜單欄,敬請期待吧~
注:文章部份內容截取至:http://www.cnblogs.com/yank/p/3406308.html