精华内容
下载资源
问答
  • 微信公众号个性化菜单

    千次阅读 2016-07-27 22:02:58
    百度上查了下,微信还真提供了这种解决方案,名叫个性化菜单。 这个功能有个缺陷,更改过后的菜单不能立马生效,有几分钟的延迟。后来项目里还是放弃了这个方案。因为发现网上讲这块的还是很少。还是值得总结下。...

    之前项目里需求需要根据不同用户类型显示不同的微信公众号菜单。百度上查了下,微信还真提供了这种解决方案,名叫个性化菜单。
    这个功能有个缺陷,更改过后的菜单不能立马生效,有几分钟的延迟。后来项目里还是放弃了这个方案。因为发现网上讲这块的还是很少。还是值得总结下。希望能帮到有需要的童鞋。

    
    /**
     * Created by Administrator on 16-6-24.
     */
    public class CreateMenu {
    
        private static final String   ACCESS_TOKEN  ="YL6F996Sb8q-Iqfipm5_irvKUtyq789HYl8jcWABL5tOuTabvROzn0W5AQSp6soSUEr7BCn3P2iMvgrKqD7dtjn8JOFTRWZixP0flskKA7dPw5y1diOzfdt1UOd2udcWWFfACADDM";
        public static void main(String[] args) {
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            String url ="https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token="+ Token.getAccess_token();
            String menue = "{\n" +
                    " \t\"button\":[\n" +
                    "            {\n" +
                    "                \"name\": \"气象监测\", \n" +
                    "                \"sub_button\": [\n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"大风信息\", \n" +
                    "                        \"url\": \"http://www.xxx.com/ooo/eee/windhome.jsp\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }, \n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"雨量监测\", \n" +
                    "                        \"url\": \"http://www.xxx.com/ooo/eee/rainhome.jsp\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }, \n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"雷暴监测\", \n" +
                    "                        \"url\": \"http://www.xxx.com/ooo/eee/thunderstormWeatherTable.jsp\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }, \n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"能见度\", \n" +
                    "                        \"url\": \"http://www.xxx.com/ooo/eee/fogWeatherTable.jsp\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }\n" +
                    "                ]\n" +
                    "            }, \n" +
                    "            {\n" +
                    "                \"name\": \"台风信息\", \n" +
                    "                \"sub_button\": [\n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"台风监测\", \n" +
                    "                        \"url\": \"http://tf.szmb.gov.cn/wap.htm?ver=2.0\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }, \n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"卫星云图\", \n" +
                    "                        \"url\": \"http://www.xxx.com/ooo/eee/cloudWeatherTable.jsp\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }\n" +
                    "                ]\n" +
                    "            }, \n" +
                    "\t\t\t {\n" +
                    "                \"name\": \"预报预警\", \n" +
                    "                \"sub_button\": [\n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"预报预警\", \n" +
                    "                        \"url\": \"http://www.xxx.com/ooo/eee/forecastWarning.jsp\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }, \n" +
                    "                    {\n" +
                    "                        \"type\": \"view\", \n" +
                    "                        \"name\": \"更改登录\", \n" +
                    "                        \"url\": \"https://open.weixin.qq.com/connect/oauth2/authorize?appid=youid&redirect_uri=yourul\", \n" +
                    "                        \"sub_button\": [ ]\n" +
                    "                    }\n" +
                    "                ]\n" +
                    "            }\n" +
                    "        ],\n" +
                    "\"matchrule\":{\n" +
                    "  \"tag_id\":\"104\",\n" +
                    " \n" +
                    "  }\n" +
                    "}";
    
            String s = up.sendPost(url,menue);   // res:{"menuid":705067163}
            System.out.println(s);
        }
    
    }
    

    工具类UploadGetImagesRequest 类中 发送url请求方法

        /**
         * 向指定URL发送POST方法的请求
         * @param
         * @param param
         *            请求参数,格式应该满足name1=value1&name2=value2的形式。
         * @return URL所代表远程资源的响应
         */
        public static String sendPost(String sendurl, String param) {
            String result = "";
            try {
                // 创建连接
                URL url = new URL(sendurl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestMethod("POST");
                connection.setUseCaches(false);
    
                connection.setInstanceFollowRedirects(true);
                connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                // connection.connect();
    
                // POST请求
                //DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                PrintWriter out = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(),"utf-8"));
                out.write(param);
                out.flush();
                out.close();
    
                // 读取响应 发送
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8"));
    
                String lines = null;
                StringBuffer sb = new StringBuffer("");
                while ((lines = reader.readLine()) != null) {
                    //lines = new String(lines.getBytes(), "utf-8");
                    //System.out.println(lines);
                    sb.append(lines);
                }
                result = sb.toString();
    
                reader.close();
                // 断开连接
                connection.disconnect();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }
    
    /**
         * 向指定URL发送GET方法的请求
         * @param url 发送请求的URL
         * @param param 请求参数,格式满足name1=value1&name2=value2的形式。
         * @return URL所代表远程资源的响应
         */
        public static String sendGet(String url , String param)
        {
            String result = "";
            String urlName = url + "?" + param;
            try
            {
                URL realUrl = new URL(urlName);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                // 设置通用的请求属性
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("user-agent"
                        , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
                // 建立实际的连接
                conn.connect();
                // 获取所有响应头字段
                Map<String, List<String>> map = conn.getHeaderFields();
                // 遍历所有的响应头字段
                for (String key : map.keySet())
                {
                    //System.out.println(key + "--->" + map.get(key));
                }
                try(
                        // 定义BufferedReader输入流来读取URL的响应
                        BufferedReader in = new BufferedReader( new InputStreamReader(conn.getInputStream() , "utf-8")))
                {
                    String lines = null;
                    StringBuffer sb = new StringBuffer("");
                        while ((lines = in.readLine()) != null) {
    
                        sb.append(lines);
                    }
                    result = sb.toString();
                }
            }
            catch(Exception e)
            {
                System.out.println("发送GET请求出现异常!" + e);
                e.printStackTrace();
            }
            System.out.println("res:"+result);
            return result;
        }
    
    
    

    获取token

    /**
     * Created by Administrator on 16-6-24.
     */
    public class GetToken {
    
        public static void main(String[] args) {
            String id="xxx";
            String key ="ooo";
            String url ="https://api.weixin.qq.com/cgi-bin/token";
            String parm ="grant_type=client_credential&appid="+id+"&secret="+key;
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            up.sendGet(url,parm);
        }
    }
    

    管理用户组

    
    /**
     * Created by Administrator on 16-6-24.
     */
    public class ManageUserGroup {
    
        private static final String   ACCESS_TOKEN  ="YL6FWQTK6Sb8q-Iqfipm5_irvKUererl8jcWABL5tOuTabvROzn0W5AQSp6soSUEr7BCn3P2iMvgrKqD7dtjn8JOvcfdxP0flskKA7derediOzfdt1UOd2udcWWFfACADDM";
    
        public static void main(String[] args) {
    
            //queryAllGroup();
            //res:{"groups":[{"id":0,"name":"未分组","count":17},
            // {"id":1,"name":"黑名单","count":0},
            // {"id":2,"name":"星标组","count":0},
            // {"id":101,"name":"thunder","count":0},
            // {"id":102,"name":"haven","count":0},
            // {"id":103,"name":"subway125","count":0},
            // {"id":104,"name":"subway3","count":0}]}
           // mvUserToGroup();
            //queryUserGroupId();
            //delGroup();
            //createGroup();
            queryAllGroup();
        }
    
        /**
         * 创建组
         */
        public static void createGroup(){
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            String url ="https://api.weixin.qq.com/cgi-bin/groups/create?access_token="+ Token.getAccess_token();
            String menue ="{\"group\":{\"name\":\"subway3\"}}";
            up.sendPost(url,menue);
            // res:{"group":{"id":100,"name":"user1"}}
            //res:{"group":{"id":101,"name":"user2"}}
            //res:{"group":{"id":102,"name":"user3"}}
        }
    
    
        /**
         * 查询所有组
         */
        public static  void queryAllGroup(){
            //https://api.weixin.qq.com/cgi-bin/groups/get?access_token=ACCESS_TOKEN
            String url ="https://api.weixin.qq.com/cgi-bin/groups/get";
            String parm ="access_token="+ Token.getAccess_token();
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            up.sendGet(url,parm);
        }
    
        /**
         * 移动用户到某组
         */
        public static void mvUserToGroup(String userid,String groupid) {
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            String url = "https://api.weixin.qq.com/cgi-bin/groups/members/update?access_token="+ Token.getAccess_token();
            String param = "{\"openid\":\""+userid+"\",\"to_groupid\":"+groupid+"}";
            String res =  up.sendPost(url,param);
            System.out.println("移动用户到组:"+res);
        }
    
        /**
         * 查询用户组id
         */
        public  static  void queryUserGroupId(){
            //https://api.weixin.qq.com/cgi-bin/groups/getid?access_token=ACCESS_TOKEN
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            String url = "https://api.weixin.qq.com/cgi-bin/groups/getid?access_token="+ Token.getAccess_token();
            String param = "{\"openid\":\"youid\"}";  //res:{"groupid":0}
            up.sendPost(url,param);
    
        }
    
        public static void delGroup(){
    //https://api.weixin.qq.com/cgi-bin/groups/delete?access_token=ACCESS_TOKEN
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            String url = "https://api.weixin.qq.com/cgi-bin/groups/delete?access_token="+ Token.getAccess_token();
            String param = "{\"group\":{\"id\":100}}";
            up.sendPost(url,param);
        }
    
    }
    

    查询菜单

        public static void main(String[] args) {
    
            String url ="https://api.weixin.qq.com/cgi-bin/menu/get";
            String parm ="access_token="+ Token.getAccess_token();
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            up.sendGet(url,parm);
        }
    

    匹配用户和菜单

      public static void main(String[] args) {
    
            // 测试匹配菜单
            UploadGetImagesRequest up = new UploadGetImagesRequest();
            String url ="https://api.weixin.qq.com/cgi-bin/menu/trymatch?access_token="+ Token.getAccess_token();
            String menue ="{\n" +
                    "\t\"user_id\":\"微信唯一id\"\n" +
                    "}";
            String s =  up.sendPost(url,menue);
            System.out.println(s);
        }

    小技巧,使用IDEA 粘贴一串字符时可以自动分割补齐转义号很方便。

    展开全文
  • 微信公众号个性化菜单-用户标签
  • 10万+IT人都在关注,史上最全面的微信开发实战教程:包含公众号,小程序,微信支付等开发案例 欢迎关注笔者个人博客:http://blogs.chenyunkeji.com/ 首先,直接上图,看效果,如下,有三个根菜单,每个菜单上有...

    10万+IT人都在关注,史上最全面的微信开发实战教程:包含公众号,小程序,微信支付等开发案例

    欢迎关注笔者个人博客:http://blogs.chenyunkeji.com/

    首先,直接上图,看效果,如下,有三个根菜单,每个菜单上有不同类型的子菜单,点击子菜单可以实现用户和公众号实时交互

    http://blogs.chenyunkeji.com

    本案例技术栈:springboot,mysql,logback,mybatis

    菜单创建请求接口:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

    首先是菜单项(按钮)的基类,所有一级菜单、二级菜单都有一个相同的属性,那就是name。菜单项基类的封装代码如下:

    public class Button {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    接着是子菜单项的封装。这里对子菜单是这样定义的:底部根菜单的二级菜单。这类子菜单项一定会包含三个属性:type、name和key,封装的代码如下

    public class CommandButton 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;
        }
    }

     接着封装父菜单项。对父菜单项的定义:包含有二级菜单项的一级菜单。这类菜单项包含有二个属性:name和sub_button,而sub_button是一个子菜单项数组。父菜单项的封装代码如下:

    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;
        }
    }

    最后是整个菜单对象的封装,菜单对象包含多个根菜单项(最多只能有3个),这些菜单项即可以是子菜单项(不含二级菜单的一级菜单),也可以是父菜单项(包含二级菜单的菜单项),如果能明白上面所讲的,再来看封装后的代码就很容易理解了:

    public class Menu {
        private Button[] button;
        public Button[] getButton() {
            return button;
        }
    
        public void setButton(Button[] button) {
            this.button = button;
        }
    }

     最后再封装一个链接类型的菜单,根据此处的名字也很好理解,不再赘述

    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;
        }
    }

    关于菜单实体类以及菜单对象的封装就介绍完了,下面根据微信接口创建自定义菜单。

    一、封装菜单创建工具类

    public class WeiXinMenuUtil {
    
        private static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";        private static Logger log = LoggerFactory.getLogger(WeiXinMenuUtil.class);
        public static int createMenu(Menu menu, String accessToken) {
            int result = 0;
            // 拼接创建菜单的url
            String url = menu_create_url .replace("ACCESS_TOKEN", accessToken);
            // 将菜单对象转换成json字符串
            String jsonMenu = JSON.toJSONString(menu);
            // 调用接口创建菜单
            JSONObject jsonObject = WeiXinUtil.httpPost(url, "POST", jsonMenu);
            if (null != jsonObject) {
                if (0 != (Integer)jsonObject.get("errcode")) {
                    result = (Integer)jsonObject.get("errcode");
                    log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.get("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return result;
        }
        
        public static Menu initMenu(){
            //1.创建菜单
            Menu menu = new Menu();
            // 主菜单1
            ComplexButton cb1 = new ComplexButton();
            cb1.setName("技术干货");
            
            // 主菜单2
            ComplexButton cb2 = new ComplexButton();
            cb2.setName("交流合作");
            
            // 主菜单3
            ComplexButton cb3 = new ComplexButton();
            cb3.setName("演示功能");
            
            // 主菜单1下面的子菜单1
            ViewButton cb01 = new ViewButton();
            cb01.setName("微服务教程连载");
            cb01.setType("view");
            cb01.setUrl("https://blog.csdn.net/guobinhui/article/category/8739270");
            
            // 主菜单1下面的子菜单2
            ViewButton cb02 = new ViewButton();
            cb02.setName("公众号开发教程");
            cb02.setType("view");
            cb02.setUrl("https://blog.csdn.net/guobinhui/article/category/8534361");
            
            ViewButton cb03 = new ViewButton();
            cb03.setName("小程序开发教程");
            cb03.setType("view");
            cb03.setUrl("https://blog.csdn.net/guobinhui/article/category/7763266");
            
            ViewButton cb04 = new ViewButton();
            cb04.setName("JavaEE基础");
            cb04.setType("view");
            cb04.setUrl("https://blog.csdn.net/guobinhui");
            
            ViewButton cb05 = new ViewButton();
            cb05.setName("笔者博客");
            cb05.setType("view");
            cb05.setUrl("http://blogs.chenyunkeji.com/");
            cb1.setSub_button(new ViewButton[]{cb01,cb02,cb03,cb04,cb05});
            
            // 主菜单2下面的子菜单1
            CommandButton cb11 = new CommandButton();
            cb11.setType("click");
            cb11.setKey("联系我");
            cb11.setName("联系笔者");
            
            CommandButton cb12 = new CommandButton();
            cb12.setName("技术交流");
            cb12.setType("click");
            cb12.setKey("18629374628");
            cb2.setSub_button(new CommandButton[]{cb11,cb12});
            
            CommandButton cb21 = new CommandButton();
            cb21.setType("scancode_waitmsg");
            cb21.setKey("rselfmenu_0_0");
            cb21.setName("扫码带提示");
            
            CommandButton cb22 = new CommandButton();
            cb22.setType("pic_sysphoto");
            cb22.setKey("rselfmenu_1_0");
            cb22.setName("系统拍照发图");
            
            CommandButton cb23 = new CommandButton();
            cb23.setType("pic_photo_or_album");
            cb23.setKey("rselfmenu_1_1");
            cb23.setName("拍照或者相册发图");
            
            CommandButton cb24 = new CommandButton();
            cb24.setType("pic_weixin");
            cb24.setKey("rselfmenu_1_2");
            cb24.setName("微信相册发图");
            
            CommandButton cb25 = new CommandButton();
            cb25.setType("location_select");
            cb25.setKey("rselfmenu_2_0");
            cb25.setName("发送地理位置");
            cb3.setSub_button(new CommandButton[]{cb21, cb22,cb23, cb24,cb25});
            menu.setButton(new Button[] { cb1,cb2, cb3});
            return menu;        
        }
    }

    二、微信接口凭证access_token的获取以及缓存实现

    access_token可以用各种缓存插件或者线程,定时任务,写入数据库等多种方式对access_token进行缓存7200秒,开发者可以依据自己的喜好选择其一,本案例策略采用IO流定时写入文件的方法缓存。首先获取access_token:

    public static JSONObject getToken()throws IOException{
    
     private String GET_ACCESS_TOKEN= "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
     String url = GET_ACCESS_TOKEN.replace("APPID",WeixinConstant.APPID).replace("APPSECRET",WeixinConstant.APPSECRET);
       JSONObject tokenObj = HttpGet(url);
       return tokenObj;
    }

    接着缓存access_token,也就是每隔7200秒生成一次access_token,生成的缓存7200秒,这样其余用到access_token的从文件中读取的就是最新的,不会过期。

    public static  Map <String,Object> cacheToken() throws IOException {
          Gson gson = new Gson();
          Map <String,Object> map = new HashMap <String,Object> ();
          String token = null;
          JSONObject tokenObj = null; //需要获取的access_token对象;
          String filePath = System.getProperty("user.dir")+"/src/main/resources/static/token.txt";
          File file = new File(filePath);//Access_token保存的位置
          if (!file.exists())
            file.createNewFile();
          // 如果文件大小等于0,说明第一次使用,存入Access_token
          if (file.length() == 0) {
            tokenObj = WeiXinUtil.getToken();
            token = (String)tokenObj.get("access_token");
            FileOutputStream fos = new FileOutputStream(filePath, false);// 不允许追加
            tokenObj.put("expires_in",System.currentTimeMillis()/1000+"");
            String json = gson.toJson(tokenObj);
            fos.write(json.getBytes());
            fos.close();
          }else {
            //读取文件内容
            @SuppressWarnings("resource")
            FileInputStream fis = new FileInputStream(file);
            byte[] b = new byte[2048];
            int len = fis.read(b);
            String jsonAccess_token = new String(b, 0, len);// 读取到的文件内容
            JSONObject access_token = gson.fromJson(jsonAccess_token,JSONObject.class);
            if (access_token.get("expires_in") != null) {
              String lastSaveTime = (String)access_token.get("expires_in");
              long nowTime = System.currentTimeMillis()/1000;
              long remianTime = nowTime - Long.valueOf(lastSaveTime);
              if (remianTime < WeixinConstant.EXPIRESIN_TIME) {
                  JSONObject access = gson.fromJson(jsonAccess_token,JSONObject.class);
                  token = (String)access.get("access_token");
              } else {
                  tokenObj = WeiXinUtil.getToken();
                  FileOutputStream fos = new FileOutputStream(file, false);// 不允许追加
                  tokenObj.put("expires_in",System.currentTimeMillis()/1000+"");
                  String json = gson.toJson(tokenObj);
                  fos.write((json).getBytes());
                  fos.close();
              }
          }
          }
          map.put("access_token",token);
          return map;
        }

    最后在项目的启动入口文件的main方法调用菜单创建方法进行初始化,那么项目在启动的时候,公众号的菜单就进行了初始化,用户就能看到公众号的菜单。

    @SpringBootApplication
    @MapperScan(basePackages = "com.chenyun.cloud.dao")
    public class HelloServiceApplication {
        private final static Logger logger= LoggerFactory.getLogger(HelloServiceApplication.class);
        
        public static void main(String[] args) {
             SpringApplication.run(HelloServiceApplication.class, args);
             Map<String, Object> map;
            try {
                map = WeiXinUtil.cacheToken();
                 String accessToken = (String)map.get("access_token");
                 logger.info("accessToken:"+accessToken);
                 Menu menu = WeiXinMenuUtil.initMenu();
                 System.out.println(JSON.toJSONString(menu));
                 int result  = WeiXinMenuUtil.createMenu(menu,accessToken);
                 if (0 == result){
                      logger.info("菜单创建成功!");
                  }else{
                      logger.info("菜单创建失败,错误码:" + result);
                  }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }    
    }

    启动项目后,打印的JSON格式的日志打就显示了创建的菜单结构。

    下节内容为大家分享公众号菜单栏的各种点击事件开发案例,更多JavaEE资料请关注下面公众号,欢迎广大开发者朋友一起交流。更多微信公众号功能演示请扫码体验,笔者电话(微信):18629374628

    展开全文
  • 微信公众号生成个性化菜单

    千次阅读 2016-12-22 20:33:30
    微信公众号后来新增的接口,可以生成个性化菜单,可以先看下个性化菜单与自定义菜单的数据格式有哪些不同。 在原有的数据格式基础上,增加了以下部分: "matchrule":{ "group_id":"2", "sex":"1", "country":...

    微信公众号后来新增的接口,可以生成个性化菜单,可以先看下个性化菜单与自定义菜单的数据格式有哪些不同。

    在原有的数据格式基础上,增加了以下部分:

    "matchrule":{
      "group_id":"2",
      "sex":"1",
      "country":"中国",
      "province":"广东",
      "city":"广州",
      "client_platform_type":"2"
      "language":"zh_CN"
      }
    也就是匹配规则,这个匹配是完全匹配,即当符合所有的匹配条件的时候才会出发定义的个性化菜单。另一点,必须得先定义自定义菜单的基础上才可以再实现个性化菜单。

    解释一下:group_id就是分组的名称,不同的分组有不同的id号,这个可以做一个二次开发,比如说不同分组的用户可以看到的是不同的菜单,那么问题来了,如何让用户自动进入不同的分组呢,这里就有一个点,即用户在关注的时候,扫描带参数二维码实现自动分组、扫描不同二维码实现自动分组,在此请参考我的另2篇文章,扫描带参数二维码实现自动分组的功能,http://blog.csdn.net/naruto668/article/details/52374082

    sex是根据用户性别区分;country,province,city这个说句心里话可能不太准确,具体可根据地理位置的不同来做大致的划分,不要太当真。毕竟是用户自己设置的,对吧~

    client_platform_type客户端版本,当前只具体到系统型号:IOS(1), Android(2),Others(3),不填则不做匹配

    最后一栏代表着语言,这个其实没什么太大的区分度。

    好了看代码实现。

    <?php
     $jsonmenu='{
         "button":[
           {
               
                   "type":"view",
                   "name":"点",
                   "url":"http://url.cn/420hqFb"
           },
          {
               "name":"扫",
               "sub_button":[
               {
                   "type":"click",
                   "name":"解码手册",
                   "key":"V201"
                },
                {
                   "type":"view",
                   "name":"扫一扫",
                   "url":"http://g-cat.me/platform/weixin/scanCode.do?code=dksj&share_voucher=voucher"
                }]
           },
           {
               "name":"挖",
               "sub_button":[
               
                {
                   "type":"view",
                   "name":"品牌故事",
                   "url":"http://mp.weixin.qq.com/s?__biz=MzA3OTQ3Mzc2Mw==&mid=210864245&idx=1&sn=243961660f7eb8ad7f4e2410b4a354af&scene=18#wechat_redirect"
                },
                {
                   "type":"view",
                   "name":"门店信息",
                   "url":"http://mp.weixin.qq.com/s?__biz=MzA3OTQ3Mzc2Mw==&mid=442478945&idx=1&sn=49722ea5e9b293fcff6ca819c4b0b26d&scene=0#rd"
                },
                {
                   "type":"view",
                   "name":"往期文章",
                   "url":"http://mp.weixin.qq.com/s?__biz=MzA3OTQ3Mzc2Mw==&mid=206509356&idx=1&sn=9daa46ba7a65e6b7daca01f43503a763&scene=0#rd"
                }]
           }],
           "matchrule":{
            "group_id":"140"
          }
     }';

    //获取accesstoken的实现我在前面已经讲过了

    require('Accesstoken.php');
    $access_token=get_token();
    $url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=".$access_token;
    $result = https_request($url, $jsonmenu);
    var_dump($result);
    function https_request($url,$data = null){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
    ?>

    展开全文
  • 微信公众号更新新增菜单

    前言

    微信要更新底部的菜单,只更新二级菜单的链接,找了微信API,发现没有更新接口,根据菜单节点更新啥的。怎么实现这个功能,其实微信后台就有对应的菜单更新方法,网上绝大多数教程都是这么教的,我这边是通过微信API更新的。

    解决

    微信虽然没有更新的接口但是有新增删除的接口啊,这里再说个小细节微信新增接口会替换之前的菜单,说白了就是全部换新
    微信自定义菜单API
    所以第一步,先查询所有的自定义菜单

    获取旧自定义菜单

    使用接口创建自定义菜单后,开发者还可使用接口查询自定义菜单的结构。另外请注意,在设置了个性化菜单后,使用本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息。

    给个ACCESS_TOKEN就能获取了

    URL

    http请求方式:GET https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
    
    https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
    

    返回

     {
        "menu": {
            "button": [
                {
                    "type": "click", 
                    "name": "今日歌曲", 
                    "key": "V1001_TODAY_MUSIC", 
                    "sub_button": [ ]
                }, 
                {
                    "type": "click", 
                    "name": "歌手简介", 
                    "key": "V1001_TODAY_SINGER", 
                    "sub_button": [ ]
                }, 
                {
                    "name": "菜单", 
                    "sub_button": [
                        {
                            "type": "view", 
                            "name": "搜索", 
                            "url": "http://www.soso.com/", 
                            "sub_button": [ ]
                        }, 
                        {
                            "type": "view", 
                            "name": "视频", 
                            "url": "http://v.qq.com/", 
                            "sub_button": [ ]
                        }, 
                        {
                            "type": "click", 
                            "name": "赞一下我们", 
                            "key": "V1001_GOOD", 
                            "sub_button": [ ]
                        }
                    ]
                }
            ]
        }
    }
    

    如下 这就是你的所有自定义菜单,这是官方写的,实际上自己拿到的会很多。

    新增自定义菜单

    复制下你的旧菜单数据,注意,只复制menu下的代码。然后修改你需要修改的菜单链接,名称,数据

    URL

     http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
    
    https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
    

    参数

    参数就是你修改的最终菜单,提个细节,微信菜单的链接静默授权,可以是微信外部链接

    {
        "button":[
            {
                "name":"理赔",
                "sub_button":[
                    {
                        "type":"A",
                        "name":"B",
                        "url":"C",
                        "sub_button":[
    
                        ],
                        "appid":"D",
                        "pagepath":"E"
                    }
                ]
            }
        ]
    }
    

    返回

    {
        "errcode": 0,
        "errmsg": "ok"
    }
    

    检查

    新增完毕后,菜单点一点,确定功能实现

    展开全文
  • 使用JAVA后端去自定义创建菜单微信公众号开发文档中提供了API: https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1421141013,请大家认真的观看文档的中的信息, 创建菜单中有一些要注意的地方: ...
  • 微信公众号开发(五)个性化菜单

    万次阅读 2017-09-07 00:16:41
    微信公众号开发(五)个性化菜单 个性化菜单让公众号的不同用户群体看到不一样的自定义菜单。该接口开放给已认证订阅号和已认证服务号,个性化菜单要求用户的微信客户端版本在iPhone6.2.2,Android 6.2.4以上,...
  • 今天接到一个小任务,要求利用接口来设置不同用户访问微信公众号时显示不同的菜单栏任务,对用户划分人群。第一次接手这样的任务,于是就在网上一顿乱搜,结果搞了半天,浪费了一上午的时间,始终报如下错误: 1 2 3...
  • 创建自定义菜单,实现菜单事件。 首先获取Access_Token 接口: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET 我用的是测试号,修改APPID和APPSECRET,然后...
  • 微信公众号之自定义菜单

    千次阅读 2015-02-17 01:00:36
    今天是“微信开发会客厅”栏目的第一期,我的微信自媒体“刘琪的商业观察”有幸请到了几位自定义菜单的“尝鲜者”,请他们谈谈对。   “订酒店”公众号负责人、快捷酒店管家产品经理朱坤的看法比较具有典型性...
  • TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公众号开发脚手架,支持任何 Node.js 的服务端框架(Express、Nest、egg 等) 接口权限 公众号接口权限说明 菜单规则以及按钮类型说明 实现自定义菜单有...
  • 微信公众号自定义菜单打开小程序(接口修改菜单) 1、前置基础知识 通过接口配置微信公众号菜单-点击进入 2、菜单json示例 2、打卡小程序的菜单类型 java类:MiniprogramButton.java public class ...
  • 微信公众号,仿照企业号的思路,增加了标签管理的功能,对关注的粉丝可以设置标签管理,实现更加方便的分组管理功能。开发者可以使用用户标签管理的相关接口,实现对公众号的标签进行创建、查询、修改、删除等操作,...
  • 微信公众号开发之自定义菜单

    万次阅读 2017-03-11 12:29:32
    微信开发交流群:148540125系列文章参考地址 极速开发微信公众号欢迎留言、转发 项目源码参考地址 点我点我–欢迎Start 前几篇文章已讲完如何导入项目,如何启动配置项目,如何成为开发者,重源码分析消息是如何...
  • 小程序菜单根本就是一段JSON,但是由于制作时不能所见即所得,先要看到效果就需要上传到公众号,调试很麻烦,特别是涉及到个性化菜单的时候,更是麻烦。所以就需要这款所见即所得的公众号菜单管理工具。以下简称“小...
  • 微信公众号

    万次阅读 2019-10-26 10:40:14
    如何去完成微信公众号的开发?
  • 回顾之前的微信公众号配置和消息处理的内容,我们已经掌握了如何配置服务器与微信公众号建立连接,也掌握了通过消息管理的方式,对用户的信息进行处理,完成公众号消息回复功能,实现公众号与用户之间的完整对话。...
  • TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公众号开发脚手架,支持任何 Node.js 的服务端框架(Express、Nest、egg 等) 接口权限 公众号接口权限说明 菜单规则以及按钮类型说明 实现自定义菜单有两种方式 ...
  • 1.微信公众平台新增了个性化菜单接口,开发者可以通过该接口,让公众号的不同用户群体看到不一样的自定义菜单。该接口开放给已认证订阅号和已认证服务号。出于安全考虑,一个公众号的所有个性化菜单,最多只能设置为...
  • 微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息...
  • 微信公众号开发 (3) 菜单处理

    千次阅读 2020-01-17 19:26:14
    微信公众号开发 (1) 微信接入认证成为开发者 微信公众号开发 (2) 消息处理 本文将实现 获取access_token 自定义菜单 微信文档中提示的一些注意点: 自定义菜单最多3个一级菜单,每一级菜单最多5个二级菜单。 一...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,526
精华内容 610
关键字:

微信公众号个性化菜单