weixin4j-mp:新增个性化菜单接口
This commit is contained in:
parent
9afa3b06ba
commit
f83c6b600d
@ -547,3 +547,7 @@
|
|||||||
* 2015-12-15
|
* 2015-12-15
|
||||||
|
|
||||||
+ weixin4j-[mp|qy]:version upgrade to 1.6.5
|
+ weixin4j-[mp|qy]:version upgrade to 1.6.5
|
||||||
|
|
||||||
|
* 2015-12-18
|
||||||
|
|
||||||
|
+ weixin4j-mp:新增个性化菜单接口
|
||||||
|
|||||||
@ -5,7 +5,7 @@ weixin4j
|
|||||||
-------------
|
-------------
|
||||||
> `weixin4j`是一个用java编写针对微信开发的工具包,包含[weixin4j-mp](./weixin4j-mp)(微信公众平台API)、[weixin4j-qy](./weixin4j-qy)(微信企业号API)以及[weixin4j-server](./weixin4j-server)(微信回调消息服务器)三个工程.
|
> `weixin4j`是一个用java编写针对微信开发的工具包,包含[weixin4j-mp](./weixin4j-mp)(微信公众平台API)、[weixin4j-qy](./weixin4j-qy)(微信企业号API)以及[weixin4j-server](./weixin4j-server)(微信回调消息服务器)三个工程.
|
||||||
|
|
||||||
功能列表
|
模块说明
|
||||||
-------
|
-------
|
||||||
* **weixin4j-base**
|
* **weixin4j-base**
|
||||||
|
|
||||||
|
|||||||
@ -179,3 +179,7 @@
|
|||||||
* 2015-12-15
|
* 2015-12-15
|
||||||
|
|
||||||
+ version upgrade to 1.6.5
|
+ version upgrade to 1.6.5
|
||||||
|
|
||||||
|
* 2015-12-18
|
||||||
|
|
||||||
|
+ 新增个性化菜单接口
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import com.foxinmy.weixin4j.mp.model.Following;
|
|||||||
import com.foxinmy.weixin4j.mp.model.Group;
|
import com.foxinmy.weixin4j.mp.model.Group;
|
||||||
import com.foxinmy.weixin4j.mp.model.KfAccount;
|
import com.foxinmy.weixin4j.mp.model.KfAccount;
|
||||||
import com.foxinmy.weixin4j.mp.model.KfSession;
|
import com.foxinmy.weixin4j.mp.model.KfSession;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.Menu;
|
||||||
import com.foxinmy.weixin4j.mp.model.MenuSetting;
|
import com.foxinmy.weixin4j.mp.model.MenuSetting;
|
||||||
import com.foxinmy.weixin4j.mp.model.QRParameter;
|
import com.foxinmy.weixin4j.mp.model.QRParameter;
|
||||||
import com.foxinmy.weixin4j.mp.model.QRResult;
|
import com.foxinmy.weixin4j.mp.model.QRResult;
|
||||||
@ -1084,7 +1085,7 @@ public class WeixinProxy {
|
|||||||
/**
|
/**
|
||||||
* 自定义菜单
|
* 自定义菜单
|
||||||
*
|
*
|
||||||
* @param btnList
|
* @param buttons
|
||||||
* 菜单列表
|
* 菜单列表
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
* @see <a
|
* @see <a
|
||||||
@ -1093,8 +1094,8 @@ public class WeixinProxy {
|
|||||||
* @see com.foxinmy.weixin4j.type.ButtonType
|
* @see com.foxinmy.weixin4j.type.ButtonType
|
||||||
* @see com.foxinmy.weixin4j.mp.api.MenuApi
|
* @see com.foxinmy.weixin4j.mp.api.MenuApi
|
||||||
*/
|
*/
|
||||||
public JsonResult createMenu(List<Button> btnList) throws WeixinException {
|
public JsonResult createMenu(List<Button> buttons) throws WeixinException {
|
||||||
return menuApi.createMenu(btnList);
|
return menuApi.createMenu(buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1111,19 +1112,64 @@ public class WeixinProxy {
|
|||||||
return menuApi.getMenu();
|
return menuApi.getMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询全部菜单(包含个性化菜单)
|
||||||
|
*
|
||||||
|
* @return 菜单集合
|
||||||
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html">查询菜单</a>
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html">个性化菜单</a>
|
||||||
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
|
* @see com.foxinmy.weixin4j.mp.model.Menu
|
||||||
|
* @see com.foxinmy.weixin4j.mp.api.MenuApi
|
||||||
|
*/
|
||||||
|
public List<Menu> getAllMenu() throws WeixinException {
|
||||||
|
return menuApi.getAllMenu();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除菜单
|
* 删除菜单
|
||||||
*
|
*
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
* @see <a
|
* @see <a
|
||||||
* href="http://mp.weixin.qq.com/wiki/16/8ed41ba931e4845844ad6d1eeb8060c8.html">删除菜单</a>
|
* href="http://mp.weixin.qq.com/wiki/16/8ed41ba931e4845844ad6d1eeb8060c8.html">删除菜单</a>
|
||||||
* @see com.foxinmy.weixin4j.model.Button
|
|
||||||
* @see com.foxinmy.weixin4j.mp.api.MenuApi
|
* @see com.foxinmy.weixin4j.mp.api.MenuApi
|
||||||
*/
|
*/
|
||||||
public JsonResult deleteMenu() throws WeixinException {
|
public JsonResult deleteMenu() throws WeixinException {
|
||||||
return menuApi.deleteMenu();
|
return menuApi.deleteMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除个性化菜单
|
||||||
|
*
|
||||||
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html#.E5.88.A0.E9.99.A4.E4.B8.AA.E6.80.A7.E5.8C.96.E8.8F.9C.E5.8D.95">删除个性化菜单</a>
|
||||||
|
* @see com.foxinmy.weixin4j.mp.api.MenuApi
|
||||||
|
* @return 处理结果
|
||||||
|
*/
|
||||||
|
public JsonResult deleteCustomMenu(String menuId) throws WeixinException {
|
||||||
|
return menuApi.deleteCustomMenu(menuId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试个性化菜单匹配结果
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* 可以是粉丝的OpenID,也可以是粉丝的微信号。
|
||||||
|
* @return 匹配到的菜单配置
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html#.E6.B5.8B.E8.AF.95.E4.B8.AA.E6.80.A7.E5.8C.96.E8.8F.9C.E5.8D.95.E5.8C.B9.E9.85.8D.E7.BB.93.E6.9E.9C">测试个性化菜单</a>
|
||||||
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
|
* @see com.foxinmy.weixin4j.mp.api.MenuApi
|
||||||
|
* @throws WeixinException
|
||||||
|
*/
|
||||||
|
public List<Button> matchCustomMenu(String userId) throws WeixinException {
|
||||||
|
return menuApi.matchCustomMenu(userId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成带参数的二维码
|
* 生成带参数的二维码
|
||||||
*
|
*
|
||||||
|
|||||||
@ -15,6 +15,8 @@ import com.foxinmy.weixin4j.http.weixin.JsonResult;
|
|||||||
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||||
import com.foxinmy.weixin4j.model.Button;
|
import com.foxinmy.weixin4j.model.Button;
|
||||||
import com.foxinmy.weixin4j.model.Token;
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.Menu;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.MenuMatchRule;
|
||||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||||
import com.foxinmy.weixin4j.type.ButtonType;
|
import com.foxinmy.weixin4j.type.ButtonType;
|
||||||
|
|
||||||
@ -26,6 +28,7 @@ import com.foxinmy.weixin4j.type.ButtonType;
|
|||||||
* @date 2014年9月25日
|
* @date 2014年9月25日
|
||||||
* @since JDK 1.6
|
* @since JDK 1.6
|
||||||
* @see com.foxinmy.weixin4j.model.Button
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
|
* @see http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
|
||||||
*/
|
*/
|
||||||
public class MenuApi extends MpApi {
|
public class MenuApi extends MpApi {
|
||||||
|
|
||||||
@ -38,21 +41,25 @@ public class MenuApi extends MpApi {
|
|||||||
/**
|
/**
|
||||||
* 自定义菜单
|
* 自定义菜单
|
||||||
*
|
*
|
||||||
* @param btnList
|
* @param buttons
|
||||||
* 菜单列表
|
* 菜单列表
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
* @see <a
|
* @see <a
|
||||||
* href="http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html">创建自定义菜单</a>
|
* href="http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html">创建自定义菜单</a>
|
||||||
* @see com.foxinmy.weixin4j.model.Button
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
*/
|
*/
|
||||||
public JsonResult createMenu(List<Button> btnList) throws WeixinException {
|
public JsonResult createMenu(List<Button> buttons) throws WeixinException {
|
||||||
String menu_create_uri = getRequestUri("menu_create_uri");
|
String menu_create_uri = getRequestUri("menu_create_uri");
|
||||||
Token token = tokenHolder.getToken();
|
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("button", btnList);
|
obj.put("button", buttons);
|
||||||
|
return createMenu0(menu_create_uri, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonResult createMenu0(String url, JSONObject data)
|
||||||
|
throws WeixinException {
|
||||||
WeixinResponse response = weixinExecutor.post(
|
WeixinResponse response = weixinExecutor.post(
|
||||||
String.format(menu_create_uri, token.getAccessToken()),
|
String.format(url, tokenHolder.getAccessToken()),
|
||||||
JSON.toJSONString(obj, new NameFilter() {
|
JSON.toJSONString(data, new NameFilter() {
|
||||||
@Override
|
@Override
|
||||||
public String process(Object object, String name,
|
public String process(Object object, String name,
|
||||||
Object value) {
|
Object value) {
|
||||||
@ -86,25 +93,47 @@ public class MenuApi extends MpApi {
|
|||||||
* @see com.foxinmy.weixin4j.model.Button
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
*/
|
*/
|
||||||
public List<Button> getMenu() throws WeixinException {
|
public List<Button> getMenu() throws WeixinException {
|
||||||
|
return buttonsConvertor(getMenu0().getJSONObject("menu"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONObject getMenu0() throws WeixinException {
|
||||||
String menu_get_uri = getRequestUri("menu_get_uri");
|
String menu_get_uri = getRequestUri("menu_get_uri");
|
||||||
Token token = tokenHolder.getToken();
|
Token token = tokenHolder.getToken();
|
||||||
WeixinResponse response = weixinExecutor.get(String.format(
|
WeixinResponse response = weixinExecutor.get(String.format(
|
||||||
menu_get_uri, token.getAccessToken()));
|
menu_get_uri, token.getAccessToken()));
|
||||||
|
return response.getAsJson();
|
||||||
|
}
|
||||||
|
|
||||||
JSONArray buttons = response.getAsJson().getJSONObject("menu")
|
/**
|
||||||
.getJSONArray("button");
|
* 查询全部菜单(包含个性化菜单)
|
||||||
List<Button> buttonList = new ArrayList<Button>(buttons.size());
|
*
|
||||||
ParseProcess processor = new ExtraProcessor() {
|
* @return 菜单集合
|
||||||
@Override
|
* @throws WeixinException
|
||||||
public void processExtra(Object object, String key, Object value) {
|
* @see <a
|
||||||
JSONPath.set(object, "$.content", value);
|
* href="http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html">查询菜单</a>
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html">个性化菜单</a>
|
||||||
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
|
* @see com.foxinmy.weixin4j.mp.model.Menu
|
||||||
|
*/
|
||||||
|
public List<Menu> getAllMenu() throws WeixinException {
|
||||||
|
JSONObject response = getMenu0();
|
||||||
|
List<Menu> menus = new ArrayList<Menu>();
|
||||||
|
// 普通菜单
|
||||||
|
JSONObject menuObj = response.getJSONObject("menu");
|
||||||
|
menus.add(new Menu(menuObj.getString("menuid"),
|
||||||
|
buttonsConvertor(menuObj), null));
|
||||||
|
// 个性化菜单
|
||||||
|
JSONArray menuObjs = response.getJSONArray("conditionalmenu");
|
||||||
|
if (menuObjs != null && !menuObjs.isEmpty()) {
|
||||||
|
for (int i = 0; i < menuObjs.size(); i++) {
|
||||||
|
menuObj = menuObjs.getJSONObject(i);
|
||||||
|
menus.add(new Menu(menuObj.getString("menuid"),
|
||||||
|
buttonsConvertor(menuObj),
|
||||||
|
menuObj.getObject("matchrule", MenuMatchRule.class)));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
for (int i = 0; i < buttons.size(); i++) {
|
|
||||||
buttonList.add(JSON.parseObject(buttons.getString(i), Button.class,
|
|
||||||
processor));
|
|
||||||
}
|
}
|
||||||
return buttonList;
|
return menus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,4 +152,85 @@ public class MenuApi extends MpApi {
|
|||||||
|
|
||||||
return response.getAsJsonResult();
|
return response.getAsJsonResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建个性化菜单
|
||||||
|
*
|
||||||
|
* @param buttons
|
||||||
|
* 菜单列表
|
||||||
|
* @param matchRule
|
||||||
|
* 匹配规则 至少要有一个匹配信息是不为空
|
||||||
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html#.E5.88.9B.E5.BB.BA.E4.B8.AA.E6.80.A7.E5.8C.96.E8.8F.9C.E5.8D.95">创建个性化菜单</a>
|
||||||
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
|
*/
|
||||||
|
public JsonResult createCustomMenu(List<Button> buttons,
|
||||||
|
MenuMatchRule matchRule) throws WeixinException {
|
||||||
|
String menu_create_uri = getRequestUri("menu_custom_create_uri");
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
obj.put("button", buttons);
|
||||||
|
obj.put("matchrule", matchRule.getRule());
|
||||||
|
return createMenu0(menu_create_uri, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除个性化菜单
|
||||||
|
*
|
||||||
|
* @throws WeixinException
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html#.E5.88.A0.E9.99.A4.E4.B8.AA.E6.80.A7.E5.8C.96.E8.8F.9C.E5.8D.95">删除个性化菜单</a>
|
||||||
|
* @return 处理结果
|
||||||
|
*/
|
||||||
|
public JsonResult deleteCustomMenu(String menuId) throws WeixinException {
|
||||||
|
String menu_delete_uri = getRequestUri("menu_delete_custom_uri");
|
||||||
|
Token token = tokenHolder.getToken();
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
obj.put("menuid", menuId);
|
||||||
|
WeixinResponse response = weixinExecutor.post(
|
||||||
|
String.format(menu_delete_uri, token.getAccessToken()),
|
||||||
|
obj.toJSONString());
|
||||||
|
|
||||||
|
return response.getAsJsonResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试个性化菜单匹配结果
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* 可以是粉丝的OpenID,也可以是粉丝的微信号。
|
||||||
|
* @return 匹配到的菜单配置
|
||||||
|
* @see <a
|
||||||
|
* href="http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html#.E6.B5.8B.E8.AF.95.E4.B8.AA.E6.80.A7.E5.8C.96.E8.8F.9C.E5.8D.95.E5.8C.B9.E9.85.8D.E7.BB.93.E6.9E.9C">测试个性化菜单</a>
|
||||||
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
|
* @throws WeixinException
|
||||||
|
*/
|
||||||
|
public List<Button> matchCustomMenu(String userId) throws WeixinException {
|
||||||
|
String menu_trymatch_uri = getRequestUri("menu_trymatch_uri");
|
||||||
|
Token token = tokenHolder.getToken();
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
obj.put("user_id", userId);
|
||||||
|
WeixinResponse response = weixinExecutor.post(
|
||||||
|
String.format(menu_trymatch_uri, token.getAccessToken()),
|
||||||
|
obj.toJSONString());
|
||||||
|
|
||||||
|
return buttonsConvertor(response.getAsJson().getJSONObject("menu"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ParseProcess buttonProcess = new ExtraProcessor() {
|
||||||
|
@Override
|
||||||
|
public void processExtra(Object object, String key, Object value) {
|
||||||
|
JSONPath.set(object, "$.content", value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private List<Button> buttonsConvertor(JSONObject menu) {
|
||||||
|
JSONArray buttons = menu.getJSONArray("button");
|
||||||
|
List<Button> buttonList = new ArrayList<Button>(buttons.size());
|
||||||
|
for (int i = 0; i < buttons.size(); i++) {
|
||||||
|
buttonList.add(JSON.parseObject(buttons.getString(i), Button.class,
|
||||||
|
buttonProcess));
|
||||||
|
}
|
||||||
|
return buttonList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,12 +56,18 @@ group_delete_uri={api_cgi_url}/groups/delete?access_token=%s
|
|||||||
following_uri={api_cgi_url}/user/get?access_token=%s&next_openid=%s
|
following_uri={api_cgi_url}/user/get?access_token=%s&next_openid=%s
|
||||||
# \u81ea\u5b9a\u4e49\u83dc\u5355
|
# \u81ea\u5b9a\u4e49\u83dc\u5355
|
||||||
menu_create_uri={api_cgi_url}/menu/create?access_token=%s
|
menu_create_uri={api_cgi_url}/menu/create?access_token=%s
|
||||||
|
# \u521b\u5efa\u4e2a\u6027\u5316\u83dc\u5355
|
||||||
|
menu_custom_create_uri={api_cgi_url}/menu/addconditional?access_token=%s
|
||||||
# \u67e5\u8be2\u83dc\u5355
|
# \u67e5\u8be2\u83dc\u5355
|
||||||
menu_get_uri={api_cgi_url}/menu/get?access_token=%s
|
menu_get_uri={api_cgi_url}/menu/get?access_token=%s
|
||||||
# \u67e5\u8be2\u901a\u8fc7\u63a5\u53e3\u6216\u8005\u5728\u516c\u4f17\u5e73\u53f0\u4e0a\u8bbe\u7f6e\u7684\u83dc\u5355\u914d\u7f6e\u4fe1\u606f
|
# \u67e5\u8be2\u901a\u8fc7\u63a5\u53e3\u6216\u8005\u5728\u516c\u4f17\u5e73\u53f0\u4e0a\u8bbe\u7f6e\u7684\u83dc\u5355\u914d\u7f6e\u4fe1\u606f
|
||||||
menu_get_selfmenu_uri={api_cgi_url}/get_current_selfmenu_info?access_token=%s
|
menu_get_selfmenu_uri={api_cgi_url}/get_current_selfmenu_info?access_token=%s
|
||||||
# \u5220\u9664\u83dc\u5355
|
# \u5220\u9664\u83dc\u5355
|
||||||
menu_delete_uri={api_cgi_url}/menu/delete?access_token=%s
|
menu_delete_uri={api_cgi_url}/menu/delete?access_token=%s
|
||||||
|
# \u5220\u9664\u4e2a\u6027\u5316\u83dc\u5355
|
||||||
|
menu_delete_custom_uri={api_cgi_url}/menu/delconditional?access_token=%s
|
||||||
|
# \u6d4b\u8bd5\u4e2a\u6027\u5316\u83dc\u5355\u5339\u914d\u7ed3\u679c
|
||||||
|
menu_trymatch_uri={api_cgi_url}/menu/trymatch?access_token=%s
|
||||||
# \u4e0a\u4f20\u56fe\u6587
|
# \u4e0a\u4f20\u56fe\u6587
|
||||||
article_upload_uri={api_cgi_url}/media/uploadnews?access_token=%s
|
article_upload_uri={api_cgi_url}/media/uploadnews?access_token=%s
|
||||||
# \u4e0a\u4f20\u89c6\u9891
|
# \u4e0a\u4f20\u89c6\u9891
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.model.Button;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 底部菜单
|
||||||
|
*
|
||||||
|
* @className Menu
|
||||||
|
* @author jy
|
||||||
|
* @date 2015年12月18日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public class Menu implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -915139819768888593L;
|
||||||
|
|
||||||
|
private String menuId;
|
||||||
|
private List<Button> buttons;
|
||||||
|
private MenuMatchRule matchRule;
|
||||||
|
|
||||||
|
public Menu(String menuId, List<Button> buttons, MenuMatchRule matchRule) {
|
||||||
|
this.menuId = menuId;
|
||||||
|
this.buttons = buttons;
|
||||||
|
this.matchRule = matchRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMenuId() {
|
||||||
|
return menuId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Button> getButtons() {
|
||||||
|
return buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuMatchRule getMatchRule() {
|
||||||
|
return matchRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Menu [menuId=" + menuId + ", buttons=" + buttons
|
||||||
|
+ ", matchRule=" + matchRule + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.foxinmy.weixin4j.model.Gender;
|
||||||
|
import com.foxinmy.weixin4j.mp.type.ClientPlatformType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 个性化菜单匹配规则
|
||||||
|
*
|
||||||
|
* @className MenuMatchRule
|
||||||
|
* @author jy
|
||||||
|
* @date 2015年12月17日
|
||||||
|
* @since JDK 1.6
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public class MenuMatchRule implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 8115117407710728580L;
|
||||||
|
|
||||||
|
private JSONObject matchRule;
|
||||||
|
|
||||||
|
public MenuMatchRule() {
|
||||||
|
this.matchRule = new JSONObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户分组id,可通过用户分组管理接口获取
|
||||||
|
*/
|
||||||
|
private Integer groupId;
|
||||||
|
|
||||||
|
@JSONField(name = "group_id")
|
||||||
|
public MenuMatchRule group(int groupId) {
|
||||||
|
matchRule.put("group_id", groupId);
|
||||||
|
this.groupId = groupId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 性别
|
||||||
|
*/
|
||||||
|
private Gender gender;
|
||||||
|
|
||||||
|
@JSONField(name = "sex")
|
||||||
|
public void gender0(int sex) {
|
||||||
|
this.gender = Gender.values().length >= sex ? Gender.values()[sex - 1]
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuMatchRule gender(Gender gender) {
|
||||||
|
if (gender != null && gender != Gender.unknown) {
|
||||||
|
matchRule.put("sex", gender.ordinal() + 1);
|
||||||
|
}
|
||||||
|
this.gender = gender;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端版本
|
||||||
|
*/
|
||||||
|
private ClientPlatformType platformType;
|
||||||
|
|
||||||
|
@JSONField(name = "client_platform_type")
|
||||||
|
public void platform0(int platform) {
|
||||||
|
this.platformType = ClientPlatformType.values().length >= platform ? ClientPlatformType
|
||||||
|
.values()[platform - 1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuMatchRule platform(ClientPlatformType platformType) {
|
||||||
|
if (platformType != null) {
|
||||||
|
matchRule.put("client_platform_type", platformType.ordinal() + 1);
|
||||||
|
}
|
||||||
|
this.platformType = platformType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 国家信息,是用户在微信中设置的地区
|
||||||
|
* <p>
|
||||||
|
* country、province、city组成地区信息,将按照country、province、city的顺序进行验证
|
||||||
|
* ,要符合地区信息表的内容。地区信息从大到小验证,小的可以不填,即若填写了省份信息,则国家信息也必填并且匹配,城市信息可以不填。 例如 “中国
|
||||||
|
* 广东省 广州市”、“中国 广东省”都是合法的地域信息,而“中国 广州市”则不合法,因为填写了城市信息但没有填写省份信息
|
||||||
|
*
|
||||||
|
* @param country
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@JSONField(name = "country")
|
||||||
|
public MenuMatchRule country(String country) {
|
||||||
|
matchRule.put("country", country);
|
||||||
|
this.country = country;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String province;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 省份信息,是用户在微信中设置的地区
|
||||||
|
* <p>
|
||||||
|
* country、province、city组成地区信息,将按照country、province、city的顺序进行验证,要符合地区信息表的内容。
|
||||||
|
* 地区信息从大到小验证,小的可以不填,即若填写了省份信息,则国家信息也必填并且匹配,城市信息可以不填。 例如 “中国 广东省 广州市”、“中国
|
||||||
|
* 广东省”都是合法的地域信息,而“中国 广州市”则不合法,因为填写了城市信息但没有填写省份信息
|
||||||
|
*
|
||||||
|
* @param country
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@JSONField(name = "province")
|
||||||
|
public MenuMatchRule province(String province) {
|
||||||
|
matchRule.put("province", province);
|
||||||
|
this.province = province;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 城市信息,是用户在微信中设置的地区
|
||||||
|
* <p>
|
||||||
|
* country、province、city组成地区信息,将按照country、province、city的顺序进行验证,要符合地区信息表的内容。
|
||||||
|
* 地区信息从大到小验证,小的可以不填,即若填写了省份信息,则国家信息也必填并且匹配,城市信息可以不填。 例如 “中国 广东省 广州市”、“中国
|
||||||
|
* 广东省”都是合法的地域信息,而“中国 广州市”则不合法,因为填写了城市信息但没有填写省份信息
|
||||||
|
*
|
||||||
|
* @param city
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@JSONField(name = "city")
|
||||||
|
public MenuMatchRule city(String city) {
|
||||||
|
matchRule.put("city", city);
|
||||||
|
this.city = city;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientPlatformType getPlatformType() {
|
||||||
|
return platformType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gender getGender() {
|
||||||
|
return gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProvince() {
|
||||||
|
return province;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasRule() {
|
||||||
|
return !matchRule.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getRule() {
|
||||||
|
return this.matchRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MenuMatchRule [groupId=" + groupId + ", gender=" + gender
|
||||||
|
+ ", platformType=" + platformType + ", country=" + country
|
||||||
|
+ ", province=" + province + ", city=" + city + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台类型
|
||||||
|
*
|
||||||
|
* @className ClientPlatformType
|
||||||
|
* @author jy
|
||||||
|
* @date 2015年12月17日
|
||||||
|
* @since JDK 1.7
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public enum ClientPlatformType {
|
||||||
|
IOS, Android, Others
|
||||||
|
}
|
||||||
@ -55,7 +55,7 @@ public class MediaTest extends TokenTest {
|
|||||||
@Test
|
@Test
|
||||||
public void download1() throws WeixinException, IOException {
|
public void download1() throws WeixinException, IOException {
|
||||||
MediaDownloadResult content = mediaApi.downloadMedia(
|
MediaDownloadResult content = mediaApi.downloadMedia(
|
||||||
"nD05mhmkW-SHVS8NfWSxdzJi-6VnVF5YSP5hmMWnKJUxLK5czAWtN4NhVmgEfVoe", false);
|
"BmzcrM2jaJXZCjBqxLwyC03kh5pge3CbrBqXP4XbYBCeKr7xz-rHuwPf4vYLVdL1", false);
|
||||||
Assert.assertTrue(content != null);
|
Assert.assertTrue(content != null);
|
||||||
System.err.println(content);
|
System.err.println(content);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,9 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
|||||||
import com.foxinmy.weixin4j.http.weixin.JsonResult;
|
import com.foxinmy.weixin4j.http.weixin.JsonResult;
|
||||||
import com.foxinmy.weixin4j.model.Button;
|
import com.foxinmy.weixin4j.model.Button;
|
||||||
import com.foxinmy.weixin4j.mp.api.MenuApi;
|
import com.foxinmy.weixin4j.mp.api.MenuApi;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.Menu;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.MenuMatchRule;
|
||||||
|
import com.foxinmy.weixin4j.mp.type.ClientPlatformType;
|
||||||
import com.foxinmy.weixin4j.type.ButtonType;
|
import com.foxinmy.weixin4j.type.ButtonType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,7 +27,7 @@ import com.foxinmy.weixin4j.type.ButtonType;
|
|||||||
public class MenuTest extends TokenTest {
|
public class MenuTest extends TokenTest {
|
||||||
|
|
||||||
private MenuApi menuApi;
|
private MenuApi menuApi;
|
||||||
private List<Button> btnList;
|
private List<Button> buttons;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() {
|
public void init() {
|
||||||
@ -33,44 +36,47 @@ public class MenuTest extends TokenTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void create() throws WeixinException {
|
public void create() throws WeixinException {
|
||||||
btnList = new ArrayList<Button>();
|
buttons = new ArrayList<Button>();
|
||||||
String domain = "http://wx.jdxg.doubimeizhi.com";
|
String domain = "http://wx.jdxg.doubimeizhi.com";
|
||||||
btnList.add(new Button("立即下单", domain, ButtonType.view));
|
buttons.add(new Button("立即下单", domain, ButtonType.view));
|
||||||
|
|
||||||
btnList.add(new Button("个人中心", domain + "/user", ButtonType.view));
|
buttons.add(new Button("个人中心", domain + "/user", ButtonType.view));
|
||||||
|
|
||||||
Button button = new Button("小哥介绍", domain, ButtonType.view);
|
Button button = new Button("小哥介绍", domain, ButtonType.view);
|
||||||
button.pushSub(new Button("小哥介绍", "http://mp.weixin.qq.com/s?__biz=MzI2MTA5OTM4OQ==&mid=400990970&idx=1&sn=5c7fd72e782c49f7c933b91c63eddc80#rd", ButtonType.view));
|
button.pushSub(new Button(
|
||||||
|
"小哥介绍",
|
||||||
|
"http://mp.weixin.qq.com/s?__biz=MzI2MTA5OTM4OQ==&mid=400990970&idx=1&sn=5c7fd72e782c49f7c933b91c63eddc80#rd",
|
||||||
|
ButtonType.view));
|
||||||
button.pushSub(new Button("服务流程", "FLOW", ButtonType.click));
|
button.pushSub(new Button("服务流程", "FLOW", ButtonType.click));
|
||||||
button.pushSub(new Button("在线客服", "KF", ButtonType.click));
|
button.pushSub(new Button("在线客服", "KF", ButtonType.click));
|
||||||
btnList.add(button);
|
buttons.add(button);
|
||||||
|
|
||||||
JsonResult result = menuApi.createMenu(btnList);
|
JsonResult result = menuApi.createMenu(buttons);
|
||||||
Assert.assertEquals(0, result.getCode());
|
Assert.assertEquals(0, result.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void create1() throws WeixinException {
|
public void create1() throws WeixinException {
|
||||||
btnList = new ArrayList<Button>();
|
buttons = new ArrayList<Button>();
|
||||||
|
|
||||||
Button b1 = new Button("我要订餐", "ORDERING", ButtonType.click);
|
Button b1 = new Button("我要订餐", "ORDERING", ButtonType.click);
|
||||||
btnList.add(b1);
|
buttons.add(b1);
|
||||||
Button b2 = new Button("查询订单", "http://www.lendocean.com/order/list",
|
Button b2 = new Button("查询订单", "http://www.lendocean.com/order/list",
|
||||||
ButtonType.view);
|
ButtonType.view);
|
||||||
btnList.add(b2);
|
buttons.add(b2);
|
||||||
Button b3 = new Button("最新资讯", "NEWS", ButtonType.click);
|
Button b3 = new Button("最新资讯", "NEWS", ButtonType.click);
|
||||||
btnList.add(b3);
|
buttons.add(b3);
|
||||||
JsonResult result = menuApi.createMenu(btnList);
|
JsonResult result = menuApi.createMenu(buttons);
|
||||||
Assert.assertEquals(0, result.getCode());
|
Assert.assertEquals(0, result.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void get() throws WeixinException {
|
public void get() throws WeixinException {
|
||||||
btnList = menuApi.getMenu();
|
buttons = menuApi.getMenu();
|
||||||
for (Button btn : btnList) {
|
for (Button btn : buttons) {
|
||||||
System.out.println(btn);
|
System.out.println(btn);
|
||||||
}
|
}
|
||||||
Assert.assertEquals(3, btnList.size());
|
Assert.assertEquals(3, buttons.size());
|
||||||
// Button [name=我的门店, type=view,
|
// Button [name=我的门店, type=view,
|
||||||
// content=http://dianzhang.canyi.net/setting/index, subs=[]]
|
// content=http://dianzhang.canyi.net/setting/index, subs=[]]
|
||||||
// Button [name=每日签到, type=click, content=CHECKIN, subs=[]]
|
// Button [name=每日签到, type=click, content=CHECKIN, subs=[]]
|
||||||
@ -86,4 +92,26 @@ public class MenuTest extends TokenTest {
|
|||||||
JsonResult result = menuApi.deleteMenu();
|
JsonResult result = menuApi.deleteMenu();
|
||||||
Assert.assertEquals(0, result.getCode());
|
Assert.assertEquals(0, result.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCustom() throws WeixinException {
|
||||||
|
buttons = new ArrayList<Button>();
|
||||||
|
buttons.add(new Button("only for iphone", "iphone", ButtonType.click));
|
||||||
|
MenuMatchRule matchRule = new MenuMatchRule();
|
||||||
|
matchRule.platform(ClientPlatformType.IOS);
|
||||||
|
JsonResult result = menuApi.createCustomMenu(buttons, matchRule);
|
||||||
|
Assert.assertEquals(0, result.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAllMenus() throws WeixinException {
|
||||||
|
List<Menu> menus = menuApi.getAllMenu();
|
||||||
|
System.err.println(menus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMatchMenu()throws WeixinException{
|
||||||
|
List<Button> buttons = menuApi.matchCustomMenu("paihuaing");
|
||||||
|
System.err.println(buttons);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -199,7 +199,7 @@ public class WeixinProxy {
|
|||||||
/**
|
/**
|
||||||
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
|
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
|
||||||
*
|
*
|
||||||
* @param btnList
|
* @param buttons
|
||||||
* 菜单列表
|
* 菜单列表
|
||||||
* @param agentid
|
* @param agentid
|
||||||
* 应用ID
|
* 应用ID
|
||||||
@ -210,9 +210,9 @@ public class WeixinProxy {
|
|||||||
* 创建自定义菜单</a>
|
* 创建自定义菜单</a>
|
||||||
* @see com.foxinmy.weixin4j.model.Button
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
*/
|
*/
|
||||||
public JsonResult createMenu(List<Button> btnList, int agentid)
|
public JsonResult createMenu(List<Button> buttons, int agentid)
|
||||||
throws WeixinException {
|
throws WeixinException {
|
||||||
return menuApi.createMenu(btnList, agentid);
|
return menuApi.createMenu(buttons, agentid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -38,7 +38,7 @@ public class MenuApi extends QyApi {
|
|||||||
/**
|
/**
|
||||||
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
|
* 自定义菜单(管理员须拥有应用的管理权限 并且应用必须设置在回调模式)
|
||||||
*
|
*
|
||||||
* @param btnList
|
* @param buttons
|
||||||
* 菜单列表
|
* 菜单列表
|
||||||
* @param agentid
|
* @param agentid
|
||||||
* 应用ID
|
* 应用ID
|
||||||
@ -47,12 +47,12 @@ public class MenuApi extends QyApi {
|
|||||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E8%8F%9C%E5%8D%95">创建自定义菜单</a>
|
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E8%8F%9C%E5%8D%95">创建自定义菜单</a>
|
||||||
* @see com.foxinmy.weixin4j.model.Button
|
* @see com.foxinmy.weixin4j.model.Button
|
||||||
*/
|
*/
|
||||||
public JsonResult createMenu(List<Button> btnList, int agentid)
|
public JsonResult createMenu(List<Button> buttons, int agentid)
|
||||||
throws WeixinException {
|
throws WeixinException {
|
||||||
String menu_create_uri = getRequestUri("menu_create_uri");
|
String menu_create_uri = getRequestUri("menu_create_uri");
|
||||||
Token token = tokenHolder.getToken();
|
Token token = tokenHolder.getToken();
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("button", btnList);
|
obj.put("button", buttons);
|
||||||
WeixinResponse response = weixinExecutor
|
WeixinResponse response = weixinExecutor
|
||||||
.post(String.format(menu_create_uri, token.getAccessToken(),
|
.post(String.format(menu_create_uri, token.getAccessToken(),
|
||||||
agentid), JSON.toJSONString(obj, new NameFilter() {
|
agentid), JSON.toJSONString(obj, new NameFilter() {
|
||||||
|
|||||||
@ -205,7 +205,6 @@ public final class ClassUtil {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
System.err
|
System.err
|
||||||
.println(getClasses(com.foxinmy.weixin4j.handler.WeixinMessageHandler.class
|
.println(getClasses("com.foxinmy.weixin4j.qy.event"));
|
||||||
.getPackage().getName()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user