MenuApi.java

  1. package com.foxinmy.weixin4j.mp.api;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. import com.alibaba.fastjson.JSON;
  5. import com.alibaba.fastjson.JSONArray;
  6. import com.alibaba.fastjson.JSONObject;
  7. import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
  8. import com.alibaba.fastjson.parser.deserializer.ParseProcess;
  9. import com.alibaba.fastjson.serializer.NameFilter;
  10. import com.foxinmy.weixin4j.exception.WeixinException;
  11. import com.foxinmy.weixin4j.http.weixin.ApiResult;
  12. import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
  13. import com.foxinmy.weixin4j.model.Button;
  14. import com.foxinmy.weixin4j.model.Token;
  15. import com.foxinmy.weixin4j.mp.model.Menu;
  16. import com.foxinmy.weixin4j.mp.model.MenuMatchRule;
  17. import com.foxinmy.weixin4j.token.TokenManager;
  18. import com.foxinmy.weixin4j.type.ButtonType;
  19. import com.foxinmy.weixin4j.util.StringUtil;

  20. /**
  21.  * 菜单相关API
  22.  *
  23.  * @className MenuApi
  24.  * @author jinyu(foxinmy@gmail.com)
  25.  * @date 2014年9月25日
  26.  * @since JDK 1.6
  27.  */
  28. public class MenuApi extends MpApi {

  29.     private final TokenManager tokenManager;

  30.     public MenuApi(TokenManager tokenManager) {
  31.         this.tokenManager = tokenManager;
  32.     }

  33.     /**
  34.      * 自定义菜单
  35.      *
  36.      * @param buttons
  37.      *            菜单列表
  38.      * @throws WeixinException
  39.      * @see <a href=
  40.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN">
  41.      *      创建自定义菜单</a>
  42.      * @see com.foxinmy.weixin4j.model.Button
  43.      * @return 处理结果
  44.      */
  45.     public ApiResult createMenu(List<Button> buttons) throws WeixinException {
  46.         String menu_create_uri = getRequestUri("menu_create_uri");
  47.         JSONObject obj = new JSONObject();
  48.         obj.put("button", buttons);
  49.         return createMenu0(menu_create_uri, obj).getAsResult();
  50.     }

  51.     private WeixinResponse createMenu0(String url, JSONObject data) throws WeixinException {
  52.         return weixinExecutor.post(String.format(url, tokenManager.getAccessToken()),
  53.                 JSON.toJSONString(data, new NameFilter() {
  54.                     @Override
  55.                     public String process(Object object, String name, Object value) {
  56.                         if (object instanceof Button && name.equals("content")
  57.                                 && StringUtil.isNotBlank(((Button) object).getType())) {
  58.                             ButtonType buttonType = ButtonType.valueOf(((Button) object).getType());
  59.                             if (ButtonType.view == buttonType || ButtonType.miniprogram == buttonType) {
  60.                                 return "url";
  61.                             } else if (ButtonType.media_id == buttonType || ButtonType.view_limited == buttonType) {
  62.                                 return "media_id";
  63.                             } else {
  64.                                 return "key";
  65.                             }
  66.                         }
  67.                         return name;
  68.                     }
  69.                 }));

  70.     }

  71.     /**
  72.      * 查询菜单
  73.      *
  74.      * @throws WeixinException
  75.      * @see <a href=
  76.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN">
  77.      *      查询菜单</a>
  78.      * @see com.foxinmy.weixin4j.model.Button
  79.      * @return 菜单集合
  80.      */
  81.     public List<Button> getMenu() throws WeixinException {
  82.         return buttonsConvertor(getMenu0().getJSONObject("menu"));
  83.     }

  84.     private JSONObject getMenu0() throws WeixinException {
  85.         String menu_get_uri = getRequestUri("menu_get_uri");
  86.         Token token = tokenManager.getCache();
  87.         WeixinResponse response = weixinExecutor.get(String.format(menu_get_uri, token.getAccessToken()));
  88.         return response.getAsJson();
  89.     }

  90.     /**
  91.      * 查询全部菜单(包含个性化菜单)
  92.      *
  93.      * @throws WeixinException
  94.      * @see <a href=
  95.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN">
  96.      *      普通菜单</a>
  97.      * @see <a href=
  98.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
  99.      *      个性化菜单</a>
  100.      * @see com.foxinmy.weixin4j.model.Button
  101.      * @see com.foxinmy.weixin4j.mp.model.Menu
  102.      * @return 菜单集合
  103.      */
  104.     public List<Menu> getAllMenu() throws WeixinException {
  105.         JSONObject response = getMenu0();
  106.         List<Menu> menus = new ArrayList<Menu>();
  107.         // 普通菜单
  108.         JSONObject menuObj = response.getJSONObject("menu");
  109.         menus.add(new Menu(menuObj.getString("menuid"), buttonsConvertor(menuObj), null));
  110.         // 个性化菜单
  111.         JSONArray menuObjs = response.getJSONArray("conditionalmenu");
  112.         if (menuObjs != null && !menuObjs.isEmpty()) {
  113.             for (int i = 0; i < menuObjs.size(); i++) {
  114.                 menuObj = menuObjs.getJSONObject(i);
  115.                 menus.add(new Menu(menuObj.getString("menuid"), buttonsConvertor(menuObj),
  116.                         menuObj.getObject("matchrule", MenuMatchRule.class)));
  117.             }
  118.         }
  119.         return menus;
  120.     }

  121.     /**
  122.      * 删除菜单
  123.      *
  124.      * @return 处理结果
  125.      * @throws WeixinException
  126.      * @see <a href=
  127.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN">
  128.      *      删除菜单</a>
  129.      * @return 处理结果
  130.      */
  131.     public ApiResult deleteMenu() throws WeixinException {
  132.         String menu_delete_uri = getRequestUri("menu_delete_uri");
  133.         Token token = tokenManager.getCache();
  134.         WeixinResponse response = weixinExecutor.get(String.format(menu_delete_uri, token.getAccessToken()));

  135.         return response.getAsResult();
  136.     }

  137.     /**
  138.      * 创建个性化菜单
  139.      *
  140.      * @param buttons
  141.      *            菜单列表
  142.      * @param matchRule
  143.      *            匹配规则 至少要有一个匹配信息是不为空
  144.      * @throws WeixinException
  145.      * @see <a href=
  146.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
  147.      *      创建个性化菜单</a>
  148.      * @see com.foxinmy.weixin4j.model.Button
  149.      * @return 菜单ID
  150.      */
  151.     public String createCustomMenu(List<Button> buttons, MenuMatchRule matchRule) throws WeixinException {
  152.         String menu_create_uri = getRequestUri("menu_custom_create_uri");
  153.         JSONObject obj = new JSONObject();
  154.         obj.put("button", buttons);
  155.         obj.put("matchrule", matchRule.getRule());
  156.         return createMenu0(menu_create_uri, obj).getAsJson().getString("menuid");
  157.     }

  158.     /**
  159.      * 删除个性化菜单
  160.      *
  161.      * @throws WeixinException
  162.      * @see <a href=
  163.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
  164.      *      删除个性化菜单</a>
  165.      * @return 处理结果
  166.      */
  167.     public ApiResult deleteCustomMenu(String menuId) throws WeixinException {
  168.         String menu_delete_uri = getRequestUri("menu_delete_custom_uri");
  169.         Token token = tokenManager.getCache();
  170.         JSONObject obj = new JSONObject();
  171.         obj.put("menuid", menuId);
  172.         WeixinResponse response = weixinExecutor.post(String.format(menu_delete_uri, token.getAccessToken()),
  173.                 obj.toJSONString());

  174.         return response.getAsResult();
  175.     }

  176.     /**
  177.      * 测试个性化菜单匹配结果
  178.      *
  179.      * @param userId
  180.      *            可以是粉丝的OpenID,也可以是粉丝的微信号。
  181.      * @return 匹配到的菜单配置
  182.      * @see <a href=
  183.      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
  184.      *      测试个性化菜单</a>
  185.      * @see com.foxinmy.weixin4j.model.Button
  186.      * @throws WeixinException
  187.      */
  188.     public List<Button> matchCustomMenu(String userId) throws WeixinException {
  189.         String menu_trymatch_uri = getRequestUri("menu_trymatch_uri");
  190.         Token token = tokenManager.getCache();
  191.         JSONObject obj = new JSONObject();
  192.         obj.put("user_id", userId);
  193.         WeixinResponse response = weixinExecutor.post(String.format(menu_trymatch_uri, token.getAccessToken()),
  194.                 obj.toJSONString());

  195.         return buttonsConvertor(response.getAsJson().getJSONObject("menu"));
  196.     }

  197.     private final ParseProcess buttonProcess = new ExtraProcessor() {
  198.         @Override
  199.         public void processExtra(Object object, String key, Object value) {
  200.             ((Button) object).setContent(String.valueOf(value));
  201.         }
  202.     };

  203.     private List<Button> buttonsConvertor(JSONObject menu) {
  204.         JSONArray buttons = menu.getJSONArray("button");
  205.         List<Button> buttonList = new ArrayList<Button>(buttons.size());
  206.         for (int i = 0; i < buttons.size(); i++) {
  207.             buttonList.add(JSON.parseObject(buttons.getString(i), Button.class, buttonProcess));
  208.         }
  209.         return buttonList;
  210.     }
  211. }