1、企業號回呼模式的設定
和公眾號一樣,微信企業號如果需要進行二次開發,也是需要在後台設定好對應的回呼參數,如下介面所示。
設定好這些後,檢查通過後,我們就可以在自己微信應用程式伺服器上進行訊息的收發操作了。
在回呼的訊息入口處,我們需要將POST資料和普通的GET資料分開處理,GET資料是微信自身的驗證處理,POST資料是微信訊息的互動操作。
/// <summary> /// 企业号回调信息接口。统一接收并处理信息的入口。 /// </summary> public class corpapi : IHttpHandler { /// <summary> /// 处理企业号的信息 /// </summary> /// <param name="context"></param> public void ProcessRequest(HttpContext context) {
上面我們定義了一個一般應用處理程序來處理訊息。
然後我們分開不同的訊息類型(POST、GET 方式),針對性的進行處理。
if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST") { using (Stream stream = HttpContext.Current.Request.InputStream) { Byte[] postBytes = new Byte[stream.Length]; stream.Read(postBytes, 0, (Int32)stream.Length); postString = Encoding.UTF8.GetString(postBytes); } if (!string.IsNullOrEmpty(postString)) { Execute(postString, accountInfo); } } else { Auth(accountInfo); }
下面是微信對於回呼模式,驗證URL的說明。
驗證URL有效性
當你提交以上資訊時,企業號將發送GET請求到填寫的URL上,GET請求攜帶四個參數,企業在取得時需要做urldecode處理,否則會驗證不成功。
參數 | 描述 | 是否必帶 |
---|---|---|
微信加密簽名,msg_signature結合了企業填寫的token、請求中的timestamp、nonce參數、加密的訊息體 | 是 | |
時間戳 | 是 | |
隨機數字 | 是 | |
加密的隨機字串,以msg_encrypt格式提供。需要解密並回傳echostr明文,解密後有random、msg_len、msg、$CorpID四個字段,其中msg即為echostr明文 | 首次校驗時必帶 |
企業應用對echostr參數解密並原樣返回echostr明文(不能加引號),則存取驗證生效,回呼模式才能開啟。
後續回呼企業時都會在請求URL中帶上以上參數(echostr除外),校驗方式與首次驗證URL一致。 根據上面的說明,我們需要取得這些參數,然後呼叫微信提供的訊息處理函數進行加解密處理。 在驗證URL的Auth(accountInfo);操作裡面,我們可以看到核心的內容如下所示,就是獲取到這些傳遞過來的參數信息,然後交給基類處理訊息的簽名內容。#region 具体处理逻辑 string echoString = HttpContext.Current.Request.QueryString["echoStr"]; string signature = HttpContext.Current.Request.QueryString["msg_signature"];//企业号的 msg_signature string timestamp = HttpContext.Current.Request.QueryString["timestamp"]; string nonce = HttpContext.Current.Request.QueryString["nonce"]; string decryptEchoString = ""; if (new CorpBasicApi().CheckSignature(token, signature, timestamp, nonce, corpId, encodingAESKey, echoString, ref decryptEchoString)) { if (!string.IsNullOrEmpty(decryptEchoString)) { HttpContext.Current.Response.Write(decryptEchoString); HttpContext.Current.Response.End(); } } #endregion驗證程式碼部門如下所示。
/// <summary> /// 验证企业号签名 /// </summary> /// <param name="token">企业号配置的Token</param> /// <param name="signature">签名内容</param> /// <param name="timestamp">时间戳</param> /// <param name="nonce">nonce参数</param> /// <param name="corpId">企业号ID标识</param> /// <param name="encodingAESKey">加密键</param> /// <param name="echostr">内容字符串</param> /// <param name="retEchostr">返回的字符串</param> /// <returns></returns> public bool CheckSignature(string token, string signature, string timestamp, string nonce, string corpId, string encodingAESKey, string echostr, ref string retEchostr) { WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId); int result = wxcpt.VerifyURL(signature, timestamp, nonce, echostr, ref retEchostr); if (result != 0) { LogTextHelper.Error("ERR: VerifyURL fail, ret: " + result); return false; } return true; }3、企業號的訊息處理 上面介紹了,微信企業號對URL的驗證過程,還有另一個訊息處理過程,就是微信伺服器把訊息傳送給我們自己的應用伺服器進行處理的過程,我們應用伺服器需要在收到訊息後,及時進行常規回覆處理。 也就是下面的程式碼邏輯。
if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST") { using (Stream stream = HttpContext.Current.Request.InputStream) { Byte[] postBytes = new Byte[stream.Length]; stream.Read(postBytes, 0, (Int32)stream.Length); postString = Encoding.UTF8.GetString(postBytes); } if (!string.IsNullOrEmpty(postString)) { Execute(postString, accountInfo); } }同樣,我們給微信伺服器回應訊息的時候,我們也需要得到對應的參數,然後再行建構資訊回答。
string echoString = HttpContext.Current.Request.QueryString["echoStr"]; string signature = HttpContext.Current.Request.QueryString["msg_signature"];//企业号的 msg_signature string timestamp = HttpContext.Current.Request.QueryString["timestamp"]; string nonce = HttpContext.Current.Request.QueryString["nonce"];而另外一些參數訊息,則是來自我們企業號帳號的設定參數。
//获取配置参数并对加解密函数初始化 string CorpToken = accountInfo.Token; string AESKey = accountInfo.EncodingAESKey; string CorpId = accountInfo.CorpID;然後使用微信提供的訊息加解密類,就可以順利地對訊息進行加解密的處理了。具體操作代碼如下所示。
//根据参数信息,初始化微信对应的消息加密解密类 WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(CorpToken, AESKey, CorpId); //对收到的密文进行解析处理 string sMsg = ""; // 解析之后的明文 int flag = wxcpt.DecryptMsg(signature, timestamp, nonce, postStr, ref sMsg); if (flag == 0) { //LogTextHelper.Info("记录解密后的数据:"); //LogTextHelper.Info(sMsg);//记录解密后的数据 CorpApiDispatch dispatch = new CorpApiDispatch(); string responseContent = dispatch.Execute(sMsg); //加密后并发送 //LogTextHelper.Info(responseContent); string encryptResponse = ""; timestamp = DateTime.Now.DateTimeToInt().ToString(); wxcpt.EncryptMsg(responseContent, timestamp, nonce, ref encryptResponse, ref signature); HttpContext.Current.Response.ContentEncoding = Encoding.UTF8; HttpContext.Current.Response.Write(encryptResponse); } else { LogTextHelper.Info("解密消息失败!"); }最終,我們把解密完成的訊息交給對應的封裝類別進行統一處理就可以了。
CorpApiDispatch dispatch = new CorpApiDispatch(); string responseContent = dispatch.Execute(sMsg);這樣我們在企業號API的封裝,就可以只需要關注訊息如何應答的邏輯就可以了,其他的不用關心。