微信公眾號開發 (3) 菜單處理

一、前言

本文將實現


  1. 根據AppID和AppSecret獲取access_token
  2. 自定義菜單(創建菜單、查詢菜單、刪除菜單)


  1. access_token的`存儲`至少要保留`512`個`字符`空間。
  2. accesstoken的有效期為2小時,需定時刷新,重複獲取將導致上次獲取的accesstoken失效
  3. 自定義菜單最多3個一級菜單,每一級菜單最多5個二級菜單
  4. 一級菜單最多4個漢字,二級菜單最多7個漢字
  5. 菜單刷新策略:5分鐘之後更新菜單。測試時可以嘗試取消關注公眾賬號後再次關注,則可以看到創建後的效果

二、RestTemplate配置 (用於遠程調用微信http接口方法)

RestTemplate是Spring提供的用於訪問Rest服務的客戶端,RestTemplate提供了多種便捷訪問遠程Http服務的方法,能夠大大提高客戶端的編寫效率。

<code>@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// 解決post請求中文亂碼問題
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}

}/<code>



  1. 獲取accesstoken接口 : 【GET請求】 `https://api.weixin.qq.com/cgi-bin/token?granttype=client_credential&appid=APPID&secret=APPSECRET`
  2. 查詢菜單接口 : 【GET請求】 https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
  3. 刪除菜單接口 : 【GET請求】 https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
  4. 創建菜單接口 : 【POST請求】 https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN


<code>public class Constants {
/**
* TODO 填寫自己的 `appID` 和 `appsecret`
*/
public static final String APP_ID = "xxx";
public static final String APP_SECRET = "xxx";

/**
* 通過 `GET請求方式` 獲取 `access_token`
*/
public static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
/**

* TODO 只做臨時方便測試使用
*/
public static final String ACCESS_TOKEN = "xxx";

/**
* 查詢菜單接口 - GET請求
*/
public static final String GET_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
/**
* 刪除菜單接口 - GET請求 (注意,在個性化菜單時,調用此接口會刪除默認菜單及全部個性化菜單)
*/
public static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
/**
* 創建菜單接口 - POST請求
*/
public static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";

}/<code>


四、根據AppID和AppSecret獲取access_token

accesstoken是公眾號的全局唯一接口調用憑據,公眾號調用各接口(下面的創建菜單、查詢菜單、刪除菜單等)時都需使用accesstoken!

https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

① 封裝響應結果AccessTokenVO


<code>@Data
@ApiModel(description = "access_token: 公眾號的全局唯一接口調用憑據")
public class AccessTokenVO {


@ApiModelProperty(value = "獲取到的憑證")
private String access_token;

@ApiModelProperty(value = "憑證有效時間,單位:秒(微信目前暫7200秒,即2小時,過期後需再次獲取)")
private int expires_in;

}/<code>


② 服務類


<code>public interface IWeixinService {

/**
* 根據AppID和AppSecret獲取access_token
*
* @param appId:
* @param appSecret:
* @return: com.zhengqing.demo.modules.weixin.model.AccessTokenVO
*/
AccessTokenVO getAccessToken(String appId, String appSecret);

}/<code>


③ 服務實現類


<code>@Slf4j
@Service
public class WeixinServiceImpl implements IWeixinService {

@Autowired
private RestTemplate restTemplate;

@Override

public AccessTokenVO getAccessToken(String appId, String appSecret) {
AccessTokenVO accessTokenVO = restTemplate.getForObject(Constants.GET_ACCESS_TOKEN_URL.replace("APPID", appId).replace("APPSECRET", appSecret), AccessTokenVO.class);
return accessTokenVO;
}

}/<code>


五、自定義菜單處理


click和view請求示例


<code>{
"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"
}]
}]

}/<code>


1、封裝菜單數據


溫馨小提示:這裡封裝數據建議多看下微信文檔中給出的數據,不然可能會對最後組裝菜單樹數據創建菜單的時候感到迷惑 ~

微信公眾號開發 (3) 菜單處理

① 菜單類型枚舉類


<code>public enum MenuType {
// 點擊式菜單
CLICK("click"),
// 鏈接式菜單
VIEW("view");
}/<code>


② 菜單 - 基類


<code>@Data
@ApiModel(description = "菜單 - 基類")
public class Button {

@ApiModelProperty(value = "菜單標題,不超過16個字節,子菜單不超過60個字節")
private String name;

}/<code>


③ 點擊式菜單


<code>@Data
@ApiModel(description = "用戶點擊菜單可接收消息推送")
public class ClickButton extends Button {

@ApiModelProperty(value = "菜單的響應動作類型,view表示網頁類型,click表示點擊類型,miniprogram表示小程序類型")

private String type = MenuType.CLICK.getType();

@ApiModelProperty(value = "菜單KEY值,用於消息接口推送,不超過128字節")
private String key;

}/<code>


④ 鏈接式菜單


<code>@Data
@ApiModel(description = "用戶點擊菜單可打開鏈接")
public class ViewButton extends Button {

@ApiModelProperty(value = "菜單的響應動作類型,view表示網頁類型,click表示點擊類型,miniprogram表示小程序類型")
private String type = MenuType.VIEW.getType();

@ApiModelProperty(value = "(view、miniprogram類型必須) 網頁 鏈接,用戶點擊菜單可打開鏈接,不超過1024字節。 type為miniprogram時,不支持小程序的老版本客戶端將打開本url")
private String url;

}/<code>


