微信公眾號開發 (3) 選單處理
阿新 • • 發佈:2020-01-17
一、前言
- 微信公眾號開發 (1) 微信接入認證成為開發者
- 微信公眾號開發 (2) 訊息處理
本文將實現
- 根據
AppID
和AppSecret
獲取access_token
- 自定義選單(
建立選單
、查詢選單
、刪除選單
)
微信文件中提示的一些注意點:
- access_token的
儲存
至少要保留512
個字元
空間。 - access_token的
有效期
為2小時
,需定時重新整理,重複獲取將導致上次獲取的access_token失效 - 自定義選單最多
3個一級選單
,每一級選單最多5個二級選單
一級選單最多4個漢字
,二級選單最多7個漢字
選單重新整理策略:
5分鐘之後更新選單。測試時可以嘗試取消關注公眾賬號後再次關注,則可以看到建立後的效果
二、RestTemplate
配置 (用於遠端呼叫
微信http介面
方法)
RestTemplate是Spring提供的用於訪問Rest服務的客戶端,RestTemplate提供了多種便捷訪問遠端Http服務的方法,能夠大大提高客戶端的編寫效率。
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); // 解決post請求中文亂碼問題 restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); return restTemplate; } }
三、微信介面呼叫說明
- 獲取access_token介面 :
【GET請求】
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
- 查詢選單介面 :
【GET請求】
https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
- 刪除選單介面 :
【GET請求】
https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
- 建立選單介面 :
【POST請求】
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
封裝微信介面所需變數
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";
}
四、根據AppID
和AppSecret
獲取access_token
access_token是公眾號的全域性唯一介面呼叫憑據,公眾號呼叫各介面(下面的建立選單
、查詢選單
、刪除選單
等)時都需使用access_token!
這裡可檢視微信文件獲取access_token方式
① 封裝響應結果AccessTokenVO
@Data
@ApiModel(description = "access_token: 公眾號的全域性唯一介面呼叫憑據")
public class AccessTokenVO {
@ApiModelProperty(value = "獲取到的憑證")
private String access_token;
@ApiModelProperty(value = "憑證有效時間,單位:秒(微信目前暫7200秒,即2小時,過期後需再次獲取)")
private int expires_in;
}
② 服務類
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);
}
③ 服務實現類
@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;
}
}
五、自定義選單處理
click
和view
請求示例
{
"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"
}]
}]
}
1、封裝選單資料
溫馨小提示:這裡封裝資料建議多看下微信文件中給出的資料,不然可能會對最後組裝選單樹資料建立選單的時候感到迷惑 ~
① 選單型別列舉類
public enum MenuType {
// 點選式選單
CLICK("click"),
// 連結式選單
VIEW("view");
}
② 選單 - 基類
@Data
@ApiModel(description = "選單 - 基類")
public class Button {
@ApiModelProperty(value = "選單標題,不超過16個位元組,子選單不超過60個位元組")
private String name;
}
③ 點選式選單
@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;
}
④ 連結式選單
@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;
}
⑤ 含二級選單的一級選單
@Data
@ApiModel(description = "含二級選單的一級選單")
public class ComplexButton extends Button {
@ApiModelProperty(value = "二級選單陣列,個數應為1~5個")
private Button[] sub_button;
}
⑥ 最外層的選單樹
@Data
@ApiModel(description = "選單樹")
public class Menu {
@ApiModelProperty(value = "一級選單陣列,個數應為1~3個")
private Button[] button;
}
2、服務類
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);
}
3、服務實現類
@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;
}
}
六、測試
1、獲取access_token
@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());
}
}
2、建立自定義選單
、查詢選單
、刪除選單
注:這裡小編將獲取到的access_token
寫死到常量 Constants.ACCESS_TOKEN
中做測試,實際專案中可將access_token
儲存到快取中,每隔快到2個小時的時候去重新獲取一次重新整理快取資料 ~
@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;
}
}
最終自定義的選單
本文案例demo原始碼
https://gitee.com/zhengqingya/java-workspace