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>
/// 企业号回调信息接口。统一接收并处理信息的入口。 /// </summary>
public class corpapi : IHttpHandler
{ /// <summary>
/// 处理企业号的信息 /// </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. |
企业通过参数msg_signature对请求进行校验,如果确认此次GET请求来自企业号,那么企业应用对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的封装,就可以只需要关注消息如何应答的逻辑就可以了,其他的不用关心。
更多C#开发微信门户及应用-微信企业号的消息和事件的接收处理及解密 相关文章请关注PHP中文网!