⑤ 含二級菜單的一級菜單


<code>@Data
@ApiModel(description = "含二級菜單的一級菜單")

public class ComplexButton extends Button {

@ApiModelProperty(value = "二級菜單數組,個數應為1~5個")
private Button[] sub_button;

}/<code>


⑥ 最外層的菜單樹


<code>@Data
@ApiModel(description = "菜單樹")
public class Menu {

@ApiModelProperty(value = "一級菜單數組,個數應為1~3個")
private Button[] button;

}/<code>


2、服務類


<code>public interface IMenuService {

/**
* 查詢菜單
*
* @param accessToken:訪問憑據
* @return: java.lang.Object
*/
Object getMenu(String accessToken);

/**
* 刪除菜單
*

* @param accessToken:訪問憑據
* @return: com.zhengqing.demo.modules.weixin.model.WeixinResponseResult
*/
WeixinResponseResult deleteMenu(String accessToken);

/**
* 創建菜單
*
* @param menu : 創建的菜單數據
* @param accessToken : 訪問憑據
* @return: com.zhengqing.demo.modules.weixin.model.WeixinResponseResult
*/
WeixinResponseResult createMenu(Menu menu, String accessToken);

}/<code>


3、服務實現類


<code>@Slf4j
@Service
public class MenuServiceImpl implements IMenuService {

@Autowired
private RestTemplate restTemplate;


@Override
public Object getMenu(String accessToken) {
Object menu = restTemplate.getForObject(Constants.GET_MENU_URL.replace("ACCESS_TOKEN", accessToken), Object.class);
return menu;
}

@Override
public WeixinResponseResult deleteMenu(String accessToken) {
WeixinResponseResult result = restTemplate.getForObject(Constants.DELETE_MENU_URL.replace("ACCESS_TOKEN", accessToken), WeixinResponseResult.class);
return result;
}

@Override
public WeixinResponseResult createMenu(Menu menu, String accessToken) {
// 將菜單對象轉換成json字符串

String jsonMenu = JSON.toJSONString(menu);
WeixinResponseResult result = restTemplate.postForObject(Constants.CREATE_MENU_URL.replace("ACCESS_TOKEN", accessToken), jsonMenu, WeixinResponseResult.class);
return result;
}

}/<code>


六、測試


1、獲取access_token


<code>@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class WeixinTest {

@Autowired
private IWeixinService weixinService;

@Test // 獲取 `access_token`
public void getAccessToken() throws Exception {
AccessTokenVO accessTokenVO = weixinService.getAccessToken(Constants.APP_ID, Constants.APP_SECRET);
log.info("======================================== \\n" + accessTokenVO.getAccess_token());
}

}/<code>


2、創建自定義菜單、查詢菜單、刪除菜單

注:這裡小編將獲取到的access_token 寫死到常量 Constants.ACCESS_TOKEN 中做測試,實際項目中可將access_token保存到緩存中,每隔快到2個小時的時候去重新獲取一次刷新緩存數據 ~

<code>@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class MenuTest {

@Autowired
private IMenuService menuService;

@Test // 查詢菜單
public void getMenu() {
Object menu = menuService.getMenu(Constants.ACCESS_TOKEN);
log.info("======================================== \\n" + JSON.toJSONString(menu));
}

@Test // 刪除菜單
public void deleteMenu() {
WeixinResponseResult result = menuService.deleteMenu(Constants.ACCESS_TOKEN);
log.info("======================================== \\n" + result);
}

@Test // 創建菜單
public void createMenu() {
WeixinResponseResult result = menuService.createMenu(createMenuTree(), Constants.ACCESS_TOKEN);
log.info("======================================== \\n" + result);
}

/**
* 菜單數據
*/
private Menu createMenuTree() {
// 鏈接式菜單
ViewButton btn11 = new ViewButton();
btn11.setName("CSDN");
btn11.setUrl("https://zhengqing.blog.csdn.net/");

ViewButton btn12 = new ViewButton();
btn12.setName("個人博客");
btn12.setUrl("http://zhengqingya.gitee.io/blog/");

// 點擊式菜單
ClickButton mainBtn2 = new ClickButton();
mainBtn2.setName("點我吖");
mainBtn2.setKey("hello");

ViewButton btn31 = new ViewButton();
btn31.setName("碼雲");

btn31.setUrl("https://gitee.com/zhengqingya/projects");

ViewButton btn32 = new ViewButton();
btn32.setName("GitHub");
btn32.setUrl("https://github.com/zhengqingya?tab=repositories");

// 含二級菜單的一級菜單
ComplexButton mainBtn1 = new ComplexButton();
mainBtn1.setName("博客");
mainBtn1.setSub_button(new ViewButton[]{btn11, btn12});

ComplexButton mainBtn3 = new ComplexButton();
mainBtn3.setName("倉庫");
mainBtn3.setSub_button(new ViewButton[]{btn31, btn32});

Menu menu = new Menu();
menu.setButton(new Button[]{mainBtn1, mainBtn2, mainBtn3});

return menu;
}

}/<code>

最終自定義的菜單

微信公眾號開發 (3) 菜單處理

本文案例demo源碼

https://gitee.com/zhengqingya/java-workspace


分享到:


相關文章: