溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

微信公眾號開發(fā)-自定義菜單接口

發(fā)布時間:2020-03-04 17:58:06 來源:網(wǎng)絡(luò) 閱讀:3887 作者:ZeroOne01 欄目:移動開發(fā)

開始

本文是 微信開發(fā)-素材/消息管理接口 的后續(xù),主要介紹微信公眾平臺的自定義菜單接口開發(fā)。由于個人的訂閱號是沒有大多數(shù)接口的權(quán)限的,所以我們需要使用微信官方提供的測試號來進行開發(fā)。測試號的申請可參考下文:

  • 使用微信測試賬號對網(wǎng)頁進行授權(quán)

自定義菜單

本小節(jié)我們來開發(fā)一個自定義菜單,官方文檔地址如下:

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013

自定義菜單接口可實現(xiàn)多種類型按鈕,如下:

1、click:點擊推事件用戶點擊click類型按鈕后,微信服務(wù)器會通過消息接口推送消息類型為event的結(jié)構(gòu)給開發(fā)者(參考消息接口指南),并且?guī)习粹o中開發(fā)者填寫的key值,開發(fā)者可以通過自定義的key值與用戶進行交互;
2、view:跳轉(zhuǎn)URL用戶點擊view類型按鈕后,微信客戶端將會打開開發(fā)者在按鈕中填寫的網(wǎng)頁URL,可與網(wǎng)頁授權(quán)獲取用戶基本信息接口結(jié)合,獲得用戶基本信息。
3、scancode_push:掃碼推事件用戶點擊按鈕后,微信客戶端將調(diào)起掃一掃工具,完成掃碼操作后顯示掃描結(jié)果(如果是URL,將進入URL),且會將掃碼的結(jié)果傳給開發(fā)者,開發(fā)者可以下發(fā)消息。
4、scancode_waitmsg:掃碼推事件且彈出“消息接收中”提示框用戶點擊按鈕后,微信客戶端將調(diào)起掃一掃工具,完成掃碼操作后,將掃碼的結(jié)果傳給開發(fā)者,同時收起掃一掃工具,然后彈出“消息接收中”提示框,隨后可能會收到開發(fā)者下發(fā)的消息。
5、pic_sysphoto:彈出系統(tǒng)拍照發(fā)圖用戶點擊按鈕后,微信客戶端將調(diào)起系統(tǒng)相機,完成拍照操作后,會將拍攝的相片發(fā)送給開發(fā)者,并推送事件給開發(fā)者,同時收起系統(tǒng)相機,隨后可能會收到開發(fā)者下發(fā)的消息。
6、pic_photo_or_album:彈出拍照或者相冊發(fā)圖用戶點擊按鈕后,微信客戶端將彈出選擇器供用戶選擇“拍照”或者“從手機相冊選擇”。用戶選擇后即走其他兩種流程。
7、pic_weixin:彈出微信相冊發(fā)圖器用戶點擊按鈕后,微信客戶端將調(diào)起微信相冊,完成選擇操作后,將選擇的相片發(fā)送給開發(fā)者的服務(wù)器,并推送事件給開發(fā)者,同時收起相冊,隨后可能會收到開發(fā)者下發(fā)的消息。
8、location_select:彈出地理位置選擇器用戶點擊按鈕后,微信客戶端將調(diào)起地理位置選擇工具,完成選擇操作后,將選擇的地理位置發(fā)送給開發(fā)者的服務(wù)器,同時收起位置選擇工具,隨后可能會收到開發(fā)者下發(fā)的消息。
9、media_id:下發(fā)消息(除文本消息)用戶點擊media_id類型按鈕后,微信服務(wù)器會將開發(fā)者填寫的永久素材id對應(yīng)的素材下發(fā)給用戶,永久素材類型可以是圖片、音頻、視頻、圖文消息。請注意:永久素材id必須是在“素材管理/新增永久素材”接口上傳后獲得的合法id。
10、view_limited:跳轉(zhuǎn)圖文消息URL用戶點擊view_limited類型按鈕后,微信客戶端將打開開發(fā)者在按鈕中填寫的永久素材id對應(yīng)的圖文消息URL,永久素材類型只支持圖文消息。請注意:永久素材id必須是在“素材管理/新增永久素材”接口上傳后獲得的合法id。

創(chuàng)建自定義菜單所需傳遞的參數(shù)如下:
微信公眾號開發(fā)-自定義菜單接口

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

其他新增按鈕類型的請求體示例:

