In the previous essay "C# Development of WeChat Portal and Application (19) - Messaging with WeChat Enterprise Account (Text, Pictures, Files, Voice, Video, Graphic Messages, etc.)" introduced the message sending with Enterprise Account, Officials specifically state that messages are sent without encryption. But on the callback server, which is the server of our website, the messages sent from WeChat are encrypted, and we need to call the class library to decrypt the messages and events. Since the official examples are incomplete, we spent a lot of time exploring. Finally, various messages and events received were successfully decrypted. This article mainly introduces the reception, processing and decryption operations of messages and events on WeChat Enterprise Accounts.
1. Setting the callback mode of the enterprise account
Like the public account, if the WeChat enterprise account needs to be developed for the second time, the corresponding callback parameters need to be set in the background, as shown in the following interface .

After setting these and passing the check, we can send and receive messages on our WeChat application server.
At the callback message entry, we need to process POST data and ordinary GET data separately. GET data is WeChat's own verification processing, and POST data is the interactive operation of WeChat messages.
????///?<summary>
????///?企業(yè)號回調(diào)信息接口。統(tǒng)一接收并處理信息的入口。????///?</summary>
????public?class?corpapi?:?IHttpHandler
????{????????///?<summary>
????????///?處理企業(yè)號的信息????????///?</summary>
????????///?<param name="context"></param>
????????public?void?ProcessRequest(HttpContext?context)
????????{
Above we defined a general application handler to process messages.
Then we separate different message types (POST, GET methods) and process them accordingly.
????????????????????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);
????????????????????}
2. Verification of WeChat callback messages
The following is WeChat’s description of callback mode and verification URL.
Verify URL validity
When you submit the above information, the enterprise account will send a GET request to the filled-in URL. The GET request carries four parameters,Enterprises need to perform urldecode processing when obtaining , otherwise the verification will fail.
Parameter |
Description |
Is it required |
msg_signature |
WeChat encrypted signature, msg_signature combines the token filled in by the enterprise, the timestamp, nonce parameter in the request, and the encrypted message body |
is |
timestamp |
Timestamp |
is |
nonce |
Random number |
is |
## echostr | Encrypted random string, provided in msg_encrypt format. It is necessary to decrypt and return the echostr plaintext. After decryption, there are four fields: random, msg_len, msg, and $CorpID. msg is the echostr plaintext. | must be included in the first verification. |
企業(yè)通過參數(shù)msg_signature對請求進行校驗,如果確認此次GET請求來自企業(yè)號,那么企業(yè)應(yīng)用對echostr參數(shù)解密并原樣返回echostr明文(不能加引號),則接入驗證生效,回調(diào)模式才能開啟。
后續(xù)回調(diào)企業(yè)時都會在請求URL中帶上以上參數(shù)(echostr除外),校驗方式與首次驗證URL一致。
根據(jù)上面的說明,我們需要獲取這些參數(shù),然后調(diào)用微信提供的消息處理函數(shù)進行加解密處理。
在驗證URL的Auth(accountInfo);操作里面,我們可以看到核心的內(nèi)容如下所示,就是獲取到這些傳遞過來的參數(shù)信息,然后交給基類處理消息的簽名內(nèi)容。
????????????????????????#region?具體處理邏輯????????????????????????string?echoString?=?HttpContext.Current.Request.QueryString["echoStr"];????????????????????????string?signature?=?HttpContext.Current.Request.QueryString["msg_signature"];//企業(yè)號的?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>
????????///?驗證企業(yè)號簽名????????///?</summary>
????????///?<param name="token">企業(yè)號配置的Token</param>
????????///?<param name="signature">簽名內(nèi)容</param>
????????///?<param name="timestamp">時間戳</param>
????????///?<param name="nonce">nonce參數(shù)</param>
????????///?<param name="corpId">企業(yè)號ID標(biāo)識</param>
????????///?<param name="encodingAESKey">加密鍵</param>
????????///?<param name="echostr">內(nèi)容字符串</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、企業(yè)號的消息處理
?上面介紹了,微信企業(yè)號對URL的驗證過程,還有另外一個消息處理過程,就是微信服務(wù)器把消息發(fā)送給我們自己的應(yīng)用服務(wù)器進行處理的過程,我們應(yīng)用服務(wù)器需要在收到消息后,及時進行常規(guī)回復(fù)處理。
也就是下面的代碼邏輯。
????????????????????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);
????????????????????????}
????????????????????}
同樣,我們給微信服務(wù)器回應(yīng)消息的時候,我們也需要獲得相應(yīng)的參數(shù),然后再行構(gòu)造信息回答。
????????????string?echoString?=?HttpContext.Current.Request.QueryString["echoStr"];????????????string?signature?=?HttpContext.Current.Request.QueryString["msg_signature"];//企業(yè)號的?msg_signature
????????????string?timestamp?=?HttpContext.Current.Request.QueryString["timestamp"];????????????string?nonce?=?HttpContext.Current.Request.QueryString["nonce"];
而另外一些參數(shù)信息,則是來源于我們企業(yè)號賬號的配置參數(shù)。
????????????//獲取配置參數(shù)并對加解密函數(shù)初始化
????????????string?CorpToken?=?accountInfo.Token;????????????string?AESKey?=?accountInfo.EncodingAESKey;????????????string?CorpId?=?accountInfo.CorpID;
然后使用微信提供的消息加解密類,就可以順利對消息進行加解密的處理了。具體操作代碼如下所示。
????????????//根據(jù)參數(shù)信息,初始化微信對應(yīng)的消息加密解密類
????????????WXBizMsgCrypt?wxcpt?=?new?WXBizMsgCrypt(CorpToken,?AESKey,?CorpId);????????????//對收到的密文進行解析處理
????????????string?sMsg?=?"";??//?解析之后的明文
????????????int?flag?=?wxcpt.DecryptMsg(signature,?timestamp,?nonce,?postStr,?ref?sMsg);????????????if?(flag?==?0)
????????????{????????????????//LogTextHelper.Info("記錄解密后的數(shù)據(jù):");????????????????//LogTextHelper.Info(sMsg);//記錄解密后的數(shù)據(jù)
????????????????CorpApiDispatch?dispatch?=?new?CorpApiDispatch();????????????????string?responseContent?=?dispatch.Execute(sMsg);????????????????//加密后并發(fā)送????????????????//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("解密消息失??!");
????????????}
最終,我們把解密完成的消息交給對應(yīng)的封裝類進行統(tǒng)一處理就可以了。
????????????????CorpApiDispatch?dispatch?=?new?CorpApiDispatch();????????????????string?responseContent?=?dispatch.Execute(sMsg);
這樣我們在企業(yè)號API的封裝,就可以只需要關(guān)注消息如何應(yīng)答的邏輯就可以了,其他的不用關(guān)心。
?
?
更多C#開發(fā)微信門戶及應(yīng)用-微信企業(yè)號的消息和事件的接收處理及解密?相關(guān)文章請關(guān)注PHP中文網(wǎng)!