• .Net6+Furion+Sqlsugar+SenparcSdk开发微信公众号系列之八:自定义菜单


    一、创建接口

    1.1、注意事项

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

    1.2、按钮类型

    1. click:点击推事件用户点击 click 类型按钮后,微信服务器会通过消息接口推送消息类型为 event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的 key 值,开发者可以通过自定义的 key 值与用户进行交互;
    2. view:跳转 URL 用户点击 view 类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。
    3. scancode_push:扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。
    4. scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。
    5. pic_sysphoto:弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。
    6. pic_photo_or_album:弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。
    7. pic_weixin:弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。
    8. location_select:弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
    9. media_id:下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材 id 对应的素材下发给用户,永久素材类型可以是图片、音频、视频 、图文消息。请注意:永久素材 id 必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
    10. view_limited:跳转图文消息 URL 用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材 id 对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材 id 必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
    11. article_id:用户点击 article_id 类型按钮后,微信客户端将会以卡片形式,下发开发者在按钮中填写的图文消息
    12. article_view_limited:类似 view_limited,但不使用 media_id 而使用 article_id

    注意: 草稿接口灰度完成后,将不再支持图文信息类型的 media_id 和 view_limited,有需要的,请使用 article_id 和 article_view_limited 代替

    请注意,3到8的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推送。9~12,是专门给第三方平台旗下未微信认证(具体而言,是资质认证未通过)的订阅号准备的事件类型,它们是没有事件推送的,能力相对受限,其他类型的公众号不必使用。

    1.3、使用测试账号

    默认账号没有认证是不能新建自定义菜单的

    可以使用平台测试账号调试接口

    1.4、WebApi

    Services文件夹下新建文件夹Menu和菜单服务MenuService.cs

    新建创建菜单接口

    namespace WeiXinApi.Application.Services
    {
        public class MenuService : BaseService
        {
    
            /// <summary>
            /// 创建菜单
            /// </summary>
            /// <param name="resultFull"></param>
            /// <returns></returns>
            [HttpPost("/menu/add")]
            public dynamic CrateMenu(GetMenuResultFull resultFull)
            {
                try
                {
                    var buttonGroup = CommonApi.GetMenuFromJsonResult(resultFull, new ButtonGroup()).menu;
                    var result = CommonApi.CreateMenu(AppId, buttonGroup);
                    if (result.errmsg == "ok")
                    {
                        return "菜单更新成功";
                    }
                    else
                    {
                        return result;
                    }
                }
                catch (Exception ex)
                {
    
                    throw Oops.Oh($"更新失败:{ex.Message}");
                }
    
            }
    
        }
    }

    使用apipost测试接口

    测试数据

    {
    	"menu": {
    		"button": [
    			{
    				"type": "click",
    				"name": "今日歌曲",
    				"key": "V1001_TODAY_MUSIC"
    			},
    			{
    				"name": "菜单",
    				"sub_button": [
    					{
    						"type": "view",
    						"name": "搜索",
    						"url": "http://www.baidu.com/"
    					},
    					{
    						"type": "click",
    						"name": "赞一下我们",
    						"key": "V1001_GOOD"
    					}
    				]
    			},
    			{
    				"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": []
    					}
    				]
    			}
    		]
    	}
    }

    二、查询接口

    2.1、说明

    本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过 API 调用设置的菜单,则返回菜单的开发配置,而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。

    请注意:

    1. 第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自定义菜单配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。
    2. 本接口与自定义菜单查询接口的不同之处在于,本接口无论公众号的接口是如何设置的,都能查询到接口,而自定义菜单查询接口则仅能查询到使用 API 设置的菜单配置。
    3. 认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。
    4. 从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。
    5. 本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理 - 获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理 - 获取永久素材接口来获取这些素材)。

    2.2、WebApi

    新建接口

            /// <summary>
            /// 获取菜单
            /// </summary>
            /// <returns></returns>
            [HttpGet("/menu/list")]
            public dynamic GetMenu()
            {
                try
                {
                    var result = CommonApi.GetMenu(AppId);
                    if (result == null)
                    {
                        throw Oops.Oh($"菜单不存在或验证失败");
                    }
                    else
                    {
                        //正常序列化只返回菜单Name,因为GetMenuResult里面button只有name字段,所以这里需要转换一下
                        var menu = JsonConvert.DeserializeObject<GetMenuResultFull>(result.ToJson());
                        return menu;
                    }
                }
                catch (Exception ex)
                {
                    throw Oops.Oh($"菜单不存在或验证失败:{ex.Message}");
    
                }
            }

    测试接口

    三、删除接口

    3.1、说明

    使用接口创建自定义菜单后,开发者还可使用接口删除当前使用的自定义菜单。另请注意,在个性化菜单时,调用此接口会删除默认菜单及全部个性化菜单。

    3.2、WebApi

            /// <summary>
            /// 删除菜单
            /// </summary>
            /// <returns></returns>
            [HttpGet("/menu/delete")]
            public dynamic Delete()
            {
                try
                {
                    var result = CommonApi.DeleteMenu(AppId);
                    if (result.errmsg == "ok")
                    {
                        return "删除菜单成功";
                    }
                    else
                    {
                        return result.errmsg;
                    }
                }
                catch (Exception ex)
                {
                    throw Oops.Oh($"删除菜单失败:{ex.Message}");
    
                }
    
            }

    请求测试

    可以看到公众号也就没有菜单了

    四、事件推送

    详情请看事件推送章节

    五、个性化菜单

    5.1、说明

    为了帮助公众号实现灵活的业务运营,微信公众平台新增了个性化菜单接口,开发者可以通过该接口,让公众号的不同用户群体看到不一样的自定义菜单。该接口开放给已认证订阅号和已认证服务号。

    开发者可以通过以下条件来设置用户看到的菜单:

    1. 用户标签(开发者的业务需求可以借助用户标签来完成)
    2. 性别
    3. 手机操作系统
    4. 地区(用户在微信客户端设置的地区)
    5. 语言(用户在微信客户端设置的语言)

    注意:为保护个人隐私,公众号个性化菜单将不再支持对性别、地区、语言这类涉及个人隐私数据的信息进行筛选的功能,具体调整如下:

    1. 创建时,只要匹配条件中包含隐私信息的,将被拒绝,并返回错误码 65320;
    2. 已经创建的,如包含隐私信息的则自动失效,不包含的则正常匹配;
    3. 开发者仍然可以正常通过测试接口,获取到粉丝看到的菜单;
    4. 查询个性化菜单时,所有规则正常显示。

    个性化菜单接口说明:

    1. 个性化菜单要求用户的微信客户端版本在iPhone6.2.2,Android 6.2.4以上,暂时不支持其他版本微信
    2. 菜单的刷新策略是,在用户进入公众号会话页或公众号 profile 页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果
    3. 普通公众号的个性化菜单的新增接口每日限制次数为2000次,删除接口也是2000次,测试个性化菜单匹配结果接口为20000次
    4. 出于安全考虑,一个公众号的所有个性化菜单,最多只能设置为跳转到3个域名下的链接
    5. 创建个性化菜单之前必须先创建默认菜单(默认菜单是指使用普通自定义菜单创建接口创建的菜单)。如果删除默认菜单,个性化菜单也会全部删除
    6. 个性化菜单接口支持用户标签,请开发者注意,当用户身上的标签超过1个时,以最后打上的标签为匹配

    个性化菜单匹配规则说明:

    个性化菜单的更新是会被覆盖的。 例如公众号先后发布了默认菜单,个性化菜单1,个性化菜单2,个性化菜单3。那么当用户进入公众号页面时,将从个性化菜单3开始匹配,如果个性化菜单3匹配成功,则直接返回个性化菜单3,否则继续尝试匹配个性化菜单2,直到成功匹配到一个菜单。 根据上述匹配规则,为了避免菜单生效时间的混淆,决定不予提供个性化菜单编辑API,开发者需要更新菜单时,需将完整配置重新发布一轮。 

    5.2、创建个性化菜单

    新增AddPersonalInput.cs类,用来接收前端传过来的值

    实体类内容

    namespace WeiXinApi.Application.Services
    {
        public class AddPersonalInput
        {
            /// <summary>
            /// 菜单
            /// </summary>
            public GetMenuResultFull ResultFull { get; set; }
    
            /// <summary>
            /// 规则
            /// </summary>
            public MenuMatchRule MenuMatchRule { get; set; }
        }
    }

    MenuService.cs新增接口

            /// <summary>
            /// 创建个性化菜单
            /// </summary>
            /// <param name="input"></param>
            /// <returns></returns>
            [HttpPost("/menu/addpersonal")]
            public dynamic CratePersonalMenu(AddPersonalInput input)
            {
                try
                {
                    WxJsonResult result = null;
                    var buttonGroup = CommonApi.GetMenuFromJsonResult(input.ResultFull, new ConditionalButtonGroup()).menu;
    
                    var addConditionalButtonGroup = buttonGroup as ConditionalButtonGroup;
                    addConditionalButtonGroup.matchrule = input.MenuMatchRule;
                    result = CommonApi.CreateMenuConditional(AppId, addConditionalButtonGroup);
                    var message = $"menuid:{(result as CreateMenuConditionalResult).menuid}";
                    if (result.errcode == 0)
                    {
                        return "菜单更新成功:" + message;
                    }
                    else
                    {
                        return result;
                    }
                }
                catch (Exception ex)
                {
    
                    throw Oops.Oh($"更新失败:{ex.Message}");
                }
    
            }

    启动项目测试接口,成功添加

    手机上测试看看效果

    电脑上的微信还是原来的菜单

    5.3、测试个性化菜单匹配结果

    MenuService新建接口

            /// <summary>
            /// 测试个性化菜单匹配结果
            /// </summary>
            /// <param name="user_id"></param>
            /// <returns></returns>
            [HttpPost("/menu/test")]
            public dynamic PersonalMenuTest(string user_id)
            {
                var result = CommonApi.TryMatch(AppId, user_id);
                return result;
            }

    测试一下,这里没有返回菜单,可能是因为传的userid,我没有根据用户的个性化设置,所以返回的是空的,不过这功能无关紧要,没必要纠结。

    六、本章Gitee地址链接

    https://gitee.com/huguodong520/weixinapi/tree/%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95/

  • 相关阅读:
    (转) 应用系统性能监控(二) Pinpoint 使用
    随机滚动名字和试题 单击暂停----给媳妇儿写的爱心小应用
    最短路径问题 java
    数字全排列 java深度优先搜索
    “接竹竿”纸牌游戏 java实现运算结果
    插入排序 java代码
    选择排序 java代码
    快速排序java代码
    1. Django的安装及配置
    python3.x,pycharm的安装
  • 原文地址:https://www.cnblogs.com/huguodong/p/16316790.html
Copyright © 2020-2023  润新知