簡介
TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公眾號開發腳手架,支援任何 Node.js 的服務端框架(Express、Nest、egg 等)
介面許可權
實現自定義選單有兩種方式
- 編輯模式
- 開發模式
編輯模式
登入 MP 平臺,側欄找到 新增功能外掛
選單並在外掛庫中找到 自定義選單
外掛新增後按照提示操作即可。
開發模式
開發模式下有兩種實現方式但推薦使用第二種
- 使用微信 公眾平臺介面除錯工具 實現
- 使用 官方提供的介面 實現
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 版本自定義選單
開源推薦
TNW
微信公眾號開發腳手架:gitee.com/javen205/TN…IJPay
讓支付觸手可及:gitee.com/javen205/IJ…- SpringBoot 微服務高效開發
mica
工具集:gitee.com/596392912/m… Avue
一款基於 vue 可配置化的神奇框架:gitee.com/smallweigit…pig
宇宙最強微服務(架構師必備):gitee.com/log4j/pigSpringBlade
完整的線上解決方案(企業開發必備):gitee.com/smallc/Spri…