TNW-微信公眾號自定義選單

Javen205發表於2019-05-05

簡介

TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公眾號開發腳手架,支援任何 Node.js 的服務端框架(Express、Nest、egg 等)

介面許可權

公眾號介面許可權說明

選單規則以及按鈕型別說明

實現自定義選單有兩種方式

  1. 編輯模式
  2. 開發模式

編輯模式

登入 MP 平臺,側欄找到 新增功能外掛 選單並在外掛庫中找到 自定義選單 外掛新增後按照提示操作即可。

開發模式

開發模式下有兩種實現方式但推薦使用第二種

  1. 使用微信 公眾平臺介面除錯工具 實現
  2. 使用 官方提供的介面 實現

TNW 中具體實現

  • 建立選單
  • 刪除選單
  • 查詢選單
  • 新增個性化選單
  • 刪除個性化選單
  • 測試個性化選單匹配結果
export class MenuApi {

    private static createMenuUrl = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s'
    private static deleteMenuUrl = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=%s';
    private static getMenuUrl = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token=s%';
    private static getSelfMenuInfoUrl = 'https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=s%';

    private static addConditionalUrl = 'https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=s%';
    private static delConditionalUrl = 'https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token=s%';
    private static tryMatchUrl = 'https://api.weixin.qq.com/cgi-bin/menu/trymatch?access_token=s%';


    /**
     * 建立選單
     * @param response 
     * @param menuJson 
     */
    public static async create(menuJson: string) {
        let accessToken = await AccessTokenApi.getAccessToken();
        let url = util.format(this.createMenuUrl, (<AccessToken>accessToken).getAccessToken);
        return HttpKit.getHttpDelegate.httpPost(url, menuJson);
    }
    /**
     * 刪除選單
     * @param response 
     */
    public static async delete() {
        let accessToken = await AccessTokenApi.getAccessToken();
        let url = util.format(this.deleteMenuUrl, (<AccessToken>accessToken).getAccessToken);
        return HttpKit.getHttpDelegate.httpGet(url);
    }
    /**
     * 查詢選單
     * @param response 
     */
    public static async get() {
        let accessToken = await AccessTokenApi.getAccessToken();
        let url = util.format(this.getMenuUrl, (<AccessToken>accessToken).getAccessToken);
        return HttpKit.getHttpDelegate.httpGet(url);
    }
    public static async getCurrentSelfMenu() {
        let accessToken = await AccessTokenApi.getAccessToken();
        let url = util.format(this.getSelfMenuInfoUrl, (<AccessToken>accessToken).getAccessToken);
        return HttpKit.getHttpDelegate.httpGet(url);
    }

    /**
     * 新增個性化選單
     * @param response 
     * @param menuJson 
     */
    public static async addConditional(menuJson: string) {
        let accessToken = await AccessTokenApi.getAccessToken();
        let url = util.format(this.addConditionalUrl, (<AccessToken>accessToken).getAccessToken);
        return HttpKit.getHttpDelegate.httpPost(url, menuJson);
    }

    /**
     * 刪除個性化選單
     * @param response 
     */
    public static async deleteConditional() {
        let accessToken = await AccessTokenApi.getAccessToken();
        let url = util.format(this.delConditionalUrl, (<AccessToken>accessToken).getAccessToken);
        return HttpKit.getHttpDelegate.httpGet(url);
    }
    /**
     * 測試個性化選單匹配結果
     * @param response 
     * @param openId 
     */
    public static async tryMatch(openId: string) {
        let accessToken = await AccessTokenApi.getAccessToken();
        let url = util.format(this.tryMatchUrl, (<AccessToken>accessToken).getAccessToken);
        return HttpKit.getHttpDelegate.httpPost(url, JSON.stringify({
            "user_id": openId
        }));
    }
}
複製程式碼

讀取配置檔案來建立選單

// 讀取配置檔案來建立自定義選單
app.get('/creatMenu', (req: any, res: any) => {
    fs.readFile("./config/menu.json", function (err, data) {
        if (err) {
            console.log(err);
            return;
        }
        let fileData = data.toString();
        console.log(fileData);
        // res.send(fileData)
        MenuApi.create(fileData).then(data => {
            res.send(data);
        });
    });
});
複製程式碼

動態建立自定義選單

app.get('/dynamicCreatMenu', (req: any, res: any) => {
    MenuApi.create(JSON.stringify(MenuManager.getMenu())).then(data => {
        res.send(data);
    });
});
複製程式碼

選單管理類

export class MenuManager {

