微信公衆號開發02----自定義菜單及菜單功能實現

創建自定義菜單

公衆平臺的自定義菜單主要分三種:

  • 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跳轉並獲取微信用戶的信息

界面跳轉並認證流程

用戶點公衆號菜單
調用view類型中配置的url
在服務器方法中調用微信的oauth認證並獲取token
再根據token來獲取微信用戶的openid及其他信息

官方的這個流程聽起來就很暈了,如果你是個新手,可能你已經完全沒勇氣往下走了,因爲這裏如果出現什麼異常,其實是很難定位的。
所以接下直接上代碼,按照代碼的編寫過程邊複製代碼邊理解,這樣就算中間出現什麼問題,你也能有解決問題的方向。

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/redirecttocashoutURL邏輯
//公衆號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)

下一篇將會介紹 微信支付 充值功能實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章