View Javadoc
1   package com.foxinmy.weixin4j.mp.api;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import com.alibaba.fastjson.JSON;
7   import com.alibaba.fastjson.JSONArray;
8   import com.alibaba.fastjson.JSONObject;
9   import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
10  import com.alibaba.fastjson.parser.deserializer.ParseProcess;
11  import com.alibaba.fastjson.serializer.NameFilter;
12  import com.foxinmy.weixin4j.exception.WeixinException;
13  import com.foxinmy.weixin4j.http.weixin.ApiResult;
14  import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
15  import com.foxinmy.weixin4j.model.Button;
16  import com.foxinmy.weixin4j.model.Token;
17  import com.foxinmy.weixin4j.mp.model.Menu;
18  import com.foxinmy.weixin4j.mp.model.MenuMatchRule;
19  import com.foxinmy.weixin4j.token.TokenManager;
20  import com.foxinmy.weixin4j.type.ButtonType;
21  import com.foxinmy.weixin4j.util.StringUtil;
22  
23  /**
24   * 菜单相关API
25   *
26   * @className MenuApi
27   * @author jinyu(foxinmy@gmail.com)
28   * @date 2014年9月25日
29   * @since JDK 1.6
30   */
31  public class MenuApi extends MpApi {
32  
33      private final TokenManager tokenManager;
34  
35      public MenuApi(TokenManager tokenManager) {
36          this.tokenManager = tokenManager;
37      }
38  
39      /**
40       * 自定义菜单
41       *
42       * @param buttons
43       *            菜单列表
44       * @throws WeixinException
45       * @see <a href=
46       *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013&token=&lang=zh_CN">
47       *      创建自定义菜单</a>
48       * @see com.foxinmy.weixin4j.model.Button
49       * @return 处理结果
50       */
51      public ApiResult createMenu(List<Button> buttons) throws WeixinException {
52          String menu_create_uri = getRequestUri("menu_create_uri");
53          JSONObject obj = new JSONObject();
54          obj.put("button", buttons);
55          return createMenu0(menu_create_uri, obj).getAsResult();
56      }
57  
58      private WeixinResponse createMenu0(String url, JSONObject data) throws WeixinException {
59          return weixinExecutor.post(String.format(url, tokenManager.getAccessToken()),
60                  JSON.toJSONString(data, new NameFilter() {
61                      @Override
62                      public String process(Object object, String name, Object value) {
63                          if (object instanceof Button && name.equals("content")
64                                  && StringUtil.isNotBlank(((Button) object).getType())) {
65                              ButtonType buttonType = ButtonType.valueOf(((Button) object).getType());
66                              if (ButtonType.view == buttonType || ButtonType.miniprogram == buttonType) {
67                                  return "url";
68                              } else if (ButtonType.media_id == buttonType || ButtonType.view_limited == buttonType) {
69                                  return "media_id";
70                              } else {
71                                  return "key";
72                              }
73                          }
74                          return name;
75                      }
76                  }));
77  
78      }
79  
80      /**
81       * 查询菜单
82       *
83       * @throws WeixinException
84       * @see <a href=
85       *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN">
86       *      查询菜单</a>
87       * @see com.foxinmy.weixin4j.model.Button
88       * @return 菜单集合
89       */
90      public List<Button> getMenu() throws WeixinException {
91          return buttonsConvertor(getMenu0().getJSONObject("menu"));
92      }
93  
94      private JSONObject getMenu0() throws WeixinException {
95          String menu_get_uri = getRequestUri("menu_get_uri");
96          Token token = tokenManager.getCache();
97          WeixinResponse response = weixinExecutor.get(String.format(menu_get_uri, token.getAccessToken()));
98          return response.getAsJson();
99      }
100 
101     /**
102      * 查询全部菜单(包含个性化菜单)
103      *
104      * @throws WeixinException
105      * @see <a href=
106      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014&token=&lang=zh_CN">
107      *      普通菜单</a>
108      * @see <a href=
109      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
110      *      个性化菜单</a>
111      * @see com.foxinmy.weixin4j.model.Button
112      * @see com.foxinmy.weixin4j.mp.model.Menu
113      * @return 菜单集合
114      */
115     public List<Menu> getAllMenu() throws WeixinException {
116         JSONObject response = getMenu0();
117         List<Menu> menus = new ArrayList<Menu>();
118         // 普通菜单
119         JSONObject menuObj = response.getJSONObject("menu");
120         menus.add(new Menu(menuObj.getString("menuid"), buttonsConvertor(menuObj), null));
121         // 个性化菜单
122         JSONArray menuObjs = response.getJSONArray("conditionalmenu");
123         if (menuObjs != null && !menuObjs.isEmpty()) {
124             for (int i = 0; i < menuObjs.size(); i++) {
125                 menuObj = menuObjs.getJSONObject(i);
126                 menus.add(new Menu(menuObj.getString("menuid"), buttonsConvertor(menuObj),
127                         menuObj.getObject("matchrule", MenuMatchRule.class)));
128             }
129         }
130         return menus;
131     }
132 
133     /**
134      * 删除菜单
135      *
136      * @return 处理结果
137      * @throws WeixinException
138      * @see <a href=
139      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015&token=&lang=zh_CN">
140      *      删除菜单</a>
141      * @return 处理结果
142      */
143     public ApiResult deleteMenu() throws WeixinException {
144         String menu_delete_uri = getRequestUri("menu_delete_uri");
145         Token token = tokenManager.getCache();
146         WeixinResponse response = weixinExecutor.get(String.format(menu_delete_uri, token.getAccessToken()));
147 
148         return response.getAsResult();
149     }
150 
151     /**
152      * 创建个性化菜单
153      *
154      * @param buttons
155      *            菜单列表
156      * @param matchRule
157      *            匹配规则 至少要有一个匹配信息是不为空
158      * @throws WeixinException
159      * @see <a href=
160      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
161      *      创建个性化菜单</a>
162      * @see com.foxinmy.weixin4j.model.Button
163      * @return 菜单ID
164      */
165     public String createCustomMenu(List<Button> buttons, MenuMatchRule matchRule) throws WeixinException {
166         String menu_create_uri = getRequestUri("menu_custom_create_uri");
167         JSONObject obj = new JSONObject();
168         obj.put("button", buttons);
169         obj.put("matchrule", matchRule.getRule());
170         return createMenu0(menu_create_uri, obj).getAsJson().getString("menuid");
171     }
172 
173     /**
174      * 删除个性化菜单
175      *
176      * @throws WeixinException
177      * @see <a href=
178      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
179      *      删除个性化菜单</a>
180      * @return 处理结果
181      */
182     public ApiResult deleteCustomMenu(String menuId) throws WeixinException {
183         String menu_delete_uri = getRequestUri("menu_delete_custom_uri");
184         Token token = tokenManager.getCache();
185         JSONObject obj = new JSONObject();
186         obj.put("menuid", menuId);
187         WeixinResponse response = weixinExecutor.post(String.format(menu_delete_uri, token.getAccessToken()),
188                 obj.toJSONString());
189 
190         return response.getAsResult();
191     }
192 
193     /**
194      * 测试个性化菜单匹配结果
195      *
196      * @param userId
197      *            可以是粉丝的OpenID,也可以是粉丝的微信号。
198      * @return 匹配到的菜单配置
199      * @see <a href=
200      *      "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455782296&token=&lang=zh_CN">
201      *      测试个性化菜单</a>
202      * @see com.foxinmy.weixin4j.model.Button
203      * @throws WeixinException
204      */
205     public List<Button> matchCustomMenu(String userId) throws WeixinException {
206         String menu_trymatch_uri = getRequestUri("menu_trymatch_uri");
207         Token token = tokenManager.getCache();
208         JSONObject obj = new JSONObject();
209         obj.put("user_id", userId);
210         WeixinResponse response = weixinExecutor.post(String.format(menu_trymatch_uri, token.getAccessToken()),
211                 obj.toJSONString());
212 
213         return buttonsConvertor(response.getAsJson().getJSONObject("menu"));
214     }
215 
216     private final ParseProcess buttonProcess = new ExtraProcessor() {
217         @Override
218         public void processExtra(Object object, String key, Object value) {
219             ((Button) object).setContent(String.valueOf(value));
220         }
221     };
222 
223     private List<Button> buttonsConvertor(JSONObject menu) {
224         JSONArray buttons = menu.getJSONArray("button");
225         List<Button> buttonList = new ArrayList<Button>(buttons.size());
226         for (int i = 0; i < buttons.size(); i++) {
227             buttonList.add(JSON.parseObject(buttons.getString(i), Button.class, buttonProcess));
228         }
229         return buttonList;
230     }
231 }