Java企业微信开发_04_自定义菜单

一、本节要点

1.菜单相关实体类的封装

参考官方文档中的请求包的内容,对菜单相关实体类进行封装。

这里需要格外注意的是,企业微信中请求包的数据是Json字符串格式的,而不是xml格式。关于json序列化的问题请参考上一节   Java企业微信开发_03_通讯录同步

2.创建菜单的接口

    public static String create_menu_url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN&agentid=AGENTID"; 

注意此处的 ACCESS_TOKEN 与通讯录那里的 ACCESS_TOKEN 不同,记住只有通讯录 ACCESS_TOKEN 才会用到通讯录密钥。其他地方用的都是应用密钥。

还有虽然企业微信和微信公众号开发的接口不同,但是大体思路是相通的。

二、代码实现

1.实体类

按照企业微信官方文档中关于自定义菜单的请求包的说明,定义好实体类。

1.1 按钮的基类——Button

package com.ray.pojo.menu;  

/**
 * @desc  : 按钮的基类
 *
 * @author: shirayner
 * @date  : 2017-8-20 下午9:29:43
 */
public class Button {
    private String name;  

    public String getName() {
        return name;
    }  

    public void setName(String name) {
        this.name = name;
    }
}  

1.2 普通按钮(子按钮) ——CommonButton

package com.ray.pojo.menu;  

/**
 * @desc  : 普通按钮(子按钮)
 *
 * @author: shirayner
 * @date  : 2017-8-20 下午9:29:58
 */
public class CommonButton extends Button {
    private String type;
    private String key;  

    public String getType() {
        return type;
    }  

    public void setType(String type) {
        this.type = type;
    }  

    public String getKey() {
        return key;
    }  

    public void setKey(String key) {
        this.key = key;
    }
}  

1.3 复杂按钮(父按钮) ——ComplexButton

package com.ray.pojo.menu;  

/**
 * @desc  : 复杂按钮(父按钮)
 *
 * @author: shirayner
 * @date  : 2017-8-20 下午9:30:17
 */
public class ComplexButton extends Button {
    private Button[] sub_button;  

    public Button[] getSub_button() {
        return sub_button;
    }  

    public void setSub_button(Button[] sub_button) {
        this.sub_button = sub_button;
    }
}  

1.4 view类型的菜单 ——ViewButton

package com.ray.pojo.menu;  

/**
 * @desc  : view类型的菜单
 *
 * @author: shirayner
 * @date  : 2017-8-20 下午9:30:44
 */
public class ViewButton extends Button {
    private String type;
    private String url;  

    public String getType() {
        return type;
    }  

    public void setType(String type) {
        this.type = type;
    }  

    public String getUrl() {
        return url;
    }  

    public void setUrl(String url) {
        this.url = url;
    }
}  

1.5 菜单——Menu

package com.ray.pojo.menu;  

/**
 * @desc  : 菜单
 *
 * @author: shirayner
 * @date  : 2017-8-20 下午9:30:31
 */
public class Menu {
    private Button[] button;  

    public Button[] getButton() {
        return button;
    }  

    public void setButton(Button[] button) {
        this.button = button;
    }
}  

2.业务类

业务类主要是java对象序列化,获取accessToken以拼接请求ur,发送http请求调用接口。

2.1菜单业务类——MenuService

package com.ray.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.ray.pojo.menu.Button;
import com.ray.pojo.menu.CommonButton;
import com.ray.pojo.menu.ComplexButton;
import com.ray.pojo.menu.Menu;
import com.ray.pojo.menu.ViewButton;
import com.ray.util.WeiXinUtil;

import net.sf.json.JSONObject;

public class MenuService {
    private static Logger log = LoggerFactory.getLogger(MenuService.class);
    // 菜单创建(POST) 限100(次/天)
    public static String create_menu_url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN&agentid=AGENTID";  

    /**
     * 1.创建菜单
     *
     * @param menu 菜单实例
     * @param accessToken 有效的access_token
     * @return 0表示成功,其他值表示失败
     */
    public void createMenu(String accessToken,Menu menu,int agentId) {  

        //1.获取json字符串:将Menu对象转换为json字符串
        Gson gson = new Gson();
        String jsonMenu =gson.toJson(menu);      //使用gson.toJson(user)即可将user对象顺序转成json
        System.out.println("jsonMenu:"+jsonMenu);

        //2.获取请求的url
        create_menu_url = create_menu_url.replace("ACCESS_TOKEN", accessToken)
                .replace("AGENTID", String.valueOf(agentId));  

        //3.调用接口,发送请求,创建菜单
        JSONObject jsonObject = WeiXinUtil.httpRequest(create_menu_url, "POST", jsonMenu);
        System.out.println("jsonObject:"+jsonObject.toString());

        //4.错误消息处理
        if (null != jsonObject) {
            if (0 != jsonObject.getInt("errcode")) {
                log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }  

    }  

    /**
     * 2.组装菜单数据
     *
     * @return
     */
    public  Menu getMenu() {
        ViewButton btn11 = new ViewButton();
        btn11.setName("JSSDK测试");
        btn11.setType("view");
        btn11.setUrl("http://5hcn2d.natappfree.cc/WeiXin_SanFenBaiXue/index.jsp");  

        CommonButton btn12 = new CommonButton();
        btn12.setName("使用帮助");
        btn12.setType("click");
        btn12.setKey("12");  

        CommonButton btn13 = new CommonButton();
        btn13.setName("翻译功能");
        btn13.setType("click");
        btn13.setKey("13");  

        ViewButton btn14 = new ViewButton();
        btn14.setName("上传图片");
        btn14.setType("view");
        btn14.setUrl("http://5hcn2d.natappfree.cc/WeiXin_SanFenBaiXue/uploadimg.jsp");  

        ViewButton btn15 = new ViewButton();
        btn15.setName("上传图片2");
        btn15.setType("view");
        btn15.setUrl("http://5hcn2d.natappfree.cc/WeiXin_SanFenBaiXue/index2.jsp");  

        CommonButton btn21 = new CommonButton();
        btn21.setName("歌曲点播");
        btn21.setType("click");
        btn21.setKey("21");  

        CommonButton btn22 = new CommonButton();
        btn22.setName("经典游戏");
        btn22.setType("click");
        btn22.setKey("22");  

        CommonButton btn23 = new CommonButton();
        btn23.setName("美女电台");
        btn23.setType("click");
        btn23.setKey("23");  

        CommonButton btn24 = new CommonButton();
        btn24.setName("人脸识别");
        btn24.setType("click");
        btn24.setKey("24");  

        CommonButton btn25 = new CommonButton();
        btn25.setName("聊天唠嗑");
        btn25.setType("click");
        btn25.setKey("25");  

        CommonButton btn31 = new CommonButton();
        btn31.setName("Q友圈");
        btn31.setType("click");
        btn31.setKey("31");  

        CommonButton btn33 = new CommonButton();
        btn33.setName("幽默笑话");
        btn33.setType("click");
        btn33.setKey("33");  

        CommonButton btn34 = new CommonButton();
        btn34.setName("用户反馈");
        btn34.setType("click");
        btn34.setKey("34");  

        CommonButton btn35 = new CommonButton();
        btn35.setName("关于我们");
        btn35.setType("click");
        btn35.setKey("35");  

        ViewButton btn32 = new ViewButton();
        btn32.setName("周边搜索");
        btn32.setType("view");
        btn32.setUrl("http://liufeng.gotoip2.com/xiaoqrobot/help.jsp");  

        ComplexButton mainBtn1 = new ComplexButton();
        mainBtn1.setName("生活助手");
        mainBtn1.setSub_button(new Button[] { btn11, btn12, btn13, btn14, btn15 });  

        ComplexButton mainBtn2 = new ComplexButton();
        mainBtn2.setName("休闲驿站");
        mainBtn2.setSub_button(new Button[] { btn21, btn22, btn23, btn24, btn25 });  

        ComplexButton mainBtn3 = new ComplexButton();
        mainBtn3.setName("更多");
        mainBtn3.setSub_button(new Button[] { btn31, btn33, btn34, btn35, btn32 });  

        /**
         * 这是企业号目前的菜单结构,每个一级菜单都有二级菜单项<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;
    }  

}

3.测试类

调用业务类,创建菜单

3.1菜单测试类——MenuTest

package com.ray.test;

import org.junit.Test;

import com.ray.pojo.menu.Menu;
import com.ray.service.MenuService;
import com.ray.util.WeiXinParamesUtil;
import com.ray.util.WeiXinUtil;

public class MenuTest {

  @Test
  public void testCreateMenu(){
      //1.组装菜单
      MenuService ms=new MenuService();
      Menu menu=ms.getMenu();

      //2.获取access_token:根据企业id和应用密钥获取access_token
      String accessToken=WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
      System.out.println("accessToken:"+accessToken);

      //3.创建菜单
      ms.createMenu( accessToken, menu, WeiXinParamesUtil.agentId);

  }

}

三、菜单事件的响应

菜单的事件响应,可归为 消息推送之被动回复消息 的一种(个人理解,望指正)。会在后续博客中补充。

四、参考资料

1.企业微信官方文档:https://work.weixin.qq.com/api/doc#10786

2.柳峰:[038] 微信公众帐号开发教程第14篇-自定义菜单的创建及菜单事件响应

时间: 2024-10-12 19:22:51

Java企业微信开发_04_自定义菜单的相关文章

Java企业微信开发_09_身份验证之移动端网页授权(有完整项目源码)

注: 源码已上传github: https://github.com/shirayner/WeiXin_QiYe_Demo 一.本节要点 1.1 授权回调域(可信域名) 在开始使用网页授权之前,需要先设置一下授权回调域.这里瞬间想到之前做JSSDK的时候,也设置过一个域名.二者本质上都是设置可信域名. 当用户授权完毕之后,请求将重定向到此域名(或者子域名)下的执行者(jsp页面或者servlet等).如何设置授权回调域,请见第二节. 1.2 获取Code https://open.weixin.

Java企业微信开发_03_通讯录同步

一.本节要点 1.获取通讯录密钥 获取方式: 登录企业微信—>管理工具—>通讯录同步助手—>开启“API接口同步”  ; 开启后,即可看到通讯录密钥,也可设置通讯录API的权限:读取或者编辑通讯录. 获取通讯录密钥的目的: 通过企业ID(CorpId)和 通讯录密钥可以获取通讯录相关接口的使用凭证(AccessToken).有了AccessToken,就可以使用通讯录相关接口了. 凭证的获取方式有两种(此处暂时存疑,以待勘误): 通讯录AccessToken:CorpId+通讯录密钥 其

Java企业微信开发_07_素材管理之上传本地临时素材文件

一.本节要点 1.临时素材有效期 media_id是可复用的,同一个media_id可用于消息的多次发送(3天内有效) 2.上传文件时的http请求里都有啥 具体原理可参看: 为什么上传文件的表单需要设置enctype="multipart/form-data" (http://blog.csdn.net/mazhibinit/article/details/49667511) 3.上传本地临时素材到微信服务器的流程 (1)建立与微信服务器的网络连接 (2)从连接中获取输出流(写入微信

Java企业微信开发_08_JSSDK多图上传

一.本节要点 1.1可信域名 所有的JS接口只能在企业微信应用的可信域名下调用(包括子域名),可在企业微信的管理后台“我的应用”里设置应用可信域名.这个域名必须要通过ICP备案,不然jssdk会配置失败 1.2JS-SDK使用权限签名算法 1.2.1 签名生成规则如下: (1)参与签名的字段包括: noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) . (2)对所有待签名参数按照字段名的ASCII

微信开发之自定义菜单--weixin-java-tools

一.前言 平时在开发微信的过程中,肯定会设计到微信的相关菜单的使用,这次就和大家介绍下如何使用weixin-java-tools来管理菜单 二.自定义菜单分类 1.click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互: 2.view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获

Java企业微信开发_09_素材管理之下载微信临时素材到本地服务器

一.本节要点 1.获取临时素材接口 请求方式:GET(HTTPS) 请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID 2.获取临时素材接口的返回结果 企业微信官方开发文档中说明的返回结果如下: 若你以为这就是返回结果,然后跟之前一样,先访问接口,从http连接的输入流中的获取回结果的文本内容,你会发现你接收到的结果是一堆乱码. 这是为何? 以图片为例,此处千

Java企业微信开发_07_总结一下企业微信的配置

一.企业微信后台 1.回调url 2.可信域名 3.菜单跳转按钮中的链接 4.PC端网页授权 二.代码内 1.企业微信的配置信息:WeiXinParamesUtil

php微信开发实现自定义菜单功能

首先说一下遇到的坑吧! 01我用的测试公众号,说好的有接口权限,结果呢,微信留了个坑,返回错误代码 48001 一查错误码 微信文档这样写:api功能未授权,请确认公众号已获得该接口,可以在公众平台官网-开发者中心页中查看接口权限 懵逼了吧! 半信半疑中,我果断换了认证过的服务号,一测试OK了 02代码的开头有空格也会报错,跟tp的机制有关,我的代码在tp下面. 03 调用接口的链接为https,结果我的服务器可能验证证书出错,最后找了半天才找到一种解决办法,就是在使用curl的部分使用如下代码

Java企业微信开发_10_未验证域名归属,JS-SDK功能受限

1.现象: 在企业微信后台填写可信域名后,提示:未验证域名归属,JS-SDK功能受限,如下图: 点击“申请域名校验”后, 注意:域名根目录 当时一直不清楚这个域名根目录在哪里,最后让我给试出来了 2.域名根目录 域名根目录:  tomcat安装目录 /  webapps  /  ROOT / 3.解决方案 将下载的文件放到域名根目录下,勾选“已上传域名归属校验文件”,点击确认即可.