微信公众号回复
仔细查看微信公众平台回复的内容:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543
注:目前微信公众号回复的图文格式只支持单图文,多图文的形式已经没有了
一、如果公众号很久没有回复消息,大部分问题一般都出现在自己写的代码上以及传送数据包的问题
二、公众号回复我是写在控制器里面,接下来就说一下回复的实现步骤:
1、首先登录微信公众平台-基本配置-回复设置:修改调用程序公众号回复的url地址(这里url地址就是控制器api的调用地址,可以在swagger里面查看Request URL)
2、在微信公众号回复内容的话,可以在日志中追踪请求的url,可以看到在微信中发消息会带有四个参数,分别是echoStr、signature、timestamp、nonce(token为你申请公众号的token)
返回echoStr即可代表连接成功,点击保存配置之后启动配置就可以啦
注:如果出现多次无法保存的情况,用日志追踪看看有没有url请求成功,请求成功的话再去验证token
if (CheckSignature(token, signature, timestamp, nonce)) { if (!string.IsNullOrEmpty(echoString)) { await HttpContext.Response.WriteAsync(echoString); } }
三、微信自动回复的接口代码
1、首先查阅微信公众平台的回复形式
注:要严格按照微信公众平台来中间不要有空格!!!
private async Task<ActionResult> MessageAsync(string httpresult) { var xEle = new XElement("a", "b", new XAttribute("c", "cc")); var Xml = ""; ToMessageBase result = null; if (!string.IsNullOrEmpty(httpresult)) { XmlDocument xmldoc = new XmlDocument(); xmldoc.LoadXml(httpresult); XmlElement root = xmldoc.DocumentElement; // 发送方帐号(open_id) string FromUserName = root.SelectSingleNode("FromUserName").InnerText; // 公众帐号 string ToUserName = root.SelectSingleNode("ToUserName").InnerText; // 消息类型 string msgType = root.SelectSingleNode("MsgType").InnerText; if (string.IsNullOrWhiteSpace(msgType)) throw new ApiArgumentException("消息类型不能为空"); string key = ""; if (msgType == "text") { //回复的关键字 key = root.SelectSingleNode("Content").InnerText; } DateTime DateNow = DateTime.Now; long UnixDate = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000; try { // ReplyType 1关注时回复 2关键字回复 4无匹配回复 if (msgType == "event") { var fromEvent = root.SelectSingleNode("Event").InnerText.ToLower(); if (string.IsNullOrWhiteSpace(fromEvent)) throw new ApiArgumentException("事件类型不能为空"); //记录日志 WeChatHelper.LoggerAction?.Invoke(nameof(ServerMessageHandler), "Event " + fromEvent); //处理微信服务器事件Key大小写不一致的问题 httpresult = httpresult.Replace("<Event><![CDATA[" + fromEvent + "]]></Event>", "<Event><![CDATA[" + fromEvent + "]]></Event>"); var fromEventType = (FromEventTypes)Enum.Parse(typeof(FromEventTypes), fromEvent); if (fromEventType == FromEventTypes.subscribe)//关注时回复 { var subscribequery = _textreply_Repository.GetAllList(p => p.ReplyType == 1 && p.IsDisable == false); foreach (var Reply_Info in subscribequery) { var serverMessageHandler = new ServerMessageHandler(1) { HandleFuncs = new Dictionary<Type, Func<IFromMessage, ToMessageBase>>() { { typeof(FromSubscribeEvent), message => new ToTextMessage() { Content = Reply_Info.Content, } } } }; //FromUserName gh_abf10bb55494 result = serverMessageHandler.HandleMessage( @"<xml><ToUserName><![CDATA[" + ToUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + FromUserName + "]]></FromUserName>" + "<CreateTime>" + UnixDate + "</CreateTime>" + "<MsgType><![CDATA[event]]></MsgType>" + "<Event><![CDATA[subscribe]]></Event>" + "<EventKey><![CDATA[]]></EventKey>" + "</xml>").Result; if (result.CreateDateTime == default(DateTime)) { throw new UserFriendlyException("时间格式错误!"); } Xml = result.ToXml(); if (string.IsNullOrWhiteSpace(Xml)) { throw new UserFriendlyException("序列化XML格式错误!"); } } } } else if (msgType == "text")//请求的类型是文本的形式 { //匹配模式 MatchType //1.模糊匹配 2精确匹配 //状态为已经启动 /0、启用 false 1禁用 true // var query = _textreply_Repository.GetAllList(p =>p.Keys.Contains(key) && p.IsDisable == false && p.ReplyType == 2);//根据关键字获取回复的关键字列表 var query = _textreply_Repository.GetAllList(p =>key.Contains(p.Keys) && p.IsDisable == false && p.ReplyType == 2);//根据关键字获取回复的关键字列表 if (query.Count > 0) { foreach (var media_Text_Reply_Info in query) { if (media_Text_Reply_Info != null) { //1关注时回复 2关键字回复 3无匹配回复 //Type 1 文本 2图文 if (media_Text_Reply_Info.Type == 1)//文本 { Media_Text_Reply_Info reply_Info = new Media_Text_Reply_Info(); #region if (media_Text_Reply_Info.MatchType == 1) //1.模糊匹配 { if (key.Contains(media_Text_Reply_Info.Keys))//media_Text_Reply_Info.Keys.Contains(key) { reply_Info = media_Text_Reply_Info; } else { reply_Info = null; } } else { if (media_Text_Reply_Info.Keys == key.Trim()) { reply_Info = media_Text_Reply_Info; } else { reply_Info = null; } } #endregion if (reply_Info != null) { var serverMessageHandler = new ServerMessageHandler(1) { HandleFuncs = new Dictionary<Type, Func<IFromMessage, ToMessageBase>>() { { typeof(FromTextMessage), message => new ToTextMessage() { Content = reply_Info.Content,//文本回复 } } } }; result = serverMessageHandler.HandleMessage( @"<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>" + "<CreateTime>" + UnixDate + "</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[回复]]></Content>" + "</xml>").Result; result.FromUserName = ToUserName; result.ToUserName = FromUserName; Xml = result.ToXml(); if (result.CreateDateTime == default(DateTime)) { throw new UserFriendlyException("时间格式错误!"); } Xml = result.ToXml(); xEle = XElement.Parse(Xml); LoggerHelper.Debug(Xml); if (string.IsNullOrWhiteSpace(Xml.ToString())) { throw new UserFriendlyException("序列化XML格式错误!"); } } else { var nomatchquery = _textreply_Repository.GetAllList(p => p.ReplyType == 4 && p.IsDisable == false); if (nomatchquery.Count > 0) { foreach (var nomatch in nomatchquery) { string content = nomatch.Content; var serverMessageHandler = new ServerMessageHandler(1) { HandleFuncs = new Dictionary<Type, Func<IFromMessage, ToMessageBase>>() { { typeof(FromTextMessage), message => new ToTextMessage() { Content = nomatch.Content, } } } }; result = serverMessageHandler.HandleMessage( @"<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>" + "<CreateTime>" + UnixDate + "</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[回复]]></Content>" + "</xml>").Result; result.FromUserName = ToUserName; result.ToUserName = FromUserName; if (result.CreateDateTime == default(DateTime)) { throw new UserFriendlyException("时间格式错误!"); } Xml = result.ToXml(); if (string.IsNullOrWhiteSpace(Xml)) { throw new UserFriendlyException("序列化XML格式错误!"); } } } else { throw new NotSupportedException("没有要匹配的关键字【" + key + "】"); } } } else { var list = _mutireply_Repository.GetAllList(x => x.ReplyId == media_Text_Reply_Info.Id);//获取图文列表 var toMsg = new ToNewsMessage(); toMsg.Articles = new List<ToNewsMessage.ArticleInfo>(); string webRootPath = _hostingEnvironment.WebRootPath; foreach (var article in list) { var articleinfo = new ToNewsMessage.ArticleInfo(); articleinfo.Description = article.Description; articleinfo.PicUrl = webRootPath.Replace(@"\", @"/") + article.ImageUrl; articleinfo.Title = article.Title; articleinfo.Url = article.Url == null ? "" : article.Url; toMsg.Articles.Add(articleinfo); } toMsg.FromUserName = ToUserName; toMsg.ToUserName = FromUserName; var serverMessageHandler = new ServerMessageHandler(1) { HandleFuncs = new Dictionary<Type, Func<IFromMessage, ToMessageBase>>() { { typeof(FromTextMessage), message => toMsg } } }; result = serverMessageHandler.HandleMessage( @"<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>" + "<CreateTime>" + UnixDate + "</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[回复]]></Content>" + "<MsgId>1234567890123456</MsgId>" + "</xml>").Result; result.FromUserName = ToUserName; result.ToUserName = FromUserName; if (result is ToNewsMessage) { var news = result as ToNewsMessage; if (news.Articles.Count > 10) throw new NotSupportedException("图文消息不能超过10条"); if (news.Articles.Count == 0) throw new ApiArgumentException("至少需要包含一条图文消息"); news.ArticleCount = news.Articles.Count; } Xml = result.ToXml(); xEle = XElement.Parse(Xml); if (xEle.Element("Articles") == null) { throw new UserFriendlyException("图文格式有误!"); } } } } } else { var noreplyquery = _textreply_Repository.GetAllList(p => p.ReplyType == 4 && p.IsDisable == false); if (noreplyquery.Count > 0) { foreach (var noreply in noreplyquery) { string content = noreply.Content; var serverMessageHandler = new ServerMessageHandler(1) { HandleFuncs = new Dictionary<Type, Func<IFromMessage, ToMessageBase>>() { { typeof(FromTextMessage), message => new ToTextMessage() { Content = noreply.Content, } } } }; result = serverMessageHandler.HandleMessage( @"<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>" + "<CreateTime>" + UnixDate + "</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[回复]]></Content>" + "</xml>").Result; result.FromUserName = ToUserName; result.ToUserName = FromUserName; if (result.CreateDateTime == default(DateTime)) { throw new UserFriendlyException("时间格式错误!"); } Xml = result.ToXml(); if (string.IsNullOrWhiteSpace(Xml)) { throw new UserFriendlyException("序列化XML格式错误!"); } } } else { throw new NotSupportedException("没有要匹配的关键字【"+key+"】"); } } } else { var noreplyquery = _textreply_Repository.GetAllList(p => p.ReplyType == 4 && p.IsDisable == false); if (noreplyquery.Count > 0) { foreach (var text_Reply_Info in noreplyquery) { var serverMessageHandler = new ServerMessageHandler(1) { HandleFuncs = new Dictionary<Type, Func<IFromMessage, ToMessageBase>>() { { typeof(FromTextMessage), message => new ToTextMessage() { Content = text_Reply_Info.Content, } } } }; result = serverMessageHandler.HandleMessage( @"<xml><ToUserName><![CDATA[" + FromUserName + "]]></ToUserName>" + "<FromUserName><![CDATA[" + ToUserName + "]]></FromUserName>" + "<CreateTime>" + UnixDate + "</CreateTime>" + "<MsgType><![CDATA[text]]></MsgType>" + "<Content><![CDATA[回复]]></Content>" + "</xml>").Result; result.FromUserName = ToUserName; result.ToUserName = FromUserName; if (result.CreateDateTime == default(DateTime)) { throw new UserFriendlyException("时间格式错误!"); } Xml = result.ToXml(); if (string.IsNullOrWhiteSpace(Xml)) { throw new UserFriendlyException("序列化XML格式错误!"); } } } else { throw new NotSupportedException("暂不支持类型为【" + msgType + "】的消息类型"); } } } catch (Exception ex) { string a = ex.ToString(); return Content(a); } } if (result == null) return Ok(); var toXml = result.ToXml(); LoggerHelper.Debug("微信服务器事件处理成功,返回格式为:" + Environment.NewLine + toXml); return Content(toXml); }