被动响应消息(返回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 ListList { 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{ /// /// 标题 /// public string Article { get; set; } ////// 来源 /// public string Source { get; set; } ////// 详情地址 /// public string DetailUrl { get; set; } ////// 图标地址 /// 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 餐厅40001 key的长度错误(32位)40002 请求内容为空40003 key错误或帐号未激活40004 当天请求次数已用完40005 暂不支持该功能40006 服务器升级中40007 服务器数据格式异常50000 机器人设定的“学用户说话”或者“默认回答”
而后拿到消息类型
private ResultType GetResultType(string response){ var result = JsonConvert.DeserializeObject(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(response); break; case ResultType.TL_LINK_DATA: result = JsonConvert.DeserializeObject (response); break; case ResultType.TL_NEWS_DATA: result = JsonConvert.DeserializeObject (response); break; case ResultType.TL_TUWEN_DATA: result = JsonConvert.DeserializeObject (response); break; case ResultType.TL_TRAIN_DATA: result = JsonConvert.DeserializeObject (response); break; case ResultType.TL_AIRPORT_DATA: result = JsonConvert.DeserializeObject (response); break; case ResultType.TL_APP_DATA: result = JsonConvert.DeserializeObject (response); break; case ResultType.TL_HOTEL_DATA: result = JsonConvert.DeserializeObject (response); break; case ResultType.TL_PRICE_DATA: result = JsonConvert.DeserializeObject (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序列化为微信需要的XML
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"),};
以上就是使用web api开发微信公众号调用图灵机器人接口的方法的详细内容,更多请关注php中文网其它相关文章!