123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- #region Apache License Version 2.0
- /*----------------------------------------------------------------
- Copyright 2019 Jeffrey Su & Suzhou Senparc Network Technology Co.,Ltd.
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software distributed under the
- License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- either express or implied. See the License for the specific language governing permissions
- and limitations under the License.
- Detail: https://github.com/JeffreySu/WeiXinMPSDK/blob/master/license.md
- ----------------------------------------------------------------*/
- #endregion Apache License Version 2.0
- /*----------------------------------------------------------------
- Copyright (C) 2019 Senparc
-
- 文件名:CommonApi.Menu.Custom.cs
- 文件功能描述:通用自定义菜单接口(自定义接口)
-
-
- 创建标识:Senparc - 20150211
-
- 修改标识:Senparc - 20150303
- 修改描述:整理接口
-
- 修改标识:Senparc - 20150312
- 修改描述:开放代理请求超时时间
-
- 修改标识:Senparc - 201503232
- 修改描述:修改字符串是否为空判断方式(感谢dusdong)
-
- 修改标识:Senparc - 20150703
- 修改描述:改用accessTokenOrAppId参数
- 修改标识:IsaacXu - 20151222
- 修改描述:添加CreateMenu重写方法
- 修改标识:Senparc - 20180928
- 修改描述:添加GetCurrentSelfMenuInfo方法
- ----------------------------------------------------------------*/
- /*
- API:http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html
- */
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Senparc.CO2NET.Extensions;
- using Senparc.CO2NET.HttpUtility;
- using Senparc.Weixin.Entities;
- using Senparc.Weixin.Exceptions;
- using Senparc.Weixin.MP.Entities;
- using Senparc.Weixin.MP.Entities.Menu;
- using Senparc.NeuChar;
- using System.Threading.Tasks;
- using Senparc.Weixin.CommonAPIs;
- using Senparc.CO2NET.Helpers;
- #if NET35 || NET40 || NET45
- using System.Web.Script.Serialization;
- #endif
- namespace Senparc.Weixin.MP.CommonAPIs
- {
- public partial class CommonApi
- {
- ///// <summary>
- ///// 特殊符号转义
- ///// </summary>
- ///// <param name="name"></param>
- ///// <returns></returns>
- //private static string ButtonNameEncode(string name)
- //{
- // //直接用UrlEncode不行,显示内容超长
- // return name.Replace("&", "%26");
- //}
- /// <summary>
- /// 创建菜单
- /// </summary>
- /// <param name="accessTokenOrAppId">AccessToken或AppId。当为AppId时,如果AccessToken错误将自动获取一次。当为null时,获取当前注册的第一个AppId。</param>
- /// <param name="buttonData">菜单内容</param>
- /// <param name="timeOut"></param>
- /// <returns></returns>
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.CreateMenu", true)]
- public static WxJsonResult CreateMenu(string accessTokenOrAppId, ButtonGroup buttonData, int timeOut = Config.TIME_OUT)
- {
- return ApiHandlerWapper.TryCommonApi(accessToken =>
- {
- var urlFormat = Config.ApiMpHost + "/cgi-bin/menu/create?access_token={0}";
- ////对特殊符号进行URL转义
- //foreach (var button in buttonData.button)
- //{
- // button.name = ButtonNameEncode(button.name);//button.name.UrlEncode();
- // if (button is SubButton)
- // {
- // var subButtonList = button as SubButton;
- // foreach (var subButton in subButtonList.sub_button)
- // {
- // subButton.name = ButtonNameEncode(button.name);//button.name.UrlEncode();
- // }
- // }
- //}
- return CommonJsonSend.Send<WxJsonResult>(accessToken, urlFormat, buttonData, timeOut: timeOut);
- }, accessTokenOrAppId);
- }
- /// <summary>
- /// 创建菜单
- /// </summary>
- /// <param name="accessTokenOrAppId">AccessToken或AppId。当为AppId时,如果AccessToken错误将自动获取一次。当为null时,获取当前注册的第一个AppId。</param>
- /// <param name="buttonData">菜单内容</param>
- /// <param name="timeOut"></param>
- /// <returns></returns>
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.CreateMenu", true)]
- public static WxJsonResult CreateMenu(string accessTokenOrAppId, object buttonData, int timeOut = Config.TIME_OUT)
- {
- return ApiHandlerWapper.TryCommonApi(accessToken =>
- {
- var urlFormat = Config.ApiMpHost + "/cgi-bin/menu/create?access_token={0}";
- return CommonJsonSend.Send<WxJsonResult>(accessToken, urlFormat, buttonData, timeOut: timeOut);
- }, accessTokenOrAppId);
- }
- #region GetMenu
- /// <summary>
- /// 获取单击按钮
- /// </summary>
- /// <param name="objs"></param>
- /// <returns></returns>
- [Obsolete("配合GetMenuFromJson方法使用")]
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.GetSingleButtonFromJsonObject", true)]
- private static SingleClickButton GetSingleButtonFromJsonObject(Dictionary<string, object> objs)
- {
- var sb = new SingleClickButton()
- {
- key = objs["key"] as string,
- name = objs["name"] as string,
- type = objs["type"] as string
- };
- return sb;
- }
- /// <summary>
- /// 从JSON字符串获取菜单对象
- /// </summary>
- /// <param name="jsonString"></param>
- /// <returns></returns>
- [Obsolete("此方法通过判断GetMenuResult并结合object类型转换得到结果。结果准确。但更推荐使用GetMenuFromJsonResult方法。")]
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.GetMenuFromJson", true)]
- public static GetMenuResult GetMenuFromJson(string jsonString)
- {
- var finalResult = new GetMenuResult(new ButtonGroup());
- try
- {
- //@"{""menu"":{""button"":[{""type"":""click"",""name"":""单击测试"",""key"":""OneClick"",""sub_button"":[]},{""name"":""二级菜单"",""sub_button"":[{""type"":""click"",""name"":""返回文本"",""key"":""SubClickRoot_Text"",""sub_button"":[]},{""type"":""click"",""name"":""返回图文"",""key"":""SubClickRoot_News"",""sub_button"":[]},{""type"":""click"",""name"":""返回音乐"",""key"":""SubClickRoot_Music"",""sub_button"":[]}]}]}}"
- object jsonResult = SerializerHelper.GetObject<object>(jsonString);
- var fullResult = jsonResult as Dictionary<string, object>;
- if (fullResult != null && fullResult.ContainsKey("menu"))
- {
- //得到菜单
- var menu = fullResult["menu"];
- var buttons = (menu as Dictionary<string, object>)["button"] as object[];
- foreach (var rootButton in buttons)
- {
- var fullButton = rootButton as Dictionary<string, object>;
- if (fullButton.ContainsKey("key") && !string.IsNullOrEmpty(fullButton["key"] as string))
- {
- //按钮,无下级菜单
- finalResult.menu.button.Add(GetSingleButtonFromJsonObject(fullButton));
- }
- else
- {
- //二级菜单
- var subButton = new SubButton(fullButton["name"] as string);
- finalResult.menu.button.Add(subButton);
- foreach (var sb in fullButton["sub_button"] as object[])
- {
- subButton.sub_button.Add(GetSingleButtonFromJsonObject(sb as Dictionary<string, object>));
- }
- }
- }
- }
- else if (fullResult != null && fullResult.ContainsKey("errmsg"))
- {
- //菜单不存在
- throw new ErrorJsonResultException(fullResult["errmsg"] as string, null, null);
- }
- }
- catch (ErrorJsonResultException ex)
- {
- finalResult = null;
- //如果没有惨淡会返回错误代码:46003:menu no exist
- }
- catch (Exception ex)
- {
- //其他异常
- finalResult = null;
- }
- return finalResult;
- }
- /// <summary>
- /// 获取当前菜单,如果菜单不存在,将返回null
- /// </summary>
- /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
- /// <returns></returns>
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.GetMenu", true)]
- public static GetMenuResult GetMenu(string accessTokenOrAppId)
- {
- return ApiHandlerWapper.TryCommonApi(accessToken =>
- {
- var url = string.Format(Config.ApiMpHost + "/cgi-bin/menu/get?access_token={0}", accessToken.AsUrlData());
- var jsonString = RequestUtility.HttpGet(url, Encoding.UTF8);
- //var finalResult = GetMenuFromJson(jsonString);
- GetMenuResult finalResult;
- try
- {
- #if NET35 || NET40 || NET45
- JavaScriptSerializer js = new JavaScriptSerializer();
- var jsonResult = js.Deserialize<GetMenuResultFull>(jsonString);
- #else
- var jsonResult = Newtonsoft.Json.JsonConvert.DeserializeObject<GetMenuResultFull>(jsonString);
- #endif
- if (jsonResult.menu == null || jsonResult.menu.button.Count == 0)
- {
- throw new WeixinMenuException(jsonResult.errmsg);
- }
- finalResult = GetMenuFromJsonResult(jsonResult, new ButtonGroup());
- }
- catch (WeixinMenuException)
- {
- throw;
- //finalResult = null;
- }
- catch (Exception)
- {
- throw;
- }
- return finalResult;
- }, accessTokenOrAppId);
- }
- #endregion
- /// <summary>
- /// 删除菜单
- /// </summary>
- /// <param name="accessTokenOrAppId"></param>
- /// <returns></returns>
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.DeleteMenu", true)]
- public static WxJsonResult DeleteMenu(string accessTokenOrAppId)
- {
- return ApiHandlerWapper.TryCommonApi(accessToken =>
- {
- var url = string.Format(Config.ApiMpHost + "/cgi-bin/menu/delete?access_token={0}", accessToken.AsUrlData());
- return CommonJsonSend.Send<WxJsonResult>(null, url, null, CommonJsonSendType.GET);
- }, accessTokenOrAppId);
- }
- #region 同步方法
- /// <summary>
- /// 获取自定义菜单配置接口
- /// </summary>
- /// <param name="accessTokenOrAppId"></param>
- /// <param name="timeOut"></param>
- /// <returns></returns>
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.GetCurrentSelfMenuInfo", true)]
- public static SelfMenuConfigResult GetCurrentSelfMenuInfo(string accessTokenOrAppId, int timeOut = Config.TIME_OUT)
- {
- return ApiHandlerWapper.TryCommonApi(accessToken =>
- {
- var url = string.Format(Config.ApiMpHost + "/cgi-bin/get_current_selfmenu_info?access_token={0}", accessToken.AsUrlData());
- return CommonJsonSend.Send<SelfMenuConfigResult>(null, url, null, CommonJsonSendType.GET, timeOut: timeOut);
- }, accessTokenOrAppId);
- }
- #endregion
- #if !NET35 && !NET40
- #region 异步方法
- /// <summary>
- /// 【异步方法】获取自定义菜单配置接口
- /// </summary>
- /// <param name="accessTokenOrAppId"></param>
- /// <param name="timeOut"></param>
- /// <returns></returns>
- [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.GetCurrentSelfMenuInfo", true)]
- public static async Task<SelfMenuConfigResult> GetCurrentSelfMenuInfoAsync(string accessTokenOrAppId, int timeOut = Config.TIME_OUT)
- {
- return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
- {
- var url = string.Format(Config.ApiMpHost + "/cgi-bin/get_current_selfmenu_info?access_token={0}", accessToken.AsUrlData());
-
- return await CommonJsonSend.SendAsync<SelfMenuConfigResult>(null, url, null, CommonJsonSendType.GET, timeOut: timeOut);
- }, accessTokenOrAppId);
- }
- #endregion
- #endif
- }
- }
|