目前在做微信第三方平台开发,其中有一个需求,所有绑定的公众号使用主公众号的关键词配置,我看了下Senparc.Weixin SDK的关键词回复方法,进行了一些调整,满足了需求。
使用Senparc.Weixin SDK 底层,文件位置 DotNet.WeChat.CommonService.CustomMessageHandler.CustomMessageHandler.cs
/// <summary> /// 处理文字请求 /// </summary> /// <returns></returns> public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage) { //说明:实际项目中这里的逻辑可以交给Service处理具体信息,参考OnLocationRequest方法或/Service/LocationSercice.cs #region 书中例子 //if (requestMessage.Content == "你好") //{ // var responseMessage = base.CreateResponseMessage<ResponseMessageNews>(); // var title = "Title"; // var description = "Description"; // var picUrl = "PicUrl"; // var url = "Url"; // responseMessage.Articles.Add(new Article() // { // Title = title, // Description = description, // PicUrl = picUrl, // Url = url // }); // return responseMessage; //} //else if (requestMessage.Content == "Senparc") //{ // //相似处理逻辑 //} //else //{ // //... //} #endregion #region 历史方法 //方法一(v0.1),此方法调用太过繁琐,已过时(但仍是所有方法的核心基础),建议使用方法二到四 //var responseMessage = // ResponseMessageBase.CreateFromRequestMessage(RequestMessage, ResponseMsgType.Text) as // ResponseMessageText; //方法二(v0.4) //var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(RequestMessage); //方法三(v0.4),扩展方法,需要using Senparc.Weixin.MP.Helpers; //var responseMessage = RequestMessage.CreateResponseMessage<ResponseMessageText>(); //方法四(v0.6+),仅适合在HandlerMessage内部使用,本质上是对方法三的封装 //注意:下面泛型ResponseMessageText即返回给客户端的类型,可以根据自己的需要填写ResponseMessageNews等不同类型。 #endregion var requestHandler = requestMessage.StartHandler(); var defaultResponseMessage = base.CreateResponseMessage<ResponseMessageText>(); // 获取主公众号关键词回复配置 GetCurrentAutoreplyInfoResult AutoreplyInfoResult = GetCurrentAutoreplyInfo(); KeywordAutoReplyInfo keywordAutoReplyInfo = null; // 关键词自动回复列表 List<KeywordAutoReplyInfo_Item> keywordAutoReplyInfoItemlist = null; // 匹配的关键词列表 List<KeywordListInfoItem> keywordListInfoList = null; // 回复内容列表 List<ReplyListInfoItem> replyListInfoList = null; ReplyListInfoItem replyListInfo = null; // 关键词内容 string content = null; // 回复匹配模式 contain 0:消息内容必须和关键词严格相同,equal 1:消息内容必须和关键词严格相同 AutoReplyMatchMode matchMode; // 回复模式 reply_all 0:全部回复,random_one 1 回复其中任意一条 AutoReplyMode autoReplyMode; // 回复类型 关键词的 貌似没用 AutoReplyType keywordType; int randomone = 0; string[] keyWordArray; string wxUserName = requestMessage.ToUserName; WechatAccountSettingEntity model = new WechatAccountSettingManager().GetObjectByUserName(wxUserName); var accessToken = GlobalSetting.GetAuthorizerAccessToken(model); //int circleNum = 0; if (AutoreplyInfoResult == null) { //defaultResponseMessage.Content = "您刚才发送了文字信息:{0} ", requestMessage.Content; //return defaultResponseMessage; requestHandler.Default(() => { var responseMessageText = base.CreateResponseMessage<ResponseMessageText>(); var result = new StringBuilder(); result.AppendFormat("您刚才发送了文字信息:{0} ", requestMessage.Content); result.AppendLine(" "); result.AppendLine("目前系统还没办法给你回复~~~"); responseMessageText.Content = result.ToString(); return responseMessageText; }); } else { // 可以自定义系统的操作参数 而且可以指定必须是某个OpenId才可以 if (string.Equals("刷新", requestMessage.Content)) { requestHandler //关键字不区分大小写,按照顺序匹配成功后将不再运行下面的逻辑 .Default(() => { AutoreplyInfoResult = GetCurrentAutoreplyInfo(true); //var result = new StringBuilder(); //result.AppendLine("主公众号关键词配置已强制刷新完毕"); //result.AppendLine(" 数据内容"); //result.AppendLine(AutoreplyInfoResult.FastToJson()); defaultResponseMessage.Content = "主公众号关键词配置已强制刷新完毕"; try { //string authorizerAccessToken = GetAuthorizerAccessToken(model); CustomApi.SendText(accessToken, requestMessage.FromUserName, "现在时间是:" + DateTime.Now); } catch (Exception ex) { defaultResponseMessage.Content += ",出现异常:" + ex.Message; } return defaultResponseMessage; }); } else { keywordAutoReplyInfo = AutoreplyInfoResult.keyword_autoreply_info; if (keywordAutoReplyInfo == null) { requestHandler.Default(() => { var responseMessageText = base.CreateResponseMessage<ResponseMessageText>(); var result = new StringBuilder(); result.AppendFormat("您刚才发送了文字信息:{0} ", requestMessage.Content); result.AppendLine(" "); result.AppendLine("没有获取到任何回复信息,貌似主系统没有配置或关闭了关键词回复功能"); responseMessageText.Content = result.ToString(); return responseMessageText; }); } else { // 关键词回复信息列表 keywordAutoReplyInfoItemlist = keywordAutoReplyInfo.list; if (keywordAutoReplyInfoItemlist != null && keywordAutoReplyInfoItemlist.Any()) { // 判断输入的关键词是否在List中 foreach (var item in keywordAutoReplyInfoItemlist) { // 关键词列表 判断关键词是否符合输入的内容 keywordListInfoList = item.keyword_list_info; autoReplyMode = item.reply_mode; if (keywordListInfoList != null && keywordListInfoList.Any()) { foreach (var keywordListInfoItem in keywordListInfoList) { replyListInfoList = item.reply_list_info; content = keywordListInfoItem.content; // 是否精确匹配 matchMode = keywordListInfoItem.match_mode; keywordType = keywordListInfoItem.type; if (!string.IsNullOrWhiteSpace(content)) { // 只要包含了英文的,就是要进行分组 if (content.IndexOf(",") > 0) { keyWordArray = content.Split(','); } else { keyWordArray = new string[] { content }; } // 判断如果是随机回复一条 设置随机值 if (autoReplyMode == AutoReplyMode.random_one) { Random rd = new Random(); randomone = rd.Next(0, replyListInfoList.Count); } bool matchSuccessed = false; // 关键词列表 匹配 foreach (var keyword in keyWordArray) { if (matchMode == AutoReplyMatchMode.equal) { // 精确匹配 if (!requestHandler.MatchSuccessed && ((requestHandler.CaseSensitive && requestMessage.Content == keyword) || (!requestHandler.CaseSensitive && requestMessage.Content.ToUpper() == keyword.ToUpper()))) { matchSuccessed = true; //requestHandler.ResponseMessage = func(); break; } } else { // 只要包含就可以 if (!requestHandler.MatchSuccessed && ((requestHandler.CaseSensitive && RequestMessageTextExtension.ContainEachOther(requestMessage.Content, keyword)) || (!requestHandler.CaseSensitive && RequestMessageTextExtension.ContainEachOther(requestMessage.Content.ToUpper(), keyword.ToUpper())))) { matchSuccessed = true; //requestHandler.ResponseMessage = func(); break; } } } if (matchSuccessed) { // 使用自动回复 if (matchMode == AutoReplyMatchMode.equal) { replyListInfo = replyListInfoList[randomone]; } else { replyListInfo = replyListInfoList[0]; } AutoReplyType replyType = replyListInfo.type; SetRequestHandler(requestMessage, requestHandler, defaultResponseMessage, replyListInfo, replyType); for (int i = 0; i < replyListInfoList.Count; i++) { if (matchMode == AutoReplyMatchMode.equal && i == randomone) { continue; } else if (i == 0) { continue; } else { // 使用客服接口发送 try { replyListInfo = replyListInfoList[i]; SendCustomMessagei(accessToken, requestMessage, replyListInfo); } catch (Exception ex) { NLogHelper.Warn(ex, "关键词回复时,客户接口异常"); } } } // 匹配完毕不再执行 break; } //// 回复内容列表 //for (int i = 0; i < replyListInfoList.Count; i++) ////foreach (var replyListInfo in replyListInfoList) //{ // replyListInfo = replyListInfoList[i]; // // 是随机回复一条的模式 // if (autoReplyMode == AutoReplyMode.random_one) // { // // 此处思路不对,关键词是否符合是在HandlerRequest里判断的 需要移到外面判断?? // if (randomone == i) // { // HandlerRequest(requestHandler, requestMessage, defaultResponseMessage, replyListInfo, matchMode, keyWordArray); // break; // } // } // else // { // HandlerRequest(requestHandler, requestMessage, defaultResponseMessage, replyListInfo, matchMode, keyWordArray); // } // circleNum++; // if (requestHandler.MatchSuccessed) // { // break; // } //} } } } // requestHandler.GetResponseMessage(); // 只要匹配成功就不再继续了 //if (requestHandler.MatchSuccessed) //{ // NLogHelper.Debug(requestMessage.Content + "匹配成功:autoReplyMode = " + AutoReplyMode.random_one + ",输出 ResponseMessage=" + requestHandler.GetResponseMessage().FastToJson()); // break; //} } } else { var responseMessageText = base.CreateResponseMessage<ResponseMessageText>(); var result = new StringBuilder(); result.AppendFormat("您刚才发送了文字信息:{0} ", requestMessage.Content); result.AppendLine(" "); result.AppendLine("没有获取到关键词回复列表数据"); responseMessageText.Content = result.ToString(); return responseMessageText; } } } } if (!requestHandler.MatchSuccessed) { requestHandler.Default(() => { var responseMessageText = base.CreateResponseMessage<ResponseMessageText>(); var result = new StringBuilder(); result.AppendFormat("您刚才发送了信息:{0} ", requestMessage.Content); result.AppendLine(" "); result.AppendLine("本园目前还不能理解您的意思。"); responseMessageText.Content = result.ToString(); return responseMessageText; }); } //NLogHelper.Info("circleNum=" + circleNum); // // 下面的要替换掉 // requestHandler // //关键字不区分大小写,按照顺序匹配成功后将不再运行下面的逻辑 // .Keyword("约束", () => // { // defaultResponseMessage.Content = // @"您正在进行微信内置浏览器约束判断测试。您可以: // <a href=""http://sdk.weixin.senparc.com/FilterTest/"">点击这里</a>进行客户端约束测试(地址:http://sdk.weixin.senparc.com/FilterTest/),如果在微信外打开将直接返回文字。 // 或: // <a href=""http://sdk.weixin.senparc.com/FilterTest/Redirect"">点击这里</a>进行客户端约束测试(地址:http://sdk.weixin.senparc.com/FilterTest/Redirect),如果在微信外打开将重定向一次URL。"; // return defaultResponseMessage; // }). // //匹配任一关键字 // Keywords(new[] { "托管", "代理" }, () => // { // //开始用代理托管,把请求转到其他服务器上去,然后拿回结果 // //甚至也可以将所有请求在DefaultResponseMessage()中托管到外部。 // DateTime dt1 = DateTime.Now; //计时开始 // var agentXml = RequestDocument.ToString(); // #region 暂时转发到SDK线上Demo // agentUrl = "http://sdk.weixin.senparc.com/weixin"; // //agentToken = WebConfigurationManager.AppSettings["WeixinToken"];//Token // //修改内容,防止死循环 // var agentDoc = XDocument.Parse(agentXml); // agentDoc.Root.Element("Content").SetValue("代理转发文字:" + requestMessage.Content); // agentDoc.Root.Element("CreateTime").SetValue(DateTimeHelper.GetWeixinDateTime(DateTime.Now));//修改时间,防止去重 // agentDoc.Root.Element("MsgId").SetValue("123");//防止去重 // agentXml = agentDoc.ToString(); // #endregion // var responseXml = MessageAgent.RequestXml(this, agentUrl, agentToken, agentXml); // //获取返回的XML // //上面的方法也可以使用扩展方法:this.RequestResponseMessage(this,agentUrl, agentToken, RequestDocument.ToString()); // /* 如果有WeiweihiKey,可以直接使用下面的这个MessageAgent.RequestWeiweihiXml()方法。 // * WeiweihiKey专门用于对接www.weiweihi.com平台,获取方式见:https://www.weiweihi.com/ApiDocuments/Item/25#51 // */ // //var responseXml = MessageAgent.RequestWeiweihiXml(weiweihiKey, RequestDocument.ToString());//获取Weiweihi返回的XML // DateTime dt2 = DateTime.Now; //计时结束 // //转成实体。 // /* 如果要写成一行,可以直接用: // * responseMessage = MessageAgent.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString()); // * 或 // * // */ // var msg = string.Format(" 代理过程总耗时:{0}毫秒", (dt2 - dt1).Milliseconds); // var agentResponseMessage = responseXml.CreateResponseMessage(); // if (agentResponseMessage is ResponseMessageText) // { // (agentResponseMessage as ResponseMessageText).Content += msg; // } // else if (agentResponseMessage is ResponseMessageNews) // { // (agentResponseMessage as ResponseMessageNews).Articles[0].Description += msg; // } // return agentResponseMessage;//可能出现多种类型,直接在这里返回 // }) // .Keywords(new[] { "测试", "退出" }, () => // { // /* // * 这是一个特殊的过程,此请求通常来自于微微嗨(http://www.weiweihi.com)的“粉丝生活小助手”应用请求(https://www.weiweihi.com/User/App/Detail/1), // * 用于演示微微嗨应用商店的处理过程,由于微微嗨的应用内部可以单独设置对话过期时间,所以这里通常不需要考虑对话状态,只要做最简单的响应。 // */ // if (defaultResponseMessage.Content == "测试") // { // //进入APP测试 // defaultResponseMessage.Content = "您已经进入【粉丝生活小助手】的测试程序,请发送任意信息进行测试。发送文字【退出】退出测试对话。10分钟内无任何交互将自动退出应用对话状态。"; // } // else // { // //退出APP测试 // defaultResponseMessage.Content = "您已经退出【粉丝生活小助手】的测试程序。"; // } // return defaultResponseMessage; // }) // .Keyword("AsyncTest", () => // { // //异步并发测试(提供给单元测试使用) //#if NET45 // DateTime begin = DateTime.Now; // int t1, t2, t3; // System.Threading.ThreadPool.GetAvailableThreads(out t1, out t3); // System.Threading.ThreadPool.GetMaxThreads(out t2, out t3); // System.Threading.Thread.Sleep(TimeSpan.FromSeconds(4)); // DateTime end = DateTime.Now; // var thread = System.Threading.Thread.CurrentThread; // defaultResponseMessage.Content = string.Format("TId:{0} App:{1} Begin:{2:mm:ss,ffff} End:{3:mm:ss,ffff} TPool:{4}", // thread.ManagedThreadId, // HttpContext.Current != null ? HttpContext.Current.ApplicationInstance.GetHashCode() : -1, // begin, // end, // t2 - t1 // ); //#endif // return defaultResponseMessage; // }) // .Keyword("OPEN", () => // { // var openResponseMessage = requestMessage.CreateResponseMessage<ResponseMessageNews>(); // openResponseMessage.Articles.Add(new Article() // { // Title = "开放平台微信授权测试", // Description = @"点击进入Open授权页面。 // 授权之后,您的微信所收到的消息将转发到第三方(粉丝生活小助手)的服务器上,并获得对应的回复。 // 测试完成后,您可以登陆公众号后台取消授权。", // //Url = "http://sdk.weixin.senparc.com/OpenOAuth/JumpToMpOAuth" // Url = "http://wechat.fensishenghuo.com/Admin/WechatOpen/JumpToMpOAuth" // }); // return openResponseMessage; // }) // .Keyword("错误", () => // { // var errorResponseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>(); // //因为没有设置errorResponseMessage.Content,所以这小消息将无法正确返回。 // return errorResponseMessage; // }) // .Keyword("容错", () => // { // Thread.Sleep(4900);//故意延时1.5秒,让微信多次发送消息过来,观察返回结果 // var faultTolerantResponseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>(); // faultTolerantResponseMessage.Content = string.Format("测试容错,MsgId:{0},Ticks:{1}", requestMessage.MsgId, // DateTime.Now.Ticks); // return faultTolerantResponseMessage; // }) // .Keyword("TM", () => // { // var openId = requestMessage.FromUserName; // var checkCode = Guid.NewGuid().ToString("n").Substring(0, 3);//为了防止openId泄露造成骚扰,这里启用验证码 // TemplateMessageCollection[checkCode] = openId; // defaultResponseMessage.Content = string.Format(@"新的验证码为:{0},请在网页上输入。网址:http://sdk.weixin.senparc.com/AsyncMethods", checkCode); // return defaultResponseMessage; // }) // .Keyword("OPENID", () => // { // var openId = requestMessage.FromUserName;//获取OpenId // var userInfo = Senparc.Weixin.MP.AdvancedAPIs.UserApi.Info(appId, openId, Language.zh_CN); // defaultResponseMessage.Content = string.Format( // "您的OpenID为:{0} 昵称:{1} 性别:{2} 地区(国家/省/市):{3}/{4}/{5} 关注时间:{6} 关注状态:{7}", // requestMessage.FromUserName, userInfo.nickname, (Sex)userInfo.sex, userInfo.country, userInfo.province, userInfo.city, DateTimeHelper.GetDateTimeFromXml(userInfo.subscribe_time), userInfo.subscribe); // return defaultResponseMessage; // }) // .Keyword("EX", () => // { // var ex = new WeixinException("openid:" + requestMessage.FromUserName + ":这是一条测试异常信息");//回调过程在global的ConfigWeixinTraceLog()方法中 // defaultResponseMessage.Content = "请等待异步模板消息发送到此界面上(自动延时数秒)。 当前时间:" + DateTime.Now.ToString(); // return defaultResponseMessage; // }) // .Keyword("MUTE", () => //不回复任何消息 // { // //方案一: // return new SuccessResponseMessage(); // //方案二: // var muteResponseMessage = base.CreateResponseMessage<ResponseMessageNoResponse>(); // return muteResponseMessage; // //方案三: // base.TextResponseMessage = "success"; // return null; // }) // .Keyword("JSSDK", () => // { // defaultResponseMessage.Content = "点击打开:http://sdk.weixin.senparc.com/WeixinJsSdk"; // return defaultResponseMessage; // }) // //Default不一定要在最后一个 // .Default(() => // { // var result = new StringBuilder(); // result.AppendFormat("您刚才发送了文字信息:{0} ", requestMessage.Content); // if (CurrentMessageContext.RequestMessages.Count > 1) // { // result.AppendFormat("您刚才还发送了如下消息({0}/{1}): ", CurrentMessageContext.RequestMessages.Count, // CurrentMessageContext.StorageData); // for (int i = CurrentMessageContext.RequestMessages.Count - 2; i >= 0; i--) // { // var historyMessage = CurrentMessageContext.RequestMessages[i]; // result.AppendFormat("{0} 【{1}】{2} ", // historyMessage.CreateTime.ToString("HH:mm:ss"), // historyMessage.MsgType.ToString(), // (historyMessage is RequestMessageText) // ? (historyMessage as RequestMessageText).Content // : "[非文字类型]" // ); // } // result.AppendLine(" "); // } // result.AppendFormat("如果您在{0}分钟内连续发送消息,记录将被自动保留(当前设置:最多记录{1}条)。过期后记录将会自动清除。 ", // WeixinContext.ExpireMinutes, WeixinContext.MaxRecordCount); // result.AppendLine(" "); // //result.AppendLine("您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。 SDK官方地址:http://sdk.weixin.senparc.com"); // result.AppendLine("您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。"); // defaultResponseMessage.Content = result.ToString(); // return defaultResponseMessage; // }) // //“一次订阅消息”接口测试 // .Keyword("订阅", () => // { // defaultResponseMessage.Content = "点击打开:https://sdk.weixin.senparc.com/SubscribeMsg"; // return defaultResponseMessage; // }) // //正则表达式 // .Regex(@"^d+#d+$", () => // { // defaultResponseMessage.Content = string.Format("您输入了:{0},符合正则表达式:^\d+#\d+$", requestMessage.Content); // return defaultResponseMessage; // }); return requestHandler.GetResponseMessage() as IResponseMessageBase; }
用到的方法
/// <summary> /// 关键词自动回复 /// </summary> /// <param name="requestMessage"></param> /// <param name="requestHandler"></param> /// <param name="defaultResponseMessage"></param> /// <param name="replyListInfo"></param> /// <param name="replyType"></param> private void SetRequestHandler(RequestMessageText requestMessage, RequestMessageTextKeywordHandler requestHandler, ResponseMessageText defaultResponseMessage, ReplyListInfoItem replyListInfo, AutoReplyType replyType) { switch (replyType) { case AutoReplyType.text: var responseMessageText = base.CreateResponseMessage<ResponseMessageText>(); responseMessageText.Content = replyListInfo.content; requestHandler.ResponseMessage = responseMessageText; break; case AutoReplyType.img: var responseMessageImage = base.CreateResponseMessage<ResponseMessageImage>(); responseMessageImage.Image.MediaId = replyListInfo.content; requestHandler.ResponseMessage = responseMessageImage; break; case AutoReplyType.voice: var responseMessageVoice = base.CreateResponseMessage<ResponseMessageVoice>(); responseMessageVoice.Voice.MediaId = replyListInfo.content; requestHandler.ResponseMessage = responseMessageVoice; break; case AutoReplyType.video: var responseMessageVideo = base.CreateResponseMessage<ResponseMessageVideo>(); responseMessageVideo.Video.MediaId = replyListInfo.content; requestHandler.ResponseMessage = responseMessageVideo; break; case AutoReplyType.news: var responseMessageNews = base.CreateResponseMessage<ResponseMessageNews>(); //responseMessageNews.Articles = replyListInfo.news_info.list; //return responseMessageNews; foreach (var newsInfo in replyListInfo.news_info.list) { responseMessageNews.Articles.Add(new Article() { Title = newsInfo.title, Description = newsInfo.digest, Url = newsInfo.content_url }); } requestHandler.ResponseMessage = responseMessageNews; break; default: var result = new StringBuilder(); result.AppendFormat("您刚才发送了文字信息:{0} ", requestMessage.Content); result.AppendLine(" "); result.AppendFormat("由于没有这个类型:{0},系统不能给你任何回复", replyListInfo.type); defaultResponseMessage.Content = result.ToString(); requestHandler.ResponseMessage = defaultResponseMessage; break; } // 设置匹配成功 requestHandler.MatchSuccessed = true; } /// <summary> /// 推送客服消息 /// </summary> /// <param name="accessToken"></param> /// <param name="requestMessage"></param> /// <param name="replyListInfo"></param> /// <param name="replyType"></param> private void SendCustomMessagei(string accessToken, RequestMessageText requestMessage, ReplyListInfoItem replyListInfo) { AutoReplyType replyType = replyListInfo.type; switch (replyType) { case AutoReplyType.text: CustomApi.SendText(accessToken, requestMessage.FromUserName, replyListInfo.content); break; case AutoReplyType.img: CustomApi.SendImage(accessToken, requestMessage.FromUserName, replyListInfo.content); break; case AutoReplyType.voice: CustomApi.SendVoice(accessToken, requestMessage.FromUserName, replyListInfo.content); break; case AutoReplyType.video: CustomApi.SendVideo(accessToken, requestMessage.FromUserName, replyListInfo.content, "视频回复", "视频消息"); break; case AutoReplyType.news: List<Article> articles = new List<Article>(); foreach (var newsInfo in replyListInfo.news_info.list) { articles.Add(new Article() { Title = newsInfo.title, Description = newsInfo.digest, Url = newsInfo.content_url }); } CustomApi.SendNews(accessToken, requestMessage.FromUserName, articles); break; } }
关键词匹配方法新增的方法:注:获取主公众号关键词回复的方法见:https://www.cnblogs.com/hnsongbiao/p/9257087.html