{
    "button": [
        {
            "name": "掃碼", 
            "sub_button": [
                {
                    "type": "scancode_waitmsg", 
                    "name": "掃碼帶提示", 
                    "key": "rselfmenu_0_0", 
                    "sub_button": [ ]
                }, 
                {
                    "type": "scancode_push", 
                    "name": "掃碼推事件", 
                    "key": "rselfmenu_0_1", 
                    "sub_button": [ ]
                }
            ]
        }, 
        {
            "name": "發(fā)圖", 
            "sub_button": [
                {
                    "type": "pic_sysphoto", 
                    "name": "系統(tǒng)拍照發(fā)圖", 
                    "key": "rselfmenu_1_0", 
                   "sub_button": [ ]
                 }, 
                {
                    "type": "pic_photo_or_album", 
                    "name": "拍照或者相冊發(fā)圖", 
                    "key": "rselfmenu_1_1", 
                    "sub_button": [ ]
                }, 
                {
                    "type": "pic_weixin", 
                    "name": "微信相冊發(fā)圖", 
                    "key": "rselfmenu_1_2", 
                    "sub_button": [ ]
                }
            ]
        }, 
        {
            "name": "發(fā)送位置", 
            "type": "location_select", 
            "key": "rselfmenu_2_0"
        },
        {
           "type": "media_id", 
           "name": "圖片", 
           "media_id": "MEDIA_ID1"
        }, 
        {
           "type": "view_limited", 
           "name": "圖文消息", 
           "media_id": "MEDIA_ID2"
        }
    ]
}

本文主要介紹click和view類型的菜單按鈕的實現(xiàn),只要成功實現(xiàn)了click和view類型的菜單按鈕,其他類型的實現(xiàn)起來都是差不多的。

首先,我們需要根據(jù)官方給出的click和view類型請求體示例中的json結(jié)構(gòu),封裝出各個實體類。第一個要創(chuàng)建的是菜單按鈕基類,封裝通用的字段,代碼如下:

package org.zero01.weixin.mqdemo.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @program: mq-demo
 * @description: 菜單按鈕基類
 * @author: 01
 * @create: 2018-07-05 20:05
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Button {
    private String name;
    private String type;
    private Button[] sub_button;
}

然后是click類型的按鈕,代碼如下:

package org.zero01.weixin.mqdemo.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @program: mq-demo
 * @description: click類型的按鈕
 * @author: 01
 * @create: 2018-07-05 20:08
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClickButton extends Button {
    // click類型按鈕的唯一標(biāo)識符
    private String key;
}

view類型的按鈕,代碼如下:

package org.zero01.weixin.mqdemo.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @program: mq-demo
 * @description: view類型的按鈕
 * @author: 01
 * @create: 2018-07-05 20:08
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ViewButton extends Button {
    // view類型按鈕的點擊跳轉(zhuǎn)鏈接
    private String url;
}

最外層的自定義菜單按鈕實體,代碼如下:

package org.zero01.weixin.mqdemo.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @program: mq-demo
 * @description: 自定義菜單
 * @author: 01
 * @create: 2018-07-05 20:10
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Menu {
    private Button[] button;
}

封裝完實體類之后,將創(chuàng)建菜單接口的url地址,配置到SpringBoot的配置文件中,如下:

wechat:
  ...
  menuUrl: https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

然后在配置類里加上該配置信息的字段,如下:

...
public class WeXinConfig {
    ...
    private String menuUrl;
}

完成配置后,接著在WeiXinUtil里加入如下兩個方法:

/**
 * 組裝自定義菜單對象
 *
 * @return
 */
public static Menu initMenu() {
    Menu menu = new Menu();
    ClickButton clickButton = new ClickButton();
    clickButton.setName("click菜單");
    clickButton.setType("click");
    // key可自定義
    clickButton.setKey("click_001");

    ViewButton viewButton = new ViewButton();
    viewButton.setName("view菜單");
    viewButton.setType("view");
    // url需要帶http協(xié)議頭
    viewButton.setUrl("http://www.baidu.com");

    ClickButton clickButton2 = new ClickButton();
    clickButton2.setName("掃碼事件");
    clickButton2.setType("scancode_push");
    clickButton2.setKey("click_002");

    ClickButton clickButton3 = new ClickButton();
    clickButton3.setName("發(fā)送地理位置");
    clickButton3.setType("location_select");
    clickButton3.setKey("click_003");

    Button button = new Button();
    button.setName("自定義菜單");
    // 設(shè)置子菜單
    button.setSub_button(new Button[]{clickButton2, clickButton3});

    menu.setButton(new Button[]{clickButton, viewButton, button});

    return menu;
}

/**
 * 創(chuàng)建自定義菜單
 *
 * @param token
 * @param menu
 * @return
 * @throws IOException
 */
public static JSONObject createMenu(String token, String menu) throws IOException {
    String url = wxConfig.getMenuUrl().replace("ACCESS_TOKEN", token);

    // 發(fā)送創(chuàng)建菜單請求
    return doPost(url, menu);
}

