이전 에세이 "C# WeChat 포털 및 애플리케이션 개발(19) - WeChat 기업 계정의 메시징 전송(텍스트, 그림, 파일, 음성, 비디오, 그래픽 메시지 등)"에서 기업 계정의 메시지 전송에 대해 소개했습니다. , 관계자는 메시지가 암호화되지 않고 전송된다고 구체적으로 명시합니다. 하지만 저희 웹사이트의 서버인 콜백 서버에서는 WeChat에서 보낸 메시지가 암호화되어 있는데, 메시지와 이벤트의 암호를 해독하려면 클래스 라이브러리를 호출해야 하므로, 공식 예제가 불완전하여 많은 시간을 소비했습니다. 마침내, 수신된 다양한 메시지와 이벤트가 성공적으로 해독되었습니다. 이 문서에서는 주로 WeChat 기업 계정의 메시지 및 이벤트 수신, 처리 및 암호 해독 작업을 소개합니다.
공식 계정과 동일합니다. WeChat 기업 계정에 2차 개발이 필요한 경우 백그라운드에서 해당 콜백 매개변수도 설정해야 합니다. 다음 인터페이스에 표시된 대로.
이를 설정하고 확인을 통과하면 자체 WeChat 애플리케이션 서버에서 메시지를 보내고 받을 수 있습니다.
콜백 메시지 입력 시 POST 데이터와 일반 GET 데이터를 별도로 처리해야 합니다. GET 데이터는 WeChat 자체 확인 처리이고 POST 데이터는 WeChat 메시지의 대화형 작업입니다.
/// <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); }
다음은 WeChat의 콜백 모드 및 확인 URL에 대한 지침입니다.
URL 유효성 확인
위 정보를 제출하면 기업 계정은 입력된 URL로 GET 요청을 보냅니다. GET 요청에는 4개의 매개변수가 포함됩니다. 기업은 을 얻을 때 urldecode 처리를 수행해야 합니다. 그렇지 않으면 확인이 실패합니다.
参数 | 描述 | 是否必带 |
---|---|---|
msg_signature | 微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体 | 是 |
timestamp | 时间戳 | 是 |
nonce | 随机数 | 是 |
echostr | 加密的随机字符串,以msg_encrypt格式提供。需要解密并返回echostr明文,解密后有random、msg_len、msg、$CorpID四个字段,其中msg即为echostr明文 | 首次校验时必带 |
企业通过参数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; }
上面介绍了,微信企业号对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中文网!