創建自定義菜單
公衆平臺的自定義菜單主要分三種:
- view類型:點菜單跳轉到一個新界面
- click類型:獲取菜單的點擊事件,點擊後要做什麼你決定
- miniprogram類型:小程序類型
官網的開發文檔中,對自定義菜單的一些基本概念和特點都講的很詳細了,這裏不再贅述,直接進入正題。
下面代碼片段都是接上一篇,代碼均是寫在WeixinGZHService.java類
1. 程序生成自定義菜單
@Value("${weixinGZH.appid}")
private String WEIXIN_GZH_APPID;
@Value("${weixinGZH.secret}")
private String WEIXIN_GZH_SECRET;
public static final String WEIXIN_ACCESS_TOKEN_KEY = "weixin_access_token";
public static final String KEY_I_HAVE_TIME = "V1001_I_have_time";
/**
* 生成菜單列表
*/
public void createMenuList() throws IOException, ParseException {
httpClient = new HttpClient(get_create_menu_list(getAcessToken()));
httpClient.setHttps(true);
//定義自定義菜單集合
List<WeixinMenu> weixinMenus = new ArrayList<>();
//一級菜單
WeixinMenu menu1 = new WeixinMenu();
menu1.setName("我有空");
menu1.setType(ButtonType.click);
menu1.setKey(KEY_I_HAVE_TIME);
weixinMenus.add(menu1);
WeixinMenu menu2 = new WeixinMenu();
menu2.setName("任務中心");
menu2.setType(ButtonType.view);
menu2.setUrl(SERVER_ROOT_URL + "/redirect/redirecttogoingorder");
weixinMenus.add(menu2);
WeixinMenu menu3 = new WeixinMenu();
menu3.setName("我的帳戶");
menu3.setSub_button(new ArrayList<>());
menu3.setType(null);
WeixinMenu subMenu3_0 = new WeixinMenu();
subMenu3_0.setName("查看餘額");
subMenu3_0.setType(ButtonType.view);
subMenu3_0.setUrl(SERVER_ROOT_URL + "/redirect/redirecttocashout");
menu3.getSub_button().add(subMenu3_1);
WeixinMenu subMenu3_1 = new WeixinMenu();
subMenu3_1.setName("本月戰績");
subMenu3_1.setType(ButtonType.view);
subMenu3_1.setUrl(SERVER_ROOT_URL + "/redirect/redirecttomonthscore");
menu3.getSub_button().add(subMenu3_1);
weixinMenus.add(menu3);
WeixinMenu subMenu3_2 = new WeixinMenu();
subMenu3_2.setName("註冊視頻教程");
subMenu3_2.setType(ButtonType.view);
subMenu3_2.setUrl("http://www.baidu.com");
menu3.getSub_button().add(subMenu3_2);
Map map = new HashMap();
map.put("button", weixinMenus);
System.out.println("菜單轉json對象:" + JSONObject.toJSONString(map));
httpClient.setXmlParam(JSONObject.toJSONString(map));
httpClient.post();
System.out.println("======創建菜單:" + httpClient.getContent());
}
/**
* 獲取創建菜單的url
*
* @return
*/
public String get_create_menu_list(String accessToken) {
return "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + accessToken;
}
@Autowired
private RedisTemplate redisTemplate;
/**
* 獲取access_token。
* access_token之所以採用緩存到redis,是因爲這個token在微信官方中指明只有2個小時時效,超過2小時,要重新獲取
* 所以在這裏,將直接藉助Redis來設置生成的token時效110分鐘,這樣目的是既可以防止頻繁調用公衆號獲取token接口又能保存程序自動獲取token
*/
public String getAcessToken() {
Object accessToken = redisTemplate.opsForValue().get(WEIXIN_ACCESS_TOKEN_KEY);
if (accessToken == null) {
//重新調用接口查詢access_token
httpClient = new HttpClient(get_access_token(WEIXIN_GZH_APPID, WEIXIN_GZH_SECRET));
try {
httpClient.get();
String content = httpClient.getContent();
JSONObject jsonObject = JSONObject.parseObject(content);
accessToken = jsonObject.get("access_token");
if (accessToken != null) {
redisTemplate.opsForValue().set(WEIXIN_ACCESS_TOKEN_KEY, accessToken.toString(), 110, TimeUnit.MINUTES);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return accessToken == null ? null : accessToken.toString();
}
2.實現每個菜單跳轉業務代碼
上面的代碼示例,我用到了3種菜單跳轉類型:
click:在點擊菜單時,處理業務邏輯
view:
跳轉界面,不需要獲取當前微信用戶信息
跳轉界面,需要獲取當前點擊菜單的微信用戶信息
2.1 click菜單業務代碼
在程序中,實現click點擊,那就需要在我上一篇中講聯調公衆平臺時寫的那個WechatCallbackApi.java類中完成
- 示例代碼如下(代碼寫在WechatCallbackApi.java)
//在doGet()方法中,通過下面的方法來進行判斷
/發送模板消息時,也會向公衆號返回一條消息,但此消息的數據類型與 click事件的返回類型不同。需要判斷eventKey的值
if (weixinResult != null && StringUtils.isNotBlank(weixinResult.getEventKey())) {
switch (weixinResult.getEventKey()) {
case KEY_I_HAVE_TIME:
//這裏處理點這個【我有空】菜單時的業務邏輯代碼
//當然,這裏的業務代碼沒必要寫在這個類中,你可以再寫一個component,然後通過@Autowired注入後調用封裝後的方法
break;
}
}
2.2 view跳轉並獲取微信用戶的信息
界面跳轉並認證流程
官方的這個流程聽起來就很暈了,如果你是個新手,可能你已經完全沒勇氣往下走了,因爲這裏如果出現什麼異常,其實是很難定位的。
所以接下直接上代碼,按照代碼的編寫過程邊複製代碼邊理解,這樣就算中間出現什麼問題,你也能有解決問題的方向。
2.2.1 編寫創建view菜單時的跳轉URL代碼
- 代碼回顧
WeixinMenu subMenu3_0 = new WeixinMenu();
subMenu3_0.setName("查看餘額");
subMenu3_0.setType(ButtonType.view);
subMenu3_0.setUrl(SERVER_ROOT_URL + "/redirect/redirecttocashout");
配置的URL是:SERVER_ROOT_URL + “/redirect/redirecttocashout”。
SERVER_ROOT_URL :這是訪問你服務器根路徑的變量
- 上面的配置,意思是當你點【查看餘額】菜單時,就會向你指定的服務器中,由微信平臺發起一個 /redirect/redirecttocashout 請求。
現在問題來了,微信後臺如何能知道我們服務器的根URL是多少呢?
所以在這裏,你需要再到微信公衆後臺配置一個訪問你服務器的根路徑信息
2.2.2 配置網頁授權
點擊【修改】,進行訪問根URL配置
將圖片中第3步的文件下載來,放到你的後臺工程中 /resources/static 目錄下。
域名1:配置外網訪問你服務器的域名或是外網IP
如何確定文件放對了位置:訪問工程URL+第3步中的文件名。如果可以成功訪問,則說明成功。
如果你在訪問時,報401之類錯誤,則說明被你的權限框架攔截了,配置文件URL放行即可。
2.2.3 編寫跳轉的control邏輯
關於公衆號view界面跳轉帶授權的邏輯將都會寫在WeixinRedirectController.java類中
- 處理
/redirect/redirecttocashout
URL邏輯
//公衆號view跳轉並獲取openid的跳轉操作
@Controller
@RequestMapping("/redirect")
public class WeixinRedirectController {
@Value("${weixinGZH.appid}")
private String WEIXIN_GZH_APPID;
@Value("${weixinGZH.secret}")
private String WEIXIN_GZH_SECRET;
@Value("${SERVER_ROOT_URL}")
private String SERVER_ROOT_URL;
/**
* 重定向到【我的餘額】
*
* @param
* @return java.lang.String
* @author caiwen
*/
@RequestMapping("/redirecttocashout")
public String redirectToCashout() {
return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid="
+ WEIXIN_GZH_APPID + "&redirect_uri=" + SERVER_ROOT_URL
+ "/redirect/weixinoauth&response_type=code&scope=snsapi_base&state=" + STATE_CASHOUT + "#wechat_redirect";
}
}
關鍵參數state
,這個值是用於區分後面oauth認證成功後,到底是點的哪個菜單。
- 跳轉到微信公衆平臺的oauth認證的統一方法
@RequestMapping("/weixinoauth")
public String weixinOauth(String code, String state) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
+ WEIXIN_GZH_APPID + "&secret=" + WEIXIN_GZH_SECRET + "&code=" + code + "&grant_type=authorization_code";
HttpClient httpClient = new HttpClient(url);
String content = "";
try {
httpClient.get();
content = httpClient.getContent();
} catch (Exception e) {
e.printStackTrace();
}
String openid = JSONObject.parseObject(content).getString("openid");
LoggerFactory.getLogger(getClass()).error("================content=" + content + ",openid=" + openid);
String redirect = "";
if (StringUtils.isBlank(openid)) {
return null;
}
//根據state的值,決定在拿到了用戶openid的情況下往哪裏跳
switch (state) {
case STATE_CASHOUT:
redirect = "真正要跳轉到你自己頁面的URL,可以是一個後臺請求URL也可以直接是一個界面地址。"
break;
}
return "redirect:" + redirect;
}
到此,通過自定義菜單跳轉個人界面,同時獲取當前點擊按鈕的微信用戶的信息(openid)
下一篇將會介紹 微信支付 充值功能實現