站内搜索

使用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  餐厅40001   key的长度错误(32位)40002   请求内容为空40003   key错误或帐号未激活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序列化为微信需要的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中文网其它相关文章!

  • 上一篇:c#开发微信实现jssdk签名生成
  • 下一篇:微信开发微网站之jquery_mobile案例分析