/// <summary> /// 核心执行 过程的 验签和解密 /// </summary> /// <param name="recXml">消息内容</param> /// <param name="signature">微信加密签名</param> /// <param name="timestamp">时间戳</param> /// <param name="nonce">随机数</param> /// <returns>验证结果及相应的消息内容体 (如果加密模式,返回的是解密后的明文)</returns> private Resp <string> PrepareExecute(string recXml, string signature, string timestamp, string nonce) { if (string.IsNullOrEmpty(recXml)) { return(new Resp <string>().WithResp(RespTypes.ObjectNull, "接收的消息体为空!")); } var resCheck = WXChatHelper.CheckSignature(ApiConfig.Token, signature, timestamp, nonce); if (!resCheck.IsSuccess()) { return(new Resp <string>().WithResp(resCheck));// resCheck.ConvertToResult<string>(); } if (ApiConfig.SecurityType == WXSecurityType.None) { return(new Resp <string>(recXml)); } var dirs = WXChatHelper.ChangXmlToDir(recXml, out XmlDocument xmlDoc); if (dirs == null || !dirs.TryGetValue("Encrypt", out var encryStr) || string.IsNullOrEmpty(encryStr)) { return(new Resp <string>().WithResp(RespTypes.ObjectNull, "加密消息为空")); } var recMsgXml = Cryptography.WXAesDecrypt(encryStr, ApiConfig.EncodingAesKey); return(new Resp <string>(recMsgXml)); }
/// <summary> /// 消息处理入口 /// </summary> /// <param name="contentXml">内容信息</param> /// <param name="signature">签名信息</param> /// <param name="timestamp">时间戳</param> /// <param name="nonce">随机字符创</param> /// <param name="echostr">验证服务器参数,如果存在则只进行签名验证,并将在结果data中返回</param> /// <returns>消息结果,Data为响应微信数据,如果出错Message为错误信息</returns> public Resp <string> Process(string contentXml, string signature, string timestamp, string nonce, string echostr) { // 一. 检查是否是服务器验证 if (!string.IsNullOrEmpty(echostr)) { return(CheckServerValid(signature, timestamp, nonce, echostr)); } // 二. 正常消息处理 var checkRes = PrepareExecute(contentXml, signature, timestamp, nonce); if (!checkRes.IsSuccess()) { return(new Resp <string>().WithResp(checkRes)); //checkRes.ConvertToResult<string>(); } var contextRes = Execute(checkRes.data); if (!contextRes.IsSuccess()) { return(new Resp <string>().WithResp(contextRes));// contextRes.ConvertToResult<string>(); } var resultString = contextRes.data.ReplyMsg.ToReplyXml(); if (ApiConfig.SecurityType != WXSecurityType.None && !string.IsNullOrEmpty(contextRes.data.ReplyMsg.MsgType)) { return(WXChatHelper.EncryptMsg(resultString, ApiConfig)); } return(new Resp <string>(resultString)); }
/// <summary> /// 核心执行方法 过程中的 委托方代码执行 /// </summary> /// <param name="recMsgXml">传入消息的xml</param> /// <returns></returns> protected virtual Resp <WXChatContext> Execute(string recMsgXml) { var recMsgDirs = WXChatHelper.ChangXmlToDir(recMsgXml, out XmlDocument xmlDoc); recMsgDirs.TryGetValue("MsgType", out var msgType);// recMsgDirs["MsgType"].ToLower(); string eventName = null; if (msgType == "event") { if (!recMsgDirs.TryGetValue("Event", out eventName)) { return(new Resp <WXChatContext>().WithResp(RespTypes.ParaError, "事件消息数据中未发现 事件类型(Event)字段!")); } } var processor = GetBasicMsgProcessor(msgType, eventName); if (!(processor?.CanExecute).HasValue) { processor = GetCustomProcessor(msgType, eventName, recMsgDirs); if (!(processor?.CanExecute).HasValue) { processor = GetRegProcessor(msgType, eventName); } } var context = processor != null && processor.CanExecute ? ExecuteProcessor(xmlDoc, recMsgDirs, processor.CreateNewInstance(), processor.Execute) : ExecuteProcessor(xmlDoc, recMsgDirs, new WXBaseRecMsg(), null); ExecuteEnd(context); return(new Resp <WXChatContext>(context)); }
/// <summary> /// 核心执行 过程的 验签和解密 /// </summary> /// <returns>验证结果及相应的消息内容体 (如果加密模式,返回的是解密后的明文)</returns> private static StrResp Prepare(WXChatConfig appConfig, string recXml, string signature, string msg_signature, string timestamp, string nonce) { var isEncryptMsg = appConfig.SecurityType == WXSecurityType.Safe; if (!isEncryptMsg) { var resCheck = WXChatHelper.CheckSignature(appConfig.Token, signature, timestamp, nonce, String.Empty); return(!resCheck.IsSuccess() ? new StrResp().WithResp(resCheck) : new StrResp(recXml)); } if (string.IsNullOrEmpty(msg_signature)) { return(new StrResp().WithResp(RespTypes.ParaError, "msg_signature 消息体验证签名参数为空!")); } var xmlDoc = WXChatHelper.GetXmlDocment(recXml); var encryStr = xmlDoc?.FirstChild["Encrypt"]?.InnerText; if (string.IsNullOrEmpty(encryStr)) { return(new StrResp().WithResp(RespTypes.ObjectNull, "安全接口的加密字段为空!")); } var cryptMsgCheck = WXChatHelper.CheckSignature(appConfig.Token, msg_signature, timestamp, nonce, encryStr); if (!cryptMsgCheck.IsSuccess()) { return(new StrResp().WithResp(cryptMsgCheck)); } var recMsgXml = Cryptography.AESDecrypt(encryStr, appConfig.EncodingAesKey); return(new StrResp(recMsgXml)); }
/// <summary> /// 核心执行方法 /// </summary> /// <param name="recMsgXml">传入消息的xml</param> /// <returns></returns> protected virtual async Task <Resp <WXChatContext> > Processing(string recMsgXml) { var recMsgDirs = WXChatHelper.ChangXmlToDir(recMsgXml, out var xmlDoc); recMsgDirs.TryGetValue("MsgType", out var msgType); string eventName = null; if (msgType == "event") { if (!recMsgDirs.TryGetValue("Event", out eventName)) { return(new Resp <WXChatContext>().WithResp(RespTypes.ParaError, "事件消息数据中未发现 事件类型(Event)字段!")); } } var processor = GetInternalMsgProcessor(msgType, eventName) ?? GetCustomProcessor(msgType, eventName, recMsgDirs); var context = await(processor != null ? ExecuteProcessor(xmlDoc, recMsgDirs, processor) : ExecuteProcessor(xmlDoc, recMsgDirs, SingleInstance <InternalWXChatProcessor> .Instance)); await ExecuteEnd(context); return(new Resp <WXChatContext>(context)); }
/// <summary> /// 服务器验证 /// </summary> /// <param name="signature"></param> /// <param name="timestamp"></param> /// <param name="nonce"></param> /// <param name="echostr"></param> /// <returns></returns> public Resp <string> CheckServerValid(string signature, string timestamp, string nonce, string echostr) { var checkSignRes = WXChatHelper.CheckSignature(ApiConfig.Token, signature, timestamp, nonce); var resultRes = new Resp <string>().WithResp(checkSignRes);// checkSignRes.ConvertToResult<string>(); resultRes.data = resultRes.IsSuccess() ? echostr : string.Empty; return(resultRes); }
/// <summary> /// 消息处理入口 /// </summary> /// <param name="contentXml">内容信息</param> /// <param name="signature">签名信息,请注意不是[msg_signature]</param> /// <param name="msg_signature">消息体签名</param> /// <param name="timestamp">时间戳</param> /// <param name="nonce">随机字符创</param> /// <param name="echostr">验证服务器参数,如果存在则只进行签名验证,并将在结果data中返回</param> /// <returns>消息结果,Data为响应微信数据,如果出错Message为错误信息</returns> public async Task <StrResp> Process(string contentXml, string signature, string msg_signature, string timestamp, string nonce, string echostr) { if (string.IsNullOrEmpty(contentXml) || string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce)) { return(new StrResp().WithResp(RespTypes.ParaError, "消息相关参数错误!")); } var appConfigRes = await GetMeta(); if (!appConfigRes.IsSuccess()) { return(new StrResp().WithResp(appConfigRes)); } var appConfig = appConfigRes.data; // 一. 检查是否是微信服务端首次地址配置验证 if (!string.IsNullOrEmpty(echostr)) { return(CheckServerValid(appConfig, signature, timestamp, nonce, echostr)); } var checkRes = Prepare(appConfig, contentXml, signature, msg_signature, timestamp, nonce); if (!checkRes.IsSuccess()) { return(new StrResp().WithResp(checkRes)); } var contextRes = await Processing(checkRes.data); if (!contextRes.IsSuccess()) { return(new StrResp().WithResp(contextRes)); } var resultString = contextRes.data.ReplyMsg.ToReplyXml(); if (appConfig.SecurityType != WXSecurityType.None && !string.IsNullOrEmpty(contextRes.data.ReplyMsg.MsgType)) { return(WXChatHelper.EncryptMsg(resultString, appConfig)); } return(new StrResp(resultString)); }