    static getMenu(): Menu {
        let btn11 = new ClickButton();
        btn11.setName = "微信相簿發圖";
        btn11.setType = "pic_weixin";
        btn11.setKey = "rselfmenu_1_1";

        let btn12 = new ClickButton();
        btn12.setName = "拍照或者相簿發圖";
        btn12.setType = "pic_photo_or_album";
        btn12.setKey = "rselfmenu_1_2";

        let btn13 = new ClickButton();
        btn13.setName = "系統拍照發圖";
        btn13.setType = "pic_sysphoto";
        btn13.setKey = "rselfmenu_1_3";

        let btn21 = new ClickButton();
        btn21.setName = "掃碼帶提示";
        btn21.setType = "scancode_waitmsg";
        btn21.setKey = "rselfmenu_2_1";

        let btn22 = new ClickButton();
        btn22.setName = "掃碼推事件";
        btn22.setType = "scancode_push";
        btn22.setKey = "rselfmenu_2_2";

        let btn23 = new ViewButton();
        btn23.setName = "Gitee";
        btn23.setType = "view";
        btn23.setUrl = "https://gitee.com/javen205";


        let btn31 = new ViewButton();
        btn31.setName = "IJPay";
        btn31.setType = "view";
        btn31.setUrl = "https://gitee.com/javen205/IJPay";

        let btn32 = new ClickButton();
        btn32.setName = "傳送位置";
        btn32.setType = "location_select";
        btn32.setKey = "rselfmenu_3_2";

        let btn33 = new ViewButton();
        btn33.setName = "線上諮詢";
        btn33.setType = "view";
        btn33.setUrl = "http://wpa.qq.com/msgrd?v=3&uin=572839485&site=qq&menu=yes";

        let btn34 = new ViewButton();
        btn34.setName = "我的部落格";
        btn34.setType = "view";
        btn34.setUrl = "https://blog.javen.dev";

        let btn35 = new ClickButton();
        btn35.setName = "點選事件";
        btn35.setType = "click";
        btn35.setKey = "rselfmenu_3_5";

        let mainBtn1 = new ComButton();
        mainBtn1.setName = "發圖";
        mainBtn1.setSubButton = [btn11, btn12, btn13];

        let mainBtn2 = new ComButton();
        mainBtn2.setName = "掃碼";
        mainBtn2.setSubButton = [btn21, btn22, btn23];

        let mainBtn3 = new ComButton();
        mainBtn3.setName = "個人中心";
        mainBtn3.setSubButton = [btn31, btn32, btn33, btn34, btn35];
        let menu = new Menu();
        menu.setButton = [mainBtn1, mainBtn2, mainBtn3];

        return menu;
    }
}
複製程式碼

封裝實體類


export class Menu {
    private button!: Button[];
    private matchrule!: Matchrule;

    public get getButton(): Button[] {
        return this.button;
    }
    public set setButton(button: Button[]) {
        this.button = button;
    }

    public get getMatchrule(): Matchrule {
        return this.matchrule;
    }
    public set setMatchrule(matchrule: Matchrule) {
        this.matchrule = matchrule;
    }
}

export class Button {
    private name: string;
    private type: string;

    constructor(name?: string, type?: string) {
        this.name = name || '';
        this.type = type || '';
    }

    public get getName(): string {
        return this.name;
    }
    public set setName(name: string) {
        this.name = name;
    }

    public get getType(): string {
        return this.type;
    }
    public set setType(type: string) {
        this.type = type;
    }
}


export class ClickButton extends Button {
    private key: string;

    constructor(name?: string, type?: string, key?: string) {
        super(name, type);
        this.key = key || '';
    }

    public get getKey(): string {
        return this.key;
    }
    public set setKey(key: string) {
        this.key = key;
    }
}


export class ComButton extends Button {
    private sub_button: Button[];

    constructor(name?: string, type?: string, sub_button?: Button[]) {
        super(name, type);
        this.sub_button = sub_button || [];
    }

    public get getSubButton(): Button[] {
        return this.sub_button;
    }
    public set setSubButton(sub_button: Button[]) {
        this.sub_button = sub_button;
    }
}


export class MediaButton extends Button {
    private media_id: string;

    constructor(name?: string, type?: string, media_id?: string) {
        super(name, type);
        this.media_id = media_id || '';
    }

    public get getMediaId(): string {
        return this.media_id;
    }
    public set setMediaId(media_id: string) {
        this.media_id = media_id;
    }
}

export class ViewButton extends Button {
    private url: string;

    constructor(name?: string, type?: string, url?: string) {
        super(name, type);
        this.url = url || '';
    }

    public get getUrl(): string {
        return this.url;
    }
    public set setUrl(url: string) {
        this.url = url;
    }
}

export class Matchrule {
    //使用者分組id,可通過使用者分組管理介面獲取
    private tag_id!: string;
    //性別:男(1)女(2),不填則不做匹配
    private sex!: string;
    //國家資訊
    private country!: string;
    //省份資訊
    private province!: string;
    //城市資訊
    private city!: string;
    //客戶端版本,當前只具體到系統型號:IOS(1), Android(2),Others(3),不填則不做匹配
    private client_platform_type!: string;
    //語言資訊
    private language!: string;


    public get getTagId(): string {
        return this.tag_id;
    }

    public set setTagId(tag_id: string) {
        this.tag_id = tag_id;
    }

    public get getSex(): string {
        return this.sex;
    }

    public set setSex(sex: string) {
        this.sex = sex;
    }

    public get getCountry(): string {
        return this.country;
    }

    public set setCountry(country: string) {
        this.country = country;
    }

    public get getProvince(): string {
        return this.province;
    }

    public set setProvince(province: string) {
        this.province = province;
    }

    public get getCity(): string {
        return this.city;
    }

    public set setCity(city: string) {
        this.city = city;
    }

    public get getClientPlatformType(): string {
        return this.client_platform_type;
    }

    public set setClientPlatformType(client_platform_type: string) {
        this.client_platform_type = client_platform_type;
    }

    public get getLanguage(): string {
        return this.language;
    }

    public set setLanguage(language: string) {
        this.language = language;
    }

}
複製程式碼

Java 版本自定義選單

微信公眾號開發之自定義選單

開源推薦

相關文章