zoukankan      html  css  js  c++  java
  • 微信公众号开发(三)

    自定义菜单

    资料:https://developers.weixin.qq.com/doc/offiaccount/Custom_Menus/Creating_Custom-Defined_Menu.html

    请注意:

    1. 自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
    2. 一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。
    3. 创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。 ​

    创建菜单接口调用请求说明

    请求地址: https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

    请求方式:POST

    删除菜单接口调用请求说明

    请求地址:https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN

    请求方式:GET

    查询菜单接口调用请求说明

    请求地址:https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN

    请求方式: GET

    示例:

    // 引入request-promist-native
    const rp = require('request-promise-native');
    // 引入fs方法
    const {writeFile, readFile} = require('fs');
    
    var app = function () {
        return {
            /**
             * 用来获取access_token
             * */
            async getAccessToken() {
                // 定义请求父地址
                const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx4cac0ae3b7cb88dc&secret=e895c1174c407d88bed2bf34e705c56b`
                /*
                * 发送请求
                * request
                * request-promist-native
                * 下载:npm i request request-promise-native
                * */
                return new Promise((resolve, reject) => {
                    rp({method: 'GET', url, json: true}).then(res => {
                        // {   //获取到的凭证
                        //     access_token: '34_4CwWFJkJN8yAvRqm4q4eqH_SozmhKqXqDDJ1gJ9HLWhD9FFnPX-sp5dxTlbhIhsmUFtFb471mCWkWjQREVmVpwewmLW45DD2MMD3tWXEjIWbsnqvB1f5ZN-d7IiXQ_UVgcOKlsx89cdUwVsgSQHgAGAZXO',
                        //     expires_in: 7200 // 过期时间
                        // }
                        // 设置access_token的过期时间
                        res.expires_in = Date.now() + (res.expires_in - 5 * 60) * 1000;
                        //    将promise对象状态改为成功的状态
                        resolve(res)
                    }).catch(err => {
                        reject('getAccessToken方法出了问题:' + err)
                    })
                })
            },
    
            /**
             * 用来保存access_token的方法
             * @param accessToken 要保存的
             * */
            saveAccessToken(accessToken) {
                // 保存
                return new Promise((resolve, reject) => {
                    writeFile('./accessToken', JSON.stringify(accessToken), err => {
                        if (!err) {
                            resolve()
                        } else {
                            reject('saveAccessToken方法出了问题' + err)
                        }
                    })
                })
            },
    
            /**
             * 用来读取access_token的方法
             * */
            readAccessToken() {
                // 保存
                return new Promise((resolve, reject) => {
                    readFile('./accessToken', (err, date) => {
                        if (!err) {
                            resolve(JSON.parse(date))
                        } else {
                            reject('saveAccessToken方法出了问题' + err)
                        }
                    })
                })
            },
    
            /**
             * 检查 access_token 是否是有效的
             * @param data
             * */
            isValidAccessToken(data) {
                // 检查传入的参数是否是有效的
                if (!data && !data.access_token && !data.expires_in) {
                    return false //    代表access_token无效的
                }
                return data.expires_in > Date.now();
            },
    
            /**
             * 用来获取没有过期的access_token
             * */
            async fetchAccessToken() {
                if (this.access_token && this.expires_in && this.isValidAccessToken(this)) {
                    // 说明之前保存过access_token,并且它是有效的,直接使用
                    return Promise.resolve({
                        access_token: this.access_token,
                        expires_in: this.expires_in
                    })
                }
                return this.readAccessToken()
                    .then(async res => {
                        // 本地文件
                        // 判断是否过期
                        if (this.isValidAccessToken(res)) {
                            return Promise.resolve(res);
                        } else {
                            // 无效的:发送请求获取access_token
                            const res = await this.getAccessToken()
                            // 保存下来,直接使用
                            await this.saveAccessToken(res);
                            // 将请求回来的access_token返回出去
                            return Promise.resolve(res);
                        }
                    }).catch(async err => {
                            // 没有本地文件
                            // 发送请求获取access_token
                            const res = await this.getAccessToken()
                            //    保存下来,直接使用
                            await this.saveAccessToken(res);
                            // 将请求回来的access_token返回出去
                            return Promise.resolve(res);
                        }
                    ).then(res => {
                        // 将access_token挂载到this中
                        this.access_token = res.access_token;
                        this.expires_in = res.expires_in;
                        // 返回res包装了一层promise对象
                        // 是this.readAccessToken()最终的返回值
                        return Promise.resolve(res);
                    })
            },
            /*
            * 创建自定义菜单
            * */
            createMenu(menu) {
                return new Promise(async (resolve, reject) => {
                    try {
                        // 获取access_token
                        const data = await this.fetchAccessToken();
                        // 定义请求地址
                        const url = `https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${data.access_token}`
                        const result = rp({method: 'POST',url,json:true,body:menu});
                        resolve(result)
                    } catch (e) {
                        reject('createMenu方法:' + e)
                    }
                })
            },
            /*
            * 删除自定义菜单
            * */
            deleteMenu() {
                return new Promise(async (resolve, reject) => {
                    try {
                        const data = await this.fetchAccessToken();
                        const url = `https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=${data.access_token}`;
                        const result =await rp({method:'GET',url,json:true});
                        resolve(result)
                    }catch (e) {
                        reject('deleteMenu:'+ e)
                    }
                })
            },
            /*
            * 查询自定义菜单
            * */
            getMenu() {
                return new Promise(async (resolve, reject) => {
                    try {
                        const data = await this.fetchAccessToken();
                        const url = `https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=${data.access_token}`;
                        const result =await rp({method:'GET',url,json:true});
                        resolve(result)
                    }catch (e) {
                        reject('deleteMenu:'+ e)
                    }
                })
            }
        }
    };
    
    
    // 菜单
    const menu = {
        "button":[
            {
                "name":"点击事件",
                "sub_button":[
                    {
                        "type":"click",
                        "name":"功能说明",
                        "key":"click事件"
                    },
                    {
                        "type":"click",
                        "name":"菜单模式1",
                        "key":"click1事件"
                    },
                    {
                        "type":"click",
                        "name":"菜单模式2",
                        "key":"click2事件"
                    }
                ]
            },
            {
                "name":"菜单",
                "sub_button":[
                    {
                        "type":"view",
                        "name":"搜索",
                        "url":"http://www.soso.com/"
                    },
                    {
                        "type": "scancode_waitmsg",
                        "name": "扫码带提示",
                        "key": "rselfmenu_0_0",
                        "sub_button": [ ]
                    },
                    {
                        "type": "scancode_push",
                        "name": "扫码推事件",
                        "key": "rselfmenu_0_1",
                        "sub_button": [ ]
                    }
                ]
            },{
                "name": "发图",
                "sub_button": [
                    {
                        "type": "pic_sysphoto",
                        "name": "系统拍照发图",
                        "key": "rselfmenu_1_0",
                        "sub_button": [ ]
                    },
                    {
                        "type": "pic_photo_or_album",
                        "name": "拍照或者相册发图",
                        "key": "rselfmenu_1_1",
                        "sub_button": [ ]
                    },
                    {
                        "type": "pic_weixin",
                        "name": "微信相册发图",
                        "key": "rselfmenu_1_2",
                        "sub_button": [ ]
                    },
                    {
                        "name": "发送位置",
                        "type": "location_select",
                        "key": "rselfmenu_2_0"
                    },
                ]
            },
        ]
    };
    (async () => {
        // 删除之前的自定义菜单
        let result = await app().deleteMenu();
        console.log(result)
        // 创建新的菜单
        result = await app().createMenu(menu);
        console.log(result)
        // 查询菜单
        result = await app().getMenu();
        console.log(result)
    })();

     右击执行,重新关注测试号

  • 相关阅读:
    [转载]Python爬虫之xpath使用技巧
    手机自动化脚本
    英镑像素转换
    小程序路径存入数据库
    avalonia项目在银河麒麟操作系统arm架构上运行报错:default font family is not be null or empty
    http 301、304状态码
    一文完全理解IP
    TCP是如何保证可靠传输的?
    一文弄懂TCP常见面试题
    一文弄懂HTTP常见面试题
  • 原文地址:https://www.cnblogs.com/huoqin/p/13220727.html
Copyright © 2011-2022 走看看