使用web api开发微信公众号调用图灵机器人接口的方法
被动响应消息(返回XML)
微信要求我们返回XML数据,且格式是规定好的,具体请看
微信公众平台开发者文档。
响应的实体类,我们之前已经写好了,因为要求是XML格式。我们在此使用微软提供的System.Xml.Serialization.XmlSerializer来将我们的数据序列化为XML。所以我们在类上边标记了XmlRoot特性,在枚举的字段上边标记了XmlEnum特性,NewsMsg中在文章列表上标记了XmlArray和XmlArrayItem特性。而后反序列化出来的便是微信要求的格式了。
序列化方法如下:public string ResponseXML(object value, Type type){StringWriter sw = new StringWriter();XmlSerializerNamespaces ns = new XmlSerializerNamespaces();ns.Add("", ""); //去除命名空间XmlSerializer serializer = new XmlSerializer(type);serializer.Serialize(sw, value, ns);return sw.ToString();}注意:此处必须去除XML的命名空间,不然微信不识别
完整方法奉上:public HttpResponseMessage Post(){var requestContent = Request.Content.ReadAsStreamAsync().Result;//从正文参数中加载微信的请求参数XmlDocument xmlDoc = new XmlDocument();xmlDoc.Load(requestContent);logger.DebugFormat("WX请求XML内容:{0}", xmlDoc.InnerText);string msgTypeStr = xmlDoc.SelectSingleNode("xml/MsgType").InnerText;string userName = xmlDoc.SelectSingleNode("xml/FromUserName").InnerText;string efhName = xmlDoc.SelectSingleNode("xml/ToUserName").InnerText;string responseContent;MsgType msgType;//获取消息类型,若未定义,则返回。if (!Enum.TryParse(msgTypeStr, true, out msgType)){responseContent = MsgService.Instance.ResponseXML(new TextMsg{FromUserName = efhName,MsgType = MsgType.Text,Content = "俺还小,不知道你在说啥子(⊙_⊙)?",CreateTime = UnixTimestamp.Now.ToNumeric(),ToUserName = userName}, typeof(TextMsg));return new HttpResponseMessage(HttpStatusCode.OK){Content = new StringContent(responseContent, Encoding.UTF8, "application/xml"),};}if (msgType == MsgType.Event){return ProcessEvent(xmlDoc, userName, efhName);}//图灵消息转换为微信响应消息,下一节奉上string content = xmlDoc.SelectSingleNode("xml/Content").InnerText;var requestResult = TuLingService.Instance.GetMsgFromResponse(content, userName, efhName);responseContent = MsgService.Instance.ResponseXML(requestResult.Data, requestResult.DataType);return new HttpResponseMessage(HttpStatusCode.OK){Content = new StringContent(responseContent, Encoding.UTF8, "application/xml"),};}private HttpResponseMessage ProcessEvent(XmlDocument xmlDoc, string userName, string efhName){string eventValue = xmlDoc.SelectSingleNode("xml/Event").InnerText;var responseContent = MsgService.Instance.ResponseXML(new TextMsg{FromUserName = efhName,MsgType = MsgType.Text,Content = eventValue.ToLower().Equals("subscribe") ? "lei好哇~" : "大爷,奴家会想你的",//其实取消订阅是不会发送消息的CreateTime = UnixTimestamp.Now.ToNumeric(),ToUserName = userName}, typeof(TextMsg));return new HttpResponseMessage(HttpStatusCode.OK){Content = new StringContent(responseContent, Encoding.UTF8, "application/xml"),};}至此,我们已经完成了微信被动回复消息的响应。
映射图灵消息及微信消息
上边我们已经实现了被动回复消息的功能,接下来我们需要将图灵机器人接口与我们的公众平台关联起来。
分析图灵机器人返回的参数,我们发现所有类型的内容都有code和text参数。又因为我们需要将图灵的消息与微信的响应消息直接对应起来,因此我们定义接口,提供转换方法public class TuLingResult{//消息类型(我们在序列化为XML的时候需要提供类型)public Type DataType { get; set; }public object Data { get; set; }}public interface IResponse{TuLingResult ToTuLingResult(string fromUserName, string toUserName);}创建文本类数据的实体作为图灵消息的基类(对应微信的文本消息)public class TextResult : IResponse{public int Code { get; set; }public string Text { get; set; }public virtual TuLingResult ToTuLingResult(string fromUserName, string toUserName){return new TuLingResult{DataType = typeof(TextMsg),Data = new TextMsg{FromUserName = fromUserName,ToUserName = toUserName,Content = Text,CreateTime = UnixTimestamp.Now.ToNumeric(),MsgType = MsgType.Text}};}}而后依次创建各种数据的实体类。如:新闻(对应微信的图文消息)public class NewsResult : TextResult{public List<NewsInfo> List { get; set; }public override TuLingResult ToTuLingResult(string fromUserName, string toUserName){if (List.Count > 10){List = List.Take(10).ToList();}return new TuLingResult{DataType = typeof(NewsMsg),Data = new NewsMsg{FromUserName = fromUserName,ToUserName = toUserName,ArticleCount = List.Count,Articles = List.Select(m => new MsgNewsInfo{Title = m.Article,Description = m.Source,Url = m.DetailUrl,PicUrl = m.Icon}).ToList(),CreateTime = UnixTimestamp.Now.ToNumeric(),MsgType=MsgType.News}};}}public class NewsInfo{/// <summary>/// 标题/// </summary>public string Article { get; set; }/// <summary>/// 来源/// </summary>public string Source { get; set; }/// <summary>/// 详情地址/// </summary>public string DetailUrl { get; set; }/// <summary>/// 图标地址/// </summary>public string Icon { get; set; }}同理创建图灵机器人提供的各类数据实体类
我们想要支持的数据实体都定义完毕后,我们便可以开始请求图灵接口,获取真实的消息了,在此我们使用HttpClient实现。private const string TULING_API_URL = "http://www.tuling123.com/openapi/api";private const string TULING_API_KEY = "XXXXX";//图灵的APIKEYpublic TuLingResult GetMsgFromResponse(string keyword, string userFlag, string efhName){string linkString = string.Format("{0}?key={1}&info={2}&userid={3}", TULING_API_URL, TULING_API_KEY, keyword, userFlag);string content = string.Empty;using (HttpClient client = new HttpClient()){HttpResponseMessage response = client.GetAsync(linkString).Result;content = response.Content.ReadAsStringAsync().Result;logger.DebugFormat("图灵机器人响应:{0}", content);}return ConvertToMsg(content, userFlag, efhName);}图灵返回了code标识消息的类型和错误信息,因此我们先将响应消息解析为TextResult,拿到图灵的类型。
先定义图灵类型枚举public enum ResultType{TL_FORMAT_DATA = 50000,TL_TEXT_DATA = 100000,TL_LINK_DATA = 200000,TL_NOVEL_DATA = 301000,TL_NEWS_DATA = 302000,TL_APP_DATA = 304000,TL_TRAIN_DATA = 305000,TL_AIRPORT_DATA = 306000,TL_TUAN_DATA = 307000,TL_TUWEN_DATA = 308000,TL_HOTEL_DATA = 309000,TL_LOTTERY_DATA = 310000,TL_PRICE_DATA = 311000,TL_RESTAURANT_DATA = 312000,TL_ERROR_LENGTH = 40001,TL_ERROR_EMPTY = 40002,TL_ERROR_INVALID = 40003,TL_ERROR_OUTLIMIT = 40004,TL_ERROR_NOTSUPPORT = 40005,TL_ERROR_SERVERUPDATE = 40006,TL_ERROR_SERVERERROR = 40007}对应于图灵的返回码100000文本类数据200000网址类数据301000小说302000新闻304000应用、软件、下载305000列车306000航班307000团购308000优惠309000酒店310000彩票311000价格312000餐厅40001key的长度错误(32位)40002请求内容为空40003key错误或帐号未激活40004当天请求次数已用完40005暂不支持该功能40006服务器升级中40007服务器数据格式异常50000机器人设定的“学用户说话”或者“默认回答”而后拿到消息类型private ResultType GetResultType(string response){var result = JsonConvert.DeserializeObject<TextResult>(response);return (ResultType)result.Code;}之后,我们便可以按照不同类型返回相对应的TuLingResult。public TuLingResult ConvertToMsg(string response, string userFlag, string efhName){IResponse result = null;var resultType = GetResultType(response);switch (resultType){case ResultType.TL_TEXT_DATA:result = JsonConvert.DeserializeObject<TextResult>(response);break;case ResultType.TL_LINK_DATA:result = JsonConvert.DeserializeObject<LinkResult>(response);break;case ResultType.TL_NEWS_DATA:result = JsonConvert.DeserializeObject<NewsResult>(response);break;case ResultType.TL_TUWEN_DATA:result = JsonConvert.DeserializeObject<TuWenResult>(response);break;case ResultType.TL_TRAIN_DATA:result = JsonConvert.DeserializeObject<TrainResult>(response);break;case ResultType.TL_AIRPORT_DATA:result = JsonConvert.DeserializeObject<AirportResult>(response);break;case ResultType.TL_APP_DATA:result = JsonConvert.DeserializeObject<AppResult>(response);break;case ResultType.TL_HOTEL_DATA:result = JsonConvert.DeserializeObject<HotelResult>(response);break;case ResultType.TL_PRICE_DATA:result = JsonConvert.DeserializeObject<PriceResult>(response);break;case ResultType.TL_ERROR_LENGTH:case ResultType.TL_ERROR_INVALID:case ResultType.TL_ERROR_EMPTY:case ResultType.TL_ERROR_OUTLIMIT:result = new TextResult { Text = "您的输入有误" };break;case ResultType.TL_ERROR_SERVERERROR:case ResultType.TL_ERROR_SERVERUPDATE:result = new TextResult { Text = "服务器忙,暂时无法为您提供服务" };break;case ResultType.TL_ERROR_NOTSUPPORT:result = new TextResult { Text = "俺还小,您说的这个还得慢慢学习,以后再来试吧" };break;default:result = new TextResult { Text = "俺还小,不知道你在说啥子(⊙_⊙)?" };break;}return result.ToTuLingResult(efhName, userFlag);}而后,我们便可以将我们拿到的TuLingResult中的Data序列化为微信需要的XMLvar requestResult = TuLingService.Instance.GetMsgFromResponse(content, userName, efhName);responseContent = MsgService.Instance.ResponseXML(requestResult.Data, requestResult.DataType);return new HttpResponseMessage(HttpStatusCode.OK){Content = new StringContent(responseContent, Encoding.UTF8, "application/xml"),};以上就是使用web api开发微信公众号调用图灵机器人接口的方法的详细内容,更多请关注小潘博客其它相关文章!