Introduction to the
TNW: TypeScript(The) + Node.js(Next) + WeChat public account development scaffolding, support any Node.js server framework (Express, Nest, Egg, etc.)
Interface permissions
Public number interface permission description
Menu rules and button types
There are two ways to implement custom menus
- Edit mode
- Development mode
Edit mode
Log in MP platform, find the menu of adding function plug-in in the sidebar, and find the custom menu plug-in in the plug-in library after adding it, follow the prompts.
Development mode
There are two implementations in development mode but the second is recommended
- Use wechat public platform interface debugging tool to achieve
- Use the interface provided by the official implementation
TNW concrete implementation
- Create a menu
- Delete menu
- Query menu
- Add personalized menu
- Delete personalized menu
- Test personalized menu matching results
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%';
/** * create menu * @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);
}
/** * delete menu * @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);
}
/** * query menu * @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);
}
/** * Add personalization menu * @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);
}
/** * Delete personalization menu * @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);
}
/** * test personalization menu matching result * @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 })); }}Copy the code
Read the configuration file to create the menu
// Read configuration files to create custom menus
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);
});
});
});
Copy the code
Dynamically create custom menus
app.get('/dynamicCreatMenu'.(req: any, res: any) = > {
MenuApi.create(JSON.stringify(MenuManager.getMenu())).then(data= > {
res.send(data);
});
});
Copy the code
Menu Management class
export class MenuManager {
static getMenu(): Menu {
let btn11 = new ClickButton();
btn11.setName = "Wechat photo Album Posting";
btn11.setType = "pic_weixin";
btn11.setKey = "rselfmenu_1_1";
let btn12 = new ClickButton();
btn12.setName = "Take photos or send pictures in albums";
btn12.setType = "pic_photo_or_album";
btn12.setKey = "rselfmenu_1_2";
let btn13 = new ClickButton();
btn13.setName = "System takes photos and sends pictures";
btn13.setType = "pic_sysphoto";
btn13.setKey = "rselfmenu_1_3";
let btn21 = new ClickButton();
btn21.setName = "Scan code with hints.";
btn21.setType = "scancode_waitmsg";
btn21.setKey = "rselfmenu_2_1";
let btn22 = new ClickButton();
btn22.setName = "Sweep push event";
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 = "Send location";
btn32.setType = "location_select";
btn32.setKey = "rselfmenu_3_2";
let btn33 = new ViewButton();
btn33.setName = "Online Consultation";
btn33.setType = "view";
btn33.setUrl = "http://wpa.qq.com/msgrd?v=3&uin=572839485&site=qq&menu=yes";
let btn34 = new ViewButton();
btn34.setName = "My Blog";
btn34.setType = "view";
btn34.setUrl = "https://blog.javen.dev";
let btn35 = new ClickButton();
btn35.setName = "Click event";
btn35.setType = "click";
btn35.setKey = "rselfmenu_3_5";
let mainBtn1 = new ComButton();
mainBtn1.setName = "Hair figure";
mainBtn1.setSubButton = [btn11, btn12, btn13];
let mainBtn2 = new ComButton();
mainBtn2.setName = "Saul code";
mainBtn2.setSubButton = [btn21, btn22, btn23];
let mainBtn3 = new ComButton();
mainBtn3.setName = "Personal Center";
mainBtn3.setSubButton = [btn31, btn32, btn33, btn34, btn35];
let menu = new Menu();
menu.setButton = [mainBtn1, mainBtn2, mainBtn3];
returnmenu; }}Copy the code
Encapsulating entity classes
export class Menu {
privatebutton! : Button[];privatematchrule! : 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 {
// User group ID, which can be obtained through the user group management interface
privatetag_id! :string;
// Gender: male (1) female (2)
privatesex! :string;
// Country information
privatecountry! :string;
// Province information
privateprovince! :string;
// City information
privatecity! :string;
// Client version. Currently, only IOS(1), Android(2), and Others(3) are available
privateclient_platform_type! :string;
// Language information
privatelanguage! :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; }}Copy the code
Java version custom menu
Custom menu for wechat public account development
Open source is recommended
TNW
Scaffolding for the development of wechat official account:Gitee.com/javen205/TN…IJPay
Make payment at your fingertips:Gitee.com/javen205/IJ…- Efficient development of SpringBoot microservices
mica
Tools:Gitee.com/596392912/m… Avue
A fantastic framework based on VUE configurable:Gitee.com/smallweigit…pig
The Strongest Microservices in the universe (required for Architects) :gitee.com/log4j/pigSpringBlade
Complete online solution (necessary for enterprise development) :Gitee.com/smallc/Spri…