由于將對象轉(zhuǎn)換成JSON數(shù)據(jù)的時候,需要用到 JSONObject.fromObject(); 這個方法,所以我們需要在pom.xml文件中,添加以下依賴:

<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
<dependency>
    <groupId>net.sf.json-lib</groupId>
    <artifactId>json-lib</artifactId>
    <version>2.4</version>
    <classifier>jdk15</classifier>
</dependency>

確保該依賴添加成功后,在WeiXinUtilTest測試類中,新增一個測試方法,用于測試創(chuàng)建自定義菜單。代碼如下:

@Test
public void createMenu() throws IOException {
    // 獲取token
    AccessToken accessToken = WeiXinUtil.getAccessToken();
    // 組裝自定義菜單對象
    Menu menu = WeiXinUtil.initMenu();
    // 將對象轉(zhuǎn)換成json
    String menuStr = JSONObject.fromObject(menu).toString();
    // 調(diào)用接口,創(chuàng)建自定義菜單
    org.json.JSONObject jsonObject = WeiXinUtil.createMenu(accessToken.getToken(), menuStr);
    // 打印返回結(jié)果
    System.out.println(jsonObject);
}

執(zhí)行如上測試方法后,控制臺輸出如下:

{"errcode":0,"errmsg":"ok"}

從輸出的信息可以看到是創(chuàng)建成功的,那么就打開測試的公眾號,自定義菜單果然成功創(chuàng)建了,如下:
微信公眾號開發(fā)-自定義菜單接口

子菜單也能正常顯示,如下:
微信公眾號開發(fā)-自定義菜單接口


菜單事件推送

開發(fā)完自定義菜單的創(chuàng)建功能后,本小節(jié)我們來看看自定義菜單的事件推送,官方文檔地址如下:

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141016

用戶點擊自定義菜單后,微信會把點擊事件推送給開發(fā)者,這樣開發(fā)者就可以對一些事件進行相應(yīng)的邏輯處理。請注意,點擊菜單彈出子菜單,不會產(chǎn)生上報。請注意,第3個到第8個的所有事件,僅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用戶,舊版本微信用戶點擊后將沒有回應(yīng),開發(fā)者也不能正常接收到事件推送。

首先,我們來看看click類型的事件推送。當(dāng)點擊click類型的菜單拉取消息時,會產(chǎn)生事件推送。推送XML數(shù)據(jù)包示例:

<xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[FromUser]]></FromUserName>
    <CreateTime>123456789</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[CLICK]]></Event>
    <EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>

參數(shù)的說明如下:
微信公眾號開發(fā)-自定義菜單接口

新增一個枚舉類,用于封裝菜單事件類型,代碼如下:

package org.zero01.weixin.mqdemo.common;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @program: mq-demo
 * @description: 菜單事件類型
 * @author: 01
 * @create: 2018-06-24 14:09
 **/
@Getter
@AllArgsConstructor
public enum MenuType {

    // 菜單的click類型
    MENU_CLICK("CLICK"),
    // 菜單的view類型
    MENU_VIEW("VIEW"),
    MENU_SCANCODE("scancode_push"),
    MENU_LOCATION("location"),
    ;

    private String menuType;
}

那么我們就來實現(xiàn)一些簡單的菜單事件推送效果吧,在 WeChatMqController 的text方法里,增加一些判斷條件,雖然這樣比較low,但是demo嘛,懶得寫那么仔細(xì)了,粗暴的能實現(xiàn)就行,如下:

/**
 * 接收微信公眾號消息的接口
 *
 * @param xmlStr
 * @return
 */
