有一段时间没有接着微信的主题继续介绍里面的功能模块了,这段时间来,微信也作了很多的变化改动,针对这些特性我全面核对了一下相关的微信公众号和企业号的接口,对原有的微信API和系统管理作了全面的更新,本随笔以及后面的随笔就是基于这个工做上的总结,以期把微信涉及的功能模块,都使用C#实现的方式来介绍。本随笔主要介绍微信公众号的个性化菜单的实现,虽然目前微信公众号和企业号已经在功能上接近一致,不过在企业号上尚未个性化菜单的相关接口。html
咱们先了解一下个性化菜单的介绍,根据官方的资料,以下介绍。api
为了帮助公众号实现灵活的业务运营,微信公众平台新增了个性化菜单接口,开发者能够经过该接口,让公众号的不一样用户群体看到不同的自定义菜单。该接口开放给已认证订阅号和已认证服务号。数组
开发者能够经过如下条件来设置用户看到的菜单:安全
一、用户分组(开发者的业务需求能够借助用户分组来完成) 二、性别 三、手机操做系统 四、地区(用户在微信客户端设置的地区) 五、语言(用户在微信客户端设置的语言)
个性化菜单接口说明:服务器
一、个性化菜单要求用户的微信客户端版本在iPhone6.2.2,Android 6.2.4以上。 二、菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,若是发现上一次拉取菜单的请求在5分钟之前,就会拉取一下菜单,若是菜单有更新,就会刷新客户端的菜单。测试时能够尝试取消关注公众帐号后再次关注,则能够看到建立后的效果。 三、普通公众号的个性化菜单的新增接口每日限制次数为2000次,删除接口也是2000次,测试个性化菜单匹配结果接口为20000次 四、出于安全考虑,一个公众号的全部个性化菜单,最多只能设置为跳转到3个域名下的连接 五、建立个性化菜单以前必须先建立默认菜单(默认菜单是指使用普通自定义菜单建立接口建立的菜单)。若是删除默认菜单,个性化菜单也会所有删除
个性化菜单匹配规则说明:微信
当公众号建立多个个性化菜单时,将按照发布顺序,由新到旧逐一匹配,直到用户信息与matchrule相符合。若是所有个性化菜单都没有匹配成功,则返回默认菜单。 例如公众号前后发布了默认菜单,个性化菜单1,个性化菜单2,个性化菜单3。那么当用户进入公众号页面时,将从个性化菜单3开始匹配,若是个性化菜单3匹配成功,则直接返回个性化菜单3,不然继续尝试匹配个性化菜单2,直到成功匹配到一个菜单。 根据上述匹配规则,为了不菜单生效时间的混淆,决定不予提供个性化菜单编辑API,开发者须要更新菜单时,需将完整配置从新发布一轮。
除正常的默认菜单外,个性化菜单提供了下面几个处理操做。数据结构
1 建立个性化菜单微信公众平台
2 删除个性化菜单post
3 测试个性化菜单匹配结果测试
4 查询个性化菜单
5 删除全部菜单
个性化自定义菜单功能,是指商家能够根据粉丝的分组、性别、手机操做系统,甚至地区,来分别展现公众号的菜单。
好比,一家健身会所的公众号,将自定义菜单根据粉丝性别进行了分开设置。男性粉丝进入公众号会展现男生们比较感兴趣菜单内容,跆拳道、搏击等;如果女性粉丝,则会展现瑜伽、舞蹈、防身术等女性粉丝感兴趣的菜单课程等。
微信的菜单是微信处理中很重要的一环,由于它是微信给用户入口体验重要的一环,也是很直观的界面呈现之一,菜单的展现就是须要咱们绞尽脑汁来精简的界面元素了,因为菜单的重要性以及功能的丰富性,我在以前好几篇随笔专门介绍了菜单的各类处理。
在《C#开发微信门户及应用(6)--微信门户菜单的管理操做》、《C#开发微信门户及应用(9)-微信门户菜单管理及提交到微信服务器》、《C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍》、《C#开发微信门户及应用(20)-微信企业号的菜单管理》分别对相关的菜单有过介绍,有须要能够参考了解一下。
菜单模块,在微信公众号和企业号,它们均可以共用一个模型,所以咱们把这些内容都放在微信共用模块里面,包括它的实体类信息(如菜单模块),虽然有些地方,部分字段内容没有,可是咱们能够经过实体类的JSON标识来进行处理,从而实现比较弹性化的实体类信息承载。
以下标识代码所示。
/// <summary> /// 菜单基本信息(公众号、企业号公用,其余部分同样) /// </summary> public class MenuJson : BaseJsonResult { /// <summary> /// 按钮描述,既按钮名字,不超过16个字节,子菜单不超过40个字节 /// </summary> public string name { get; set; } /// <summary> /// 按钮类型(click或view) /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string type { get; set; } /// <summary> /// 按钮KEY值,用于消息接口(event类型)推送,不超过128字节 /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string key { get; set; } /// <summary> /// 网页连接,用户点击按钮可打开连接,不超过256字节 /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string url { get; set; } /// <summary> /// media_id类型和view_limited类型必须,调用新增永久素材接口返回的合法media_id /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string media_id { get; set; } /// <summary> /// 子按钮数组,按钮个数应为2~5个 /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public List<MenuJson> sub_button { get; set; }
上面这个实体类是菜单信息的基础信息,咱们须要从这个基础上扩展出来几个实体类,方便在构建,获取菜单信息的时候进行信息转换,以下几个类图的设计所示。
经过这几个类的关系,咱们就能够适应全部的默认菜单和个性化菜单,以及企业号的菜单信息转换处理了,经过JSON转换为对应的实体类,实现信息的强类型处理。
其中咱们菜单处理的API实现类代码以下所示。
/// <summary> /// 菜单的相关操做 /// </summary> public class MenuApi : IMenuApi
这样咱们在IMenuApi的基础上增长几个个性化的接口。
/// <summary> /// 建立个性化菜单 /// </summary> /// <param name="accessToken">调用接口凭证</param> /// <param name="menuJson">菜单对象</param> /// <returns></returns> string CreateConditionalMenu(string accessToken, MenuListJson menuJson); /// <summary> /// 根据菜单ID删除个性化菜单 /// </summary> /// <param name="accessToken">调用接口凭证</param> /// <param name="menuid">菜单ID</param> /// <returns></returns> CommonResult DeleteConditionalMenu(string accessToken, string menuid); /// <summary> /// 测试个性化菜单匹配结果 /// </summary> /// <param name="accessToken">调用接口凭证</param> /// <returns></returns> MenuListJson TryMatchConditionalMenu(string accessToken, string user_id);
而后在MenuApi实现类里面实现相关的逻辑处理便可。
下面是建立个性化菜单的接口说明。
http请求方式:POST(请使用https协议)
https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=ACCESS_TOKEN
请求示例
{ "button":[ { "type":"click", "name":"今日歌曲", "key":"V1001_TODAY_MUSIC" }, { "name":"菜单", "sub_button":[ { "type":"view", "name":"搜索", "url":"http://www.soso.com/" }, { "type":"view", "name":"视频", "url":"http://v.qq.com/" }, { "type":"click", "name":"赞一下咱们", "key":"V1001_GOOD" }] }], "matchrule":{ "group_id":"2", "sex":"1", "country":"中国", "province":"广东", "city":"广州", "client_platform_type":"2" "language":"zh_CN" } }
其中上面的信息,转换为咱们的实体类对象信息就是以下所示。
MenuListJson menuJson
它API返回结果以下所示。
{ "menuid":"208379533" }
为了承载这个信息,咱们须要定义一个实体类来承载这个信息。
/// <summary> /// 返回MenuId的结果 /// </summary> public class MenuIdResult { /// <summary> /// 菜单的ID /// </summary> public string menuid { get; set; } }
最后咱们的API接口只须要获取里面的菜单ID值,字符串类型的就能够了,API具体实现代码以下所示。
/// <summary> /// 建立个性化菜单 /// </summary> /// <param name="accessToken">调用接口凭证</param> /// <param name="menuJson">菜单对象</param> /// <returns></returns> public string CreateConditionalMenu(string accessToken, MenuListJson menuJson) { string result = ""; var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token={0}", accessToken); //matchrule不能为空 ArgumentValidation.CheckForNullReference(menuJson.matchrule, "matchrule"); string postData = menuJson.ToJson(); MenuIdResult list = JsonHelper<MenuIdResult>.ConvertJson(url, postData); if (list != null) { result = list.menuid; } return result; }
而删除个性化菜单的接口也是相似的处理,以下所示。
/// <summary> /// 根据菜单ID删除个性化菜单 /// </summary> /// <param name="accessToken">调用接口凭证</param> /// <param name="menuid">菜单ID</param> /// <returns></returns> public CommonResult DeleteConditionalMenu(string accessToken, string menuid) { var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token={0}", accessToken); var data = new { menuid = menuid }; string postData = data.ToJson(); return Helper.GetExecuteResult(url, postData); }
另外,对于个性化菜单来讲,查询、删除全部的菜单操做接口和普通默认菜单是同样的,所以能够重用这两个接口,不过因为咱们扩展了查询返回的信息类,因此若是是个性化菜单,那么它返回的JSON字符串里面,包含了conditionalmenu的属性,这个是一个集合 ,也就是说个性化菜单是多个规则的个性化菜单的集合。
菜单的JSON数据结构以下所示。
有了上面接口的封装,咱们能够在建立个性化菜单的时候很方便了,构建个性化菜单的时候,咱们须要把所有须要出现的菜单都须要放在一个conditionalmenu的单元里面,虽然这样的单元在集合里面出现多个。
以下面是构建一个个性化的菜单项目,和普通的默认菜单不一样,它须要指定一个matchrule的对象,以下代码所示。
MenuJson conditional = new MenuJson("相关连接", new MenuJson[] { new MenuJson("个性化菜单", ButtonType.click, "event_company") }); MatchRule rule = new MatchRule() { sex = "1" }; MenuListJson menuJson = new MenuListJson(); menuJson.button.AddRange(new MenuJson[] { conditional }); menuJson.matchrule = rule;
经过上面的代码了解,咱们若是须要增长多个个性化菜单,那么就是经过这个方法,每次建立一个个性化菜单的方式进行构建,固然若是咱们使用查询个性化菜单的结果能够看到,若是建立多个,那么conditionalmenu集合里面是多个对象的。
调用代码每次添加一个个性化菜单的操做以下所示。
string menuid = menuBLL.CreateConditionalMenu(token, menuJson); Console.WriteLine("建立菜单:" + (!string.IsNullOrEmpty(menuid) ? "成功:" + menuid : "失败"));
咱们建立多个规则后,能够经过TryMatch的方式来检查匹配的结果,也就是对应不一样用户(openid)会出现不一样的个性化菜单列表了。
var myResult = menuBLL.TryMatchConditionalMenu(token, openId); if (myResult != null) { Console.WriteLine(myResult.ToJson()); } var userid_female = "oSiLnt2J4mYkhVG3aLTdMIF1hv-s";//女性的ID myResult = menuBLL.TryMatchConditionalMenu(token, userid_female); if (myResult != null) { Console.WriteLine(myResult.ToJson()); }
若是对这个《C#开发微信门户及应用》系列感兴趣,能够关注个人其余文章,系列随笔以下所示:
C#开发微信门户及应用(28)--微信“摇一摇·周边”功能的使用和接口的实现
C#开发微信门户及应用(23)-微信小店商品管理接口的封装和测试
C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密
C#开发微信门户及应用(19)-微信企业号的消息发送(文本、图片、文件、语音、视频、图文消息等)
C#开发微信门户及应用(18)-微信企业号的通信录管理开发之成员管理
C#开发微信门户及应用(17)-微信企业号的通信录管理开发之部门管理
C#开发微信门户及应用(15)-微信菜单增长扫一扫、发图片、发地理位置功能
C#开发微信门户及应用(14)-在微信菜单中采用重定向获取用户数据
C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍
C#开发微信门户及应用(10)--在管理系统中同步微信用户分组信息