微信公众号开发之自定义菜单

微信开发交流群:148540125

系列文章参考地址 极速开发微信公众号

欢迎留言、转发
项目源码参考地址 点我点我–欢迎Start

前几篇文章已讲完如何导入项目,如何启动配置项目,如何成为开发者,重源码分析消息是如何交互(如果前四项不是很清楚可以看这里 极速开发微信公众号。这篇文章就来讲讲如果实现自定义菜单

实现自定义菜单有两种方式
1、编辑模式
2、开发模式

编辑模式就很简单了就不赘述了……

开发模式实现自定义菜单

1、使用微信公众平台接口调试工具实现
2、使用官方提供的接口实现

前期准备

注意:
1、目前订阅号 只能使用编辑模式而且不能添加超链接,微信认证之后才可以使用开发模式。
2、编辑模式与开发模式不能同时开启
3、生成的菜单不会立即显示(隔天),如果想立即看到效果可以取消关注再关注

添加插件

K8WTIEI86W9W5XERD`MRD{6.png

使用微信公众平台接口调试工具实现

自定义菜单-接口调试工具.png

可以看到需要两个参数而且都是必填 access_token body

有人要问,这两个参数如何获取呢?

body 其实就是要生成菜单的JSON对象 官方有提供一个栗子可以参考

 {
     "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"
            }]
       }]
 }

access_token 的获取如下图
自定义菜单-获取access_token.png

使用官方提供的接口实现

初次了解微信自定义菜单的同学建议先看看官方的文档3遍

Jfinal-weixin中有封装菜单的创建、查询、删除、以及个性化菜单的创建、查询、删除、测试个性化菜单匹配结果

自定义菜单-菜单封装的接口.png

那么问题来了,封装好了如何使用呢?
以下是提供封装的接口

    //查询自定义菜单
    public static ApiResult getMenu() {
        String jsonResult = HttpUtils.get(getMenu + AccessTokenApi.getAccessTokenStr());
        return new ApiResult(jsonResult);
    }
    //创建自定义菜单
    public static ApiResult createMenu(String jsonStr) {
        String jsonResult = HttpUtils.post(createMenu + AccessTokenApi.getAccessTokenStr(), jsonStr);
        return new ApiResult(jsonResult);
    }
    //删除自定义菜单
    public static ApiResult deleteMenu() {
        String jsonResult = HttpUtils.get(deleteMenuUrl + AccessTokenApi.getAccessTokenStr());
        return new ApiResult(jsonResult);
    }
    //创建个性化自定义菜单
    public static ApiResult addConditional(String jsonStr) {
        String jsonResult = HttpUtils.post(addConditionalUrl + AccessTokenApi.getAccessTokenStr(), jsonStr);
        return new ApiResult(jsonResult);
    }
    //删除个性化自定义菜单
    public static ApiResult delConditional(String menuid) {
        HashMap params = new HashMap();
        params.put("menuid", menuid);
        String url = delConditionalUrl + AccessTokenApi.getAccessTokenStr();
        String jsonResult = HttpUtils.post(url, JsonUtils.toJson(params));
        return new ApiResult(jsonResult);
    }
    //测试个性化菜单匹配结果
    public static ApiResult tryMatch(String userId) {
        HashMap params = new HashMap();
        params.put("user_id", userId);
        String url = tryMatchUrl + AccessTokenApi.getAccessTokenStr();
        String jsonResult = HttpUtils.post(url, JsonUtils.toJson(params));
        return new ApiResult(jsonResult);
    }

    public static ApiResult getCurrentSelfMenuInfo() {
        String jsonResult = HttpUtils.get(getCurrentSelfMenuInfoUrl + AccessTokenApi.getAccessTokenStr());
        return new ApiResult(jsonResult);
    }

开源项目weixin_guidecom.javen.weixin.menu.MenuManager类中提供了详细使用的Demo

public static void main(String[] args) { 

           // 将菜单对象转换成json字符串
           String jsonMenu = JsonKit.toJson(getTestMenu()).toString();
           System.out.println(jsonMenu);
           ApiConfig ac = new ApiConfig();

            // 配置微信 API 相关常量 请使用你自己公众号的
            ac.setAppId("wx614c453e0d1dcd12");
            ac.setAppSecret("19a02e4927d346484fc70327970457f9");
//          ac.setAppId(PropKit.get("appId"));
//          ac.setAppSecret(PropKit.get("appSecret"));
            ApiConfigKit.setThreadLocalApiConfig(ac);

           //创建菜单
           ApiResult apiResult=MenuApi.createMenu(jsonMenu);
           System.out.println(apiResult.getJson());
     }  

可以看到main方法中调用了MenuApi.createMenu(jsonMenu)
jsonMenu 从何而来呢?

其实这里是将自定义菜单的实体对象转化为了JSON

String jsonMenu = JsonKit.toJson(getTestMenu()).toString();

菜单的封装

 
             *  
             * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?
* 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义:
* menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 }); */ Menu menu = new Menu(); menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 }); return menu; }" data-snippet-id="ext.c263135461e9345e2fb1fe96fc2d9c0c" data-snippet-saved="false" data-codota-status="done">/** * 组装菜单数据 * * @return */ private static Menu getTestMenu() { ClickButton btn11 = new ClickButton(); btn11.setName("微信相册发图"); btn11.setType("pic_weixin"); btn11.setKey("rselfmenu_1_1"); ClickButton btn12 = new ClickButton(); btn12.setName("拍照或者相册发图"); btn12.setType("pic_photo_or_album"); btn12.setKey("rselfmenu_1_2");; ClickButton btn13 = new ClickButton(); btn13.setName("系统拍照发图"); btn13.setType("pic_sysphoto"); btn13.setKey("rselfmenu_1_3"); ClickButton btn21 = new ClickButton(); btn21.setName("扫码带提示"); btn21.setType("scancode_waitmsg"); btn21.setKey("rselfmenu_2_1");; ClickButton btn22 = new ClickButton(); btn22.setName("扫码推事件"); btn22.setType("scancode_push"); btn22.setKey("rselfmenu_2_2");; ViewButton btn23 = new ViewButton(); btn23.setName("我的设备"); btn23.setType("view"); btn23.setUrl("https://hw.weixin.qq.com/devicectrl/panel/device-list.html?appid=wx614c453e0d1dcd12"); ViewButton btn31 = new ViewButton(); btn31.setName("微社区"); btn31.setType("view"); btn31.setUrl("http://whsf.tunnel.mobi/whsf/msg/wsq"); ClickButton btn32 = new ClickButton(); btn32.setName("发送位置"); btn32.setType("location_select"); btn32.setKey("rselfmenu_3_2"); //http://tencent://message/?uin=572839485&Site=在线咨询&Menu=yes //http://wpa.qq.com/msgrd?v=3&uin=572839485&site=qq&menu=yes ViewButton btn33 = new ViewButton(); btn33.setName("在线咨询"); btn33.setType("view"); btn33.setUrl("http://wpa.qq.com/msgrd?v=3&uin=572839485&site=qq&menu=yes"); ViewButton btn34 = new ViewButton(); btn34.setName("我的博客"); btn34.setType("view"); btn34.setUrl("http://www.cnblogs.com/zyw-205520"); ClickButton btn35 = new ClickButton(); btn35.setName("点击事件"); btn35.setType("click"); btn35.setKey("rselfmenu_3_5"); ComButton mainBtn1 = new ComButton(); mainBtn1.setName("发图"); mainBtn1.setSub_button(new Button[] { btn11, btn12, btn13}); ComButton mainBtn2 = new ComButton(); mainBtn2.setName("扫码"); mainBtn2.setSub_button(new Button[] { btn21, btn22 ,btn23}); ComButton mainBtn3 = new ComButton(); mainBtn3.setName("个人中心"); mainBtn3.setSub_button(new Button[] { btn31, btn32, btn33, btn34 ,btn35 }); /** * 这是公众号xiaoqrobot目前的菜单结构,每个一级菜单都有二级菜单项<br> * * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?<br> * 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义:<br> * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 }); */ Menu menu = new Menu(); menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 }); return menu; }

执行main方法会输出生成菜单的JSON以及响应的状态

生成菜单的JSON:{"button":[{"sub_button":[{"name":"微信相册发图","type":"pic_weixin","key":"rselfmenu_1_1"},{"name":"拍照或者相册发图","type":"pic_photo_or_album","key":"rselfmenu_1_2"},{"name":"系统拍照发图","type":"pic_sysphoto","key":"rselfmenu_1_3"}],"name":"发图","type":null},{"sub_button":[{"name":"扫码带提示","type":"scancode_waitmsg","key":"rselfmenu_2_1"},{"name":"扫码推事件","type":"scancode_push","key":"rselfmenu_2_2"},{"name":"我的设备","type":"view","url":"https://hw.weixin.qq.com/devicectrl/panel/device-list.html?appid=wx614c453e0d1dcd12"}],"name":"扫码","type":null},{"sub_button":[{"name":"微社区","type":"view","url":"http://whsf.tunnel.mobi/whsf/msg/wsq"},{"name":"发送位置","type":"location_select","key":"rselfmenu_3_2"},{"name":"在线咨询","type":"view","url":"http://wpa.qq.com/msgrd?v=3&uin=572839485&site=qq&menu=yes"},{"name":"我的博客","type":"view","url":"http://www.cnblogs.com/zyw-205520"},{"name":"点击事件","type":"click","key":"rselfmenu_3_5"}],"name":"个人中心","type":null}],"matchrule":null}

响应的状态: {"errcode":0,"errmsg":"ok"}

以上是生成自定义菜单的全过程。

欢迎留言、转发
项目源码参考地址 点我点我–欢迎Start

<think> 根据用户的问题,用户希望了解企业微信自定义菜单如何进行分权限设置。结合站内引用内容,我们需要从权限验证和应用菜单设置两个方面来回答。 引用[1]提到,需要对企业微信用户进行权限身份验证,确保只有加入企业微信的用户才能访问。这涉及到身份验证的API。 引用[2]详细介绍了企业微信自定义菜单的创建规则,包括菜单的层级、数量限制等,但并未直接提及分权限设置。 引用[3]是一个OAuth2授权链接的示例,用于网页授权,这可能与菜单权限控制有关。 实际上,企业微信自定义菜单本身并不直接支持为不同用户显示不同菜单。但我们可以通过以下方式实现类似分权限设置的效果: 方法一:利用菜单的可见范围 在创建菜单时,可以设置菜单的可见范围(应用可见范围)。每个应用可以设置可见的部门或成员,这样只有可见范围内的成员才能看到该菜单。 具体步骤: 1. 登录企业微信管理后台,进入需要设置的应用。 2. 在应用设置中,设置该应用的可见范围(即哪些部门或成员可以使用此应用)。 3. 为该应用创建自定义菜单,则只有可见范围内的成员才能看到这个菜单。 方法二:通过菜单事件处理进行权限控制 如果不同权限的用户需要看到同一个菜单项,但点击后执行不同的操作或进入不同的页面,可以在菜单事件处理中进行权限判断。 步骤: 1. 创建菜单时,菜单的key值可以自定义(对于click类型菜单)。 2. 当用户点击菜单时,企业微信会推送事件到应用的回调URL。 3. 在应用服务器接收到事件后,根据用户的身份(userid)判断其权限,然后返回不同的内容(比如跳转到不同的页面)。 方法三:使用网页授权获取用户身份 如果菜单类型是view(跳转到网页),则可以在跳转的URL中使用OAuth2授权来获取用户身份,然后在目标网页中根据用户权限显示不同的内容。 具体实现: 1. 将菜单的跳转URL设置为授权URL(如引用[3]所示),其中redirect_uri参数是经过URL编码的目标页面地址。 2. 用户点击菜单后,企业微信会重定向到授权页面,用户同意授权后,会带着code参数跳转到redirect_uri指定的页面。 3. 在目标页面中,服务器使用code换取用户身份(userid),然后根据该用户的权限动态生成页面内容。 注意:以上方法中,方法一是在菜单显示时就进行了权限控制(直接不显示),方法二和方法三是在用户点击菜单后进行权限控制。 根据引用[2]中的说明,创建菜单时需要注意: - 菜单最多两级,一级菜单最多3个,二级菜单最多5个。 - 菜单的可见范围由应用的可见范围决定。 因此,要实现分权限设置,通常的做法是为不同权限的用户群体创建不同的应用,每个应用设置不同的菜单和可见范围。 总结步骤: 1. 确定需要分权限的菜单项,以及对应的用户群体(部门或成员)。 2. 为每个用户群体创建一个独立的应用(如果已有应用且可见范围不同,则可以直接使用)。 3. 在每个应用中设置自定义菜单菜单内容根据该用户群体的权限设计)。 4. 将应用添加到工作台,或者通过消息型应用的方式让用户使用。 注意:一个用户可能属于多个应用,那么他将看到多个应用的菜单(在应用入口中),但每个应用菜单是独立的。 如果用户希望在一个应用内根据权限动态显示菜单,目前企业微信官方不支持。但可以通过以下变通方式: - 使用一个固定菜单项(如“主菜单”),点击后进入一个导航页面,在该页面中根据用户权限显示不同的导航链接(即用网页模拟菜单)。 引用说明: [^1] 说明了需要做用户权限验证,我们可以利用企业微信提供的API验证用户身份。 [^2] 提供了菜单创建的基本规则,同时提到应用可见范围,这是控制菜单对哪些用户可见的关键。 [^3] 提供了网页授权的链接示例,可用于获取用户身份。 因此,回答用户问题:企业微信自定义菜单的分权限设置主要是通过设置应用的可见范围来实现的,即为不同权限的用户群体创建不同的应用,每个应用设置自己的菜单和可见范围。 此外,还可以在菜单点击事件处理中或跳转页面中根据用户权限进行后续的权限控制。 </think>### 企业微信自定义菜单分权限设置方法 企业微信自定义菜单的分权限设置主要通过以下两种方式实现,核心原理是**将菜单与应用绑定,通过应用的可见范围控制菜单权限**: #### 方法一:基于应用可见范围(推荐) 1. **创建独立应用** 为不同权限组创建独立应用(如:管理员应用/员工应用),每个应用拥有专属菜单 ```markdown 企业微信管理后台 > 应用管理 > 创建应用 ``` 2. **设置应用可见范围** 在应用设置中指定可见的部门/成员(权限组): ```markdown 应用详情 > 可见范围 > 选择部门/成员 ``` ![应用可见范围设置](https://example.com/permission-setting.png)[^2] 3. **创建分权菜单** 在不同应用中创建专属菜单,系统会根据可见范围自动控制菜单显示: ```markdown 应用管理 > 进入目标应用 > 自定义菜单 > 创建菜单 ``` #### 方法二:基于菜单事件权限验证 1. **统一菜单配置** 在单个应用中创建通用菜单,但所有菜单项指向业务系统(非直接跳转链接) 2. **菜单点击事件处理** 当用户点击菜单时,通过OAuth2.0获取用户身份: ```python # 伪代码:验证用户权限 def menu_click_handler(user_id): if user_id in admin_group: # 权限验证 return admin_page # 返回管理员页面 else: return default_page # 返回普通用户页面 ``` 3. **权限验证API调用** 使用企业微信[成员身份验证接口](https://work.weixin.qq.com/api/doc/90000/90135/91022): ```http GET https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?code=CODE ``` #### 关键限制说明[^2] 1. 菜单可见性由应用可见范围决定,无法在单应用内设置菜单项级权限 2. 权限变更同步周期 ≤24小时(因微信客户端缓存) 3. 权限组划分上限: - 最大部门层级:15层 - 部门总数上限:3万个 - 标签总数上限:3000个 #### 操作建议 1. **测试技巧** 取消关注后重新关注企业号,可立即刷新菜单权限(避免24小时缓存等待) 2. **权限架构设计** ```mermaid graph TD A[权限组划分] --> B[管理组] A --> C[财务组] A --> D[普通员工] B --> E[创建管理专用应用] C --> F[创建财务专用应用] D --> G[创建员工应用] ``` 3. **兼容性注意** 旧版微信(<iPhone5.4.1/Android5.4)仅支持click/view类型菜单事件[^2] > **最佳实践**:结合[网页授权登录](https://open.weixin.qq.com/connect/oauth2/authorize)[^3]实现细粒度权限控制,在业务系统中进行二次权限校验。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值