TNW: TypeScript(The) + Node.js(Next) + WeChat 微信公衆號開發腳手架,支持任何 Node.js 的服務端框架(Express、Nest、egg 等)vue
公衆號接口權限說明git
菜單規則以及按鈕類型說明typescript
實現自定義菜單有兩種方式json
登陸 MP 平臺,側欄找到 添加功能插件
菜單並在插件庫中找到 自定義菜單
插件添加後按照提示操做便可。api
開發模式下有兩種實現方式但推薦使用第二種微信
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;
}
}
複製代碼
封裝實體類app
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;
}
}
複製代碼
TNW
微信公衆號開發腳手架:gitee.com/javen205/TN…IJPay
讓支付觸手可及:gitee.com/javen205/IJ…mica
工具集:gitee.com/596392912/m…Avue
一款基於 vue 可配置化的神奇框架:gitee.com/smallweigit…pig
宇宙最強微服務(架構師必備):gitee.com/log4j/pigSpringBlade
完整的線上解決方案(企業開發必備):gitee.com/smallc/Spri…