微信公众平台开发教程(四) 实例入门:机器人(附源码)
一、功能介绍
通过微信公众平台实现在线客服机器人功能。主要的功能包括:简单对话、查询天气等服务。
这里只是提供比较简单的功能,重在通过此实例来说明公众平台的具体研发过程。只是一个简单DEMO,如果需要的话可以在此基础上进行扩展。
当然后续我们还会推出比较复杂的应用实例。
二、具体实现
1、提供访问接口
这里不再赘述,参照上一章,微信公众账号开发教程(二) 基础框架搭建
http://www.cnblogs.com/yank/p/3392394.html
2、签名认证和分发请求
这里不再赘述,参照上一章,微信公众账号开发教程(二) 基础框架搭建
http://www.cnblogs.com/yank/p/3392394.html
3、处理请求,并响应
1)关注
当微信用户关注公众账号时,可以给其适当的提示。可以是欢迎词,可以是帮助提示。
直接上代码:
1 class EventHandler : IHandler 2 { 3 /// <summary> 4 /// 请求的xml 5 /// </summary> 6 private string RequestXml { get; set; } 7 /// <summary> 8 /// 构造函数 9 /// </summary> 10 /// <param name="requestXml"></param> 11 public EventHandler(string requestXml) 12 { 13 this.RequestXml = requestXml; 14 } 15 /// <summary> 16 /// 处理请求 17 /// </summary> 18 /// <returns></returns> 19 public string HandleRequest() 20 { 21 string response = string.Empty; 22 EventMessage em = EventMessage.LoadFromXml(RequestXml); 23 if (em.Event.Equals("subscribe",StringComparison.OrdinalIgnoreCase)) 24 { 25 //回复欢迎消息 26 TextMessage tm = new TextMessage(); 27 tm.ToUserName = em.FromUserName; 28 tm.FromUserName = em.ToUserName; 29 tm.CreateTime = Common.GetNowTime(); 30 tm.Content = "欢迎您关注***,我是大哥大,有事就问我,呵呵!\n\n"; 31 response = tm.GenerateContent(); 32 } 33 34 return response; 35 } 36 }
2)问候
简单的交流问候,比如你好、帮助等等,跟我们使用微信聊天一样,不过回应是由我们的程序响应。具体功能,可以根据自己的需要进行添加。
微信本来就是沟通的平台。这个案例,可以用于在线服务机器人,类似于淘宝的客服机器人,可是我们这个是微信版的。呵呵
其实,很简单,获取请求消息,根据关键字来匹配回应。当然这里可能要做的工作很多,如何支持智能匹配,如何支持模糊匹配等。
代码如下:
1 /// <summary> 2 /// 文本信息处理类 3 /// </summary> 4 public class TextHandler : IHandler 5 { 6 /// <summary> 7 /// 请求的XML 8 /// </summary> 9 private string RequestXml { get; set; } 10 /// <summary> 11 /// 构造函数 12 /// </summary> 13 /// <param name="requestXml">请求的xml</param> 14 public TextHandler(string requestXml) 15 { 16 this.RequestXml = requestXml; 17 } 18 /// <summary> 19 /// 处理请求 20 /// </summary> 21 /// <returns></returns> 22 public string HandleRequest() 23 { 24 string response = string.Empty; 25 TextMessage tm = TextMessage.LoadFromXml(RequestXml); 26 string content = tm.Content.Trim(); 27 if (string.IsNullOrEmpty(content)) 28 { 29 response = "您什么都没输入,没法帮您啊,%>_<%。"; 30 } 31 else 32 { 33 if (content.StartsWith("tq", StringComparison.OrdinalIgnoreCase)) 34 { 35 string cityName = content.Substring(2).Trim(); 36 response = WeatherHelper.GetWeather(cityName); 37 } 38 else 39 { 40 response = HandleOther(content); 41 } 42 } 43 tm.Content = response; 44 //进行发送者、接收者转换 45 string temp = tm.ToUserName; 46 tm.ToUserName = tm.FromUserName; 47 tm.FromUserName = temp; 48 response = tm.GenerateContent(); 49 return response; 50 } 51 /// <summary> 52 /// 处理其他消息 53 /// </summary> 54 /// <param name="tm"></param> 55 /// <returns></returns> 56 private string HandleOther(string requestContent) 57 { 58 string response = string.Empty; 59 if (requestContent.Contains("你好") || requestContent.Contains("您好")) 60 { 61 response = "您也好~"; 62 } 63 else if (requestContent.Contains("傻")) 64 { 65 response = "我不傻!哼~ "; 66 } 67 else if (requestContent.Contains("逼") || requestContent.Contains("操")) 68 { 69 response = "哼,你说脏话! "; 70 } 71 else if (requestContent.Contains("是谁")) 72 { 73 response = "我是大哥大,有什么能帮您的吗?~"; 74 } 75 else if (requestContent.Contains("再见")) 76 { 77 response = "再见!"; 78 } 79 else if (requestContent.Contains("bye")) 80 { 81 response = "Bye!"; 82 } 83 else if (requestContent.Contains("谢谢")) 84 { 85 response = "不客气!嘿嘿"; 86 } 87 else if (requestContent == "h" || requestContent == "H" || requestContent.Contains("帮助")) 88 { 89 response = @"查询天气,输入tq 城市名称\拼音\首字母"; 90 } 91 else 92 { 93 response = "您说的,可惜,我没明白啊,试试其他关键字吧。"; 94 } 95 96 return response; 97 } 98 }
3)查询天气
这个功能需要请求实时查询的,请求官方的天气发布网站,然后解析其返回值,按照我们需要的格式,组织天气信息,最后发送给微信客户。
采用文本消息方式处理。
用户请求,只需输入:tq 城市名称/拼音/首字母,即可获取消息。
回复的消息:(以北京为例)
北京 2013年11月6日 星期三 今天:(17℃~4℃)晴北风4-5级转3-4级4-5级转3-4级 24小时穿衣指数:天气冷,建议着棉服、羽绒服、皮夹克加羊毛衫等冬季服装。年老体弱者宜着厚棉衣、冬大衣或厚羽绒服。 明天:(14℃~3℃)晴转多云微风小于3级 48小时穿衣指数:天气冷,建议着棉服、羽绒服、皮夹克加羊毛衫等冬季服装。年老体弱者宜着厚棉衣、冬大衣或厚羽绒服。
来看源码吧:
1 class WeatherHelper 2 { 3 /// <summary> 4 /// 城市集合字段 5 /// </summary> 6 private static Dictionary<string, City> mCities; 7 /// <summary> 8 /// 城市集合 9 /// </summary> 10 public static Dictionary<string, City> Cities 11 { 12 get 13 { 14 if (mCities == null) 15 { 16 LoadCities(); 17 } 18 19 return mCities; 20 } 21 } 22 /// <summary> 23 /// 加载城市 24 /// </summary> 25 private static void LoadCities() 26 { 27 mCities = new Dictionary<string, City>(); 28 mCities.Clear(); 29 mCities.Add("101010100", new City() { Code = "101010100", Name = "北京", PinYin = "beijing", FristLetter = "bj" }); 30 mCities.Add("101020100", new City() { Code = "101020100", Name = "上海", PinYin = "shanghai", FristLetter = "sh" }); 31 mCities.Add("101200101", new City() { Code = "101200101", Name = "武汉", PinYin = "wuhai", FristLetter = "wh" }); 32 33 } 34 /// <summary> 35 /// 获取城市的天气 36 /// </summary> 37 /// <param name="name">城市名称、拼音或首字母</param> 38 /// <returns></returns> 39 public static string GetWeather(string name) 40 { 41 string result = string.Empty; 42 string cityCode = string.Empty; 43 //获取城市编码 44 IEnumerable<string> codes = from item in Cities 45 where item.Value != null 46 && (item.Value.Name.Equals(name, StringComparison.OrdinalIgnoreCase) 47 || item.Value.PinYin.Equals(name, StringComparison.OrdinalIgnoreCase) 48 || item.Value.FristLetter.Equals(name, StringComparison.OrdinalIgnoreCase)) 49 select item.Value.Code; 50 if (codes != null && codes.Count() > 0) 51 { 52 cityCode = codes.First<string>(); 53 } 54 55 //http请求,获取天气 56 if (!string.IsNullOrEmpty(cityCode)) 57 { 58 string url = "http://m.weather.com.cn/data/{0}.html"; 59 url = string.Format(url, cityCode); 60 WebRequest request = HttpWebRequest.Create(url); 61 //超时时间为:2秒 62 request.Timeout = 2000; 63 request.Credentials = CredentialCache.DefaultCredentials; 64 WebResponse response = request.GetResponse(); 65 StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); 66 string weahterInfo = reader.ReadToEnd(); 67 if (string.IsNullOrEmpty(weahterInfo)) 68 { 69 result = "暂时没有取到天气数据,请稍后再试"; 70 } 71 else 72 { 73 XmlDocument doc = JsonConvert.DeserializeXmlNode(weahterInfo); 74 if (doc != null) 75 { 76 XmlNode node = doc.DocumentElement; 77 if (node != null) 78 { 79 StringBuilder builder = new StringBuilder(); 80 builder.Append(node["city"].InnerText).Append("\n"); 81 builder.Append(node["date_y"].InnerText).Append(" ").Append(node["week"].InnerText).Append("\n"); 82 builder.Append("今天:").Append("(").Append(node["temp1"].InnerText).Append(")").Append(node["weather1"].InnerText).Append(node["wind1"].InnerText).Append(node["fl1"].InnerText).Append("\n"); 83 builder.Append("24小时穿衣指数:").Append(node["index_d"].InnerText).Append("\n"); 84 builder.Append("明天:").Append("(").Append(node["temp2"].InnerText).Append(")").Append(node["weather2"].InnerText).Append(node["wind2"].InnerText).Append(node["fl2"].InnerText).Append("\n"); 85 builder.Append("48小时穿衣指数:").Append(node["index48_d"].InnerText).Append("\n"); 86 result = builder.ToString(); 87 } 88 } 89 #region 天气json数据格式 90 /* 91 92 { 93 "weatherinfo": { 94 "city": "北京", 95 "city_en": "beijing", 96 "date_y": "2013年11月4日", 97 "date": "", 98 "week": "星期一", 99 "fchh": "11", 100 "cityid": "101010100", 101 "temp1": "17℃~5℃", 102 "temp2": "16℃~5℃", 103 "temp3": "18℃~4℃", 104 "temp4": "17℃~5℃", 105 "temp5": "14℃~6℃", 106 "temp6": "14℃~2℃", 107 "tempF1": "62.6℉~41℉", 108 "tempF2": "60.8℉~41℉", 109 "tempF3": "64.4℉~39.2℉", 110 "tempF4": "62.6℉~41℉", 111 "tempF5": "57.2℉~42.8℉", 112 "tempF6": "57.2℉~35.6℉", 113 "weather1": "晴转多云", 114 "weather2": "多云", 115 "weather3": "多云转晴", 116 "weather4": "晴转多云", 117 "weather5": "多云转阴", 118 "weather6": "阴转晴", 119 "img1": "0", 120 "img2": "1", 121 "img3": "1", 122 "img4": "99", 123 "img5": "1", 124 "img6": "0", 125 "img7": "0", 126 "img8": "1", 127 "img9": "1", 128 "img10": "2", 129 "img11": "2", 130 "img12": "0", 131 "img_single": "0", 132 "img_title1": "晴", 133 "img_title2": "多云", 134 "img_title3": "多云", 135 "img_title4": "多云", 136 "img_title5": "多云", 137 "img_title6": "晴", 138 "img_title7": "晴", 139 "img_title8": "多云", 140 "img_title9": "多云", 141 "img_title10": "阴", 142 "img_title11": "阴", 143 "img_title12": "晴", 144 "img_title_single": "晴", 145 "wind1": "微风", 146 "wind2": "微风", 147 "wind3": "微风", 148 "wind4": "微风", 149 "wind5": "微风", 150 "wind6": "北风4-5级", 151 "fx1": "微风", 152 "fx2": "微风", 153 "fl1": "小于3级", 154 "fl2": "小于3级", 155 "fl3": "小于3级", 156 "fl4": "小于3级", 157 "fl5": "小于3级", 158 "fl6": "4-5级", 159 "index": "较冷", 160 "index_d": "建议着大衣、呢外套加毛衣、卫衣等服装。体弱者宜着厚外套、厚毛衣。因昼夜温差较大,注意增减衣服。", 161 "index48": "冷", 162 "index48_d": "天气冷,建议着棉服、羽绒服、皮夹克加羊毛衫等冬季服装。年老体弱者宜着厚棉衣、冬大衣或厚羽绒服。", 163 "index_uv": "中等", 164 "index48_uv": "弱", 165 "index_xc": "适宜", 166 "index_tr": "适宜", 167 "index_co": "舒适", 168 "st1": "17", 169 "st2": "5", 170 "st3": "17", 171 "st4": "5", 172 "st5": "18", 173 "st6": "6", 174 "index_cl": "适宜", 175 "index_ls": "适宜", 176 "index_ag": "极不易发" 177 } 178 } 179 */ 180 #endregion 181 182 } 183 } 184 else 185 { 186 result = "没有获取到该城市的天气,请确定输入了正确的城市名称,如\'北京\'或者\'beijing\'或者\'bj\'"; 187 } 188 189 //返回 190 return result; 191 } 192 /// <summary> 193 /// 内部类:城市 194 /// </summary> 195 internal class City 196 { 197 /// <summary> 198 /// 编码 199 /// </summary> 200 public string Code { get; set; } 201 /// <summary> 202 /// 名称 203 /// </summary> 204 public string Name { get; set; } 205 /// <summary> 206 /// 拼音 207 /// </summary> 208 public string PinYin { get; set; } 209 /// <summary> 210 /// 拼音首字母 211 /// </summary> 212 public string FristLetter { get; set; } 213 } 214 }
三、源码
这里可是可执行的代码哦。应大家的需求,这里提供全部的源代码。
https://files.cnblogs.com/yank/Yank.WeiXin.Robot.zip
既不回头,何必不忘;
既然无缘,何须誓言;
今日种种,逝水无痕;
明夕何夕,君已陌路;