@PostMapping("/common")
public String text(@RequestBody String xmlStr) {
    // 將xml格式的數(shù)據(jù),轉(zhuǎn)換為 AllMessage 對象
    AllMessage allMessage = MessageUtil.xmlToAllMessage(xmlStr);

    // 是否是文本消息類型
    if (allMessage.getMsgType().equals(MessageTypeEnum.MSG_TEXT.getMsgType())) {
        if ("1".equals(allMessage.getContent())) {
            return MessageUtil.initNewsMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        } else if ("2".equals(allMessage.getContent())) {
            return MessageUtil.initImageMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        } else if ("3".equals(allMessage.getContent())) {
            return MessageUtil.initMusicMessage(allMessage.getToUserName(), allMessage.getFromUserName());
        }
        // 自動回復(fù)用戶所發(fā)送的文本消息
        return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_PREFIX.getContent() + allMessage.getContent());
    }
    // 是否是事件推送類型
    else if (allMessage.getMsgType().equals(MessageTypeEnum.MSG_EVENT.getMsgType())) {
        // 是否為訂閱事件
        if (EventType.EVENT_SUBSCRIBE.getEventType().equals(allMessage.getEvent())) {
            // 自動回復(fù)歡迎語
            return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_SUBSCRIBE.getContent());
        } else if (MenuType.MENU_CLICK.getMenuType().equals(allMessage.getEvent())) {
            return MessageUtil.autoReply(allMessage, "你點擊了click菜單");
        } else if (MenuType.MENU_VIEW.getMenuType().equals(allMessage.getEvent())) {
            String url = allMessage.getEventKey();
            System.out.println("用戶點擊了view菜單, url: " + url);
        } else if (MenuType.MENU_SCANCODE.getMenuType().equals(allMessage.getEvent())) {
            String key = allMessage.getEventKey();
            System.out.println("用戶點擊了掃碼菜單, key: " + key);
        }
    } else if (MenuType.MENU_LOCATION.getMenuType().equals(allMessage.getMsgType())) {
        String label = allMessage.getLabel();
        return MessageUtil.autoReply(allMessage, "你點擊了發(fā)送地理位置菜單, label: " + label);
    } else {
        // 暫不支持文本以外的消息回復(fù)
        return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_NONSUPPORT.getContent());
    }
    return MessageUtil.autoReply(allMessage, ContentEnum.CONTENT_NONSUPPORT.getContent());
}

重啟SpringBoot工程,效果如下:
微信公眾號開發(fā)-自定義菜單接口

控制臺輸出信息如下:

用戶點擊了view菜單, url: http://www.baidu.com
用戶點擊了掃碼菜單, key: click_002

菜單查詢與刪除

菜單的幾個基本事件也介紹完了,本小節(jié)我們來看看自定義菜單的查詢與刪除,官方文檔地址如下,自定義菜單查詢接口:

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141014

自定義菜單刪除接口:

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141015

由于查詢與刪除接口比較簡單,這里就不贅述了,直接開始開發(fā)吧。同樣的,我們需要先把這兩個接口的url地址配置到SpringBoot的配置文件當(dāng)中,如下:

wechat:
  ...
  queryMenuUrl: https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
  delMenuUrl: https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN

在配置類里加上這兩個配置項的字段,如下:

...
public class WeXinConfig {
    ...
    private String queryMenuUrl;
    private String delMenuUrl;
}

在WeiXinUtil類中,增加如下兩個方法:

/**
 * 查詢自定義菜單
 *
 * @param token
 * @return
 * @throws IOException
 */
public static JSONObject queryMenu(String token) throws IOException {
    String url = wxConfig.getQueryMenuUrl().replace("ACCESS_TOKEN", token);
    return doGet(url);
}

/**
 * 刪除當(dāng)前使用的自定義菜單
 *
 * @param token
 * @return
 * @throws IOException
 */
public static JSONObject delMenu(String token) throws IOException {
    String url = wxConfig.getDelMenuUrl().replace("ACCESS_TOKEN", token);
    return doGet(url);
}

在WeiXinUtilTest測試類里,增加如下測試方法:

@Test
public void queryMenu() throws IOException {
    AccessToken accessToken = WeiXinUtil.getAccessToken();
    org.json.JSONObject jsonObject = WeiXinUtil.queryMenu(accessToken.getToken());
    System.out.println(jsonObject);
}

執(zhí)行測試方法后,正常情況會返回一段json格式的數(shù)據(jù),將其格式化后,如下:

{
  "menu": {
    "button": [
      {
        "name": "click菜單",
        "sub_button": [],
        "type": "click",
        "key": "click_001"
      },
      {
        "name": "view菜單",
        "sub_button": [],
        "type": "view",
        "url": "http:\/\/www.baidu.com"
      },
      {
        "name": "自定義菜單",
        "sub_button": [
          {
            "name": "掃碼事件",
            "sub_button": [],
            "type": "scancode_push",
            "key": "click_002"
          },
          {
            "name": "發(fā)送地理位置",
            "sub_button": [],
            "type": "location_select",
            "key": "click_003"
          }
        ]
      }
    ]
  }
}

查詢自定義菜單的方法測試成功后,再來測試一下刪除當(dāng)前使用的自定義菜單的方法。在WeiXinUtilTest測試類里,增加如下測試方法:

@Test
public void delMenu() throws IOException {
    AccessToken accessToken = WeiXinUtil.getAccessToken();
    org.json.JSONObject jsonObject = WeiXinUtil.delMenu(accessToken.getToken());
    System.out.println(jsonObject);
}

執(zhí)行測試方法后,控制臺輸出如下:

{"errcode":0,"errmsg":"ok"}

可以看到,菜單已經(jīng)刪除成功了,沒有之前的菜單按鈕了:
微信公眾號開發(fā)-自定義菜單接口

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI