Java 微信公众平台开发(四)——自定义菜单的实现

在完成了微信公众号的接入之后,菜单功能就不能直接在公众号的后台进行编辑了,我们需要自己开发菜单功能,丰富公众号的功能

自定义菜单分为一级菜单和二级菜单
菜单实际上就是按钮,自定义菜单接口可实现多种类型按钮:

1.click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
2.view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。
3.scancode_push:扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。
4.scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。
5.pic_sysphoto:弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。
6.pic_photo_or_album:弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。
7.pic_weixin:弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。
8.location_select:弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
9.media_id:下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id
10.view_limited:跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。

这里以click与view的请求为例

{
     "button":[
     {    
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "name":"菜单",
           "sub_button":[
           {    
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
                 "type":"miniprogram",
                 "name":"wxa",
                 "url":"http://mp.weixin.qq.com",
                 "appid":"wx286b93c14bbf93aa",
                 "pagepath":"pages/lunar/index"
             },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }

这里我将自定义菜单直接写成json文件来读取。
menu.json

/* 自定义菜单json文件 */

 {
    "button": [
        {
            "name": "快来世界",
            "sub_button": [
                {
                    "type": "click",
                    "name": "BUG反馈",
                    "key": "CLICK_BUG"
                },
                {
                    "type": "click",
                    "name": "人工客服",
                    "key": "CLICK_RGKF"
                },
                {
                    "type": "view",
                    "name": "游戏下载",
                    "url": "http://www.soso.com/"
                }
            ]
        },
        {
            "name": "推广提现",
            "sub_button": [
                {
                    "type": "view",
                    "name": "H5",
                    "url": "http://www.soso.com/"
                },
                {
                    "type": "miniprogram",
                    "name": "王牌跑得快",
                    "url": "https://h5game.miko.cn",
                    "appid": "wxf12321412423412421",
                    "pagepath": ""
                }
            ]
        },
        {
            "type": "view",
            "name": "游戏盒子",
            "url": "http://www.soso.com/"
        }
    ]
}

菜单在项目启动等时候被调用

package cc.feefox.wechat;

import javax.servlet.ServletException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

import cc.feefox.wechat.common.constant.WechatConstant;
import cc.feefox.wechat.common.json.JsonConfig;
import cc.feefox.wechat.menu.MenuService;
import cc.feefox.wechat.token.TokenThread;

@SpringBootApplication
@EnableScheduling // 这里,启用定时任务(待扩展)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        try {
            init();
            while (1 > 0) {
                if (WechatConstant.ACCESS_TOKEN != null) {
                    menu();
                    break;
                }
            }
        } catch (ServletException e) {
            e.printStackTrace();
        }
    }

    public static void init() throws ServletException {

        // 启动线程定时获取access_token
        new Thread(new TokenThread()).start();
    }

    // 自定义菜单
    public static void menu() {

        String access_token = WechatConstant.ACCESS_TOKEN;
        String menu = JsonConfig.getJsonResource("datas/menu").toString();
        MenuService.createMenu(menu, access_token);
    }
}

工具类JsonConfig用来读取json文件

package cc.feefox.wechat.common.json;

import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;

/**
 * 读取配置文件(仅json)数据
 * 
 * @Package: cc.feefox.wechat.common.json
 * @author: cc
 * @date: 2018年8月22日 上午11:22:47
 */
public class JsonConfig {

    private static final Logger logger = LoggerFactory.getLogger(JsonConfig.class);

    /*
     * 根据json文件名称获取json配置文件数据
     *
     * @param fileName json文件名称前缀,如果在resource下直接写文件名,如果有路径,请在前面添加路径如:"com/xxx/abc"
     */
    public static JSONObject getJsonResource(String fileName) {

        fileName += ".json";
        ClassLoader classLoader = getClassLoader();

        Enumeration<URL> resources;
        JSONObject jsonObject = new JSONObject();
        try {
            resources = classLoader.getResources(fileName);
        } catch (IOException e) {
            logger.warn("getJsonResource fail {}", fileName, e);
            return jsonObject;
        }

        while (resources.hasMoreElements()) {
            URL url = resources.nextElement();
            try {
                String json = Resources.toString(url, Charsets.UTF_8);
                jsonObject.putAll(JSON.parseObject(json)); // 有多个的时候,后面的覆盖前面的
            } catch (IOException e) {
                logger.warn("addJsonFile fail url:{}", url, e);
            }
        }
        return jsonObject;
    }

    private static ClassLoader getClassLoader() {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader != null) {
            return classLoader;
        }
        return JsonConfig.class.getClassLoader();
    }

    /**
     * 私有构造方法,防止工具类被new
     */
    private JsonConfig() {
        throw new IllegalAccessError();
    }
}

读取到文件后,创建菜单

package cc.feefox.wechat.menu;

import org.apache.log4j.Logger;

import cc.feefox.wechat.common.util.HttpUtil;
import net.sf.json.JSONObject;

/**
 * 菜单创建
 * 
 * @Package: cc.feefox.wechat.menu 
 * @author: cc   
 * @date: 2018年8月22日 下午9:12:30
 */
public class MenuService {

    public static Logger log = Logger.getLogger(MenuService.class);

    /**
     * 菜单创建(POST) 限100(次/天)
     */
    public static String MENU_CREATE = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";

    /**
     * 菜单查询
     */
    public static String MENU_GET = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";

    /**
     * 创建菜单
     * 
     * @param jsonMenu 
     * json格式
     * @return 状态 0 表示成功、其他表示失败
     */
    public static Integer createMenu(String jsonMenu, String access_token) {
        int result = 0;
        if (access_token != null) {
            // 拼装创建菜单的url
            String url = MENU_CREATE.replace("ACCESS_TOKEN", access_token);
            // 调用接口创建菜单
            JSONObject jsonObject = null;
            try {
                jsonObject = HttpUtil.httpsRequest(url, "POST", jsonMenu);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if (null != jsonObject) {
                if (0 != jsonObject.getInt("errcode")) {
                    result = jsonObject.getInt("errcode");
                    log.error("创建菜单失败 errcode:" + jsonObject.getInt("errcode")
                            + ",errmsg:" + jsonObject.getString("errmsg"));
                }
            }
        }
        return result;
    }
}

启动项目,创建菜单

如有错漏请指出,欢迎加群 581817132
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值