CommonApi.Menu.Common.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. #region Apache License Version 2.0
  2. /*----------------------------------------------------------------
  3. Copyright 2019 Jeffrey Su & Suzhou Senparc Network Technology Co.,Ltd.
  4. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5. except in compliance with the License. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software distributed under the
  8. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  9. either express or implied. See the License for the specific language governing permissions
  10. and limitations under the License.
  11. Detail: https://github.com/JeffreySu/WeiXinMPSDK/blob/master/license.md
  12. ----------------------------------------------------------------*/
  13. #endregion Apache License Version 2.0
  14. /*----------------------------------------------------------------
  15. Copyright (C) 2019 Senparc
  16. 文件名:CommonApi.Menu.Common.cs
  17. 文件功能描述:通用自定义菜单接口(公共方法)
  18. 创建标识:Senparc - 20150211
  19. 修改标识:Senparc - 20150303
  20. 修改描述:整理接口
  21. 修改标识:Senparc - 20150312
  22. 修改描述:开放代理请求超时时间
  23. 修改标识:Senparc - 201503232
  24. 修改描述:修改字符串是否为空判断方式(感谢dusdong)
  25. 修改标识:Senparc - 20150703
  26. 修改描述:改用accessTokenOrAppId参数
  27. 修改标识:IsaacXu - 20151222
  28. 修改描述:添加CreateMenu重写方法
  29. 修改标识:IsaacXu - 20170328
  30. 修改描述:添加小程序按钮
  31. 修改标识:Senparc - 20170419
  32. 修改描述:v14.3.143 修复上一版本造成的菜单获取错误问题
  33. 修改标识:Senparc - 20170419
  34. 修改描述:v14.4.13 修复二级菜单小程序无法设置的问题
  35. ----------------------------------------------------------------*/
  36. /*
  37. API:http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html
  38. */
  39. using System;
  40. using System.Collections.Generic;
  41. using System.Linq;
  42. using System.Text;
  43. using Senparc.NeuChar;
  44. using Senparc.Weixin.Entities;
  45. using Senparc.Weixin.Exceptions;
  46. using Senparc.Weixin.HttpUtility;
  47. using Senparc.Weixin.MP.Entities;
  48. using Senparc.Weixin.MP.Entities.Menu;
  49. namespace Senparc.Weixin.MP.CommonAPIs
  50. {
  51. public partial class CommonApi
  52. {
  53. /// <summary>
  54. /// 从rootButtonList获取buttonGroup
  55. /// </summary>
  56. /// <param name="rootButtonList"></param>
  57. /// <param name="buttonGroup"></param>
  58. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.GetButtonGroup", true)]
  59. private static void GetButtonGroup(List<MenuFull_RootButton> rootButtonList, ButtonGroupBase buttonGroup)
  60. {
  61. foreach (var rootButton in rootButtonList)
  62. {
  63. if (rootButton == null || string.IsNullOrEmpty(rootButton.name))
  64. {
  65. continue; //没有设置一级菜单
  66. }
  67. var availableSubButton = rootButton.sub_button == null
  68. ? 0
  69. : rootButton.sub_button.Count(z => z != null && !string.IsNullOrEmpty(z.name)); //可用二级菜单按钮数量
  70. if (availableSubButton == 0)
  71. {
  72. //底部单击按钮
  73. if (rootButton.type == null ||
  74. (rootButton.type.Equals("CLICK", StringComparison.OrdinalIgnoreCase)
  75. && string.IsNullOrEmpty(rootButton.key)))
  76. {
  77. throw new WeixinMenuException("单击按钮的key不能为空!");
  78. }
  79. if (rootButton.type.Equals("CLICK", StringComparison.OrdinalIgnoreCase))
  80. {
  81. //点击
  82. buttonGroup.button.Add(new SingleClickButton()
  83. {
  84. name = rootButton.name,
  85. key = rootButton.key,
  86. type = rootButton.type
  87. });
  88. }
  89. else if (rootButton.type.Equals("VIEW", StringComparison.OrdinalIgnoreCase))
  90. {
  91. //URL
  92. buttonGroup.button.Add(new SingleViewButton()
  93. {
  94. name = rootButton.name,
  95. url = rootButton.url,
  96. type = rootButton.type
  97. });
  98. }
  99. else if (rootButton.type.Equals("MINIPROGRAM", StringComparison.OrdinalIgnoreCase))
  100. {
  101. //小程序
  102. buttonGroup.button.Add(new SingleMiniProgramButton()
  103. {
  104. name = rootButton.name,
  105. url = rootButton.url,
  106. appid = rootButton.appid,
  107. pagepath = rootButton.pagepath,
  108. type = rootButton.type
  109. });
  110. }
  111. else if (rootButton.type.Equals("LOCATION_SELECT", StringComparison.OrdinalIgnoreCase))
  112. {
  113. //弹出地理位置选择器
  114. buttonGroup.button.Add(new SingleLocationSelectButton()
  115. {
  116. name = rootButton.name,
  117. key = rootButton.key,
  118. type = rootButton.type
  119. });
  120. }
  121. else if (rootButton.type.Equals("PIC_PHOTO_OR_ALBUM", StringComparison.OrdinalIgnoreCase))
  122. {
  123. //弹出拍照或者相册发图
  124. buttonGroup.button.Add(new SinglePicPhotoOrAlbumButton()
  125. {
  126. name = rootButton.name,
  127. key = rootButton.key,
  128. type = rootButton.type
  129. });
  130. }
  131. else if (rootButton.type.Equals("PIC_SYSPHOTO", StringComparison.OrdinalIgnoreCase))
  132. {
  133. //弹出系统拍照发图
  134. buttonGroup.button.Add(new SinglePicSysphotoButton()
  135. {
  136. name = rootButton.name,
  137. key = rootButton.key,
  138. type = rootButton.type
  139. });
  140. }
  141. else if (rootButton.type.Equals("PIC_WEIXIN", StringComparison.OrdinalIgnoreCase))
  142. {
  143. //弹出微信相册发图器
  144. buttonGroup.button.Add(new SinglePicWeixinButton()
  145. {
  146. name = rootButton.name,
  147. key = rootButton.key,
  148. type = rootButton.type
  149. });
  150. }
  151. else if (rootButton.type.Equals("SCANCODE_PUSH", StringComparison.OrdinalIgnoreCase))
  152. {
  153. //扫码推事件
  154. buttonGroup.button.Add(new SingleScancodePushButton()
  155. {
  156. name = rootButton.name,
  157. key = rootButton.key,
  158. type = rootButton.type
  159. });
  160. }
  161. else if (rootButton.type.Equals("SCANCODE_WAITMSG", StringComparison.OrdinalIgnoreCase))
  162. {
  163. //扫码推事件且弹出“消息接收中”提示框
  164. buttonGroup.button.Add(new SingleScancodeWaitmsgButton()
  165. {
  166. name = rootButton.name,
  167. key = rootButton.key,
  168. type = rootButton.type
  169. });
  170. }
  171. else if (rootButton.type.Equals("MEDIA_ID", StringComparison.OrdinalIgnoreCase))
  172. {
  173. //扫码推事件
  174. buttonGroup.button.Add(new SingleMediaIdButton()
  175. {
  176. name = rootButton.name,
  177. media_id = rootButton.media_id,
  178. type = rootButton.type
  179. });
  180. }
  181. else if (rootButton.type.Equals("VIEW_LIMITED", StringComparison.OrdinalIgnoreCase))
  182. {
  183. //扫码推事件
  184. buttonGroup.button.Add(new SingleViewLimitedButton()
  185. {
  186. name = rootButton.name,
  187. media_id = rootButton.media_id,
  188. type = rootButton.type
  189. });
  190. }
  191. else
  192. {
  193. throw new WeixinMenuException("菜单类型无法处理:" + rootButton.type);
  194. }
  195. }
  196. //else if (availableSubButton < 2)
  197. //{
  198. // throw new WeixinMenuException("子菜单至少需要填写2个!");
  199. //}
  200. else
  201. {
  202. //底部二级菜单
  203. var subButton = new SubButton(rootButton.name);
  204. buttonGroup.button.Add(subButton);
  205. foreach (var subSubButton in rootButton.sub_button)
  206. {
  207. if (subSubButton == null || string.IsNullOrEmpty(subSubButton.name))
  208. {
  209. continue; //没有设置菜单
  210. }
  211. if (subSubButton.type.Equals("CLICK", StringComparison.OrdinalIgnoreCase)
  212. && string.IsNullOrEmpty(subSubButton.key))
  213. {
  214. throw new WeixinMenuException("单击按钮的key不能为空!");
  215. }
  216. if (subSubButton.type.Equals("CLICK", StringComparison.OrdinalIgnoreCase))
  217. {
  218. //点击
  219. subButton.sub_button.Add(new SingleClickButton()
  220. {
  221. name = subSubButton.name,
  222. key = subSubButton.key,
  223. type = subSubButton.type
  224. });
  225. }
  226. else if (subSubButton.type.Equals("VIEW", StringComparison.OrdinalIgnoreCase))
  227. {
  228. //URL
  229. subButton.sub_button.Add(new SingleViewButton()
  230. {
  231. name = subSubButton.name,
  232. url = subSubButton.url,
  233. type = subSubButton.type
  234. });
  235. }
  236. else if (subSubButton.type.Equals("MINIPROGRAM", StringComparison.OrdinalIgnoreCase))
  237. {
  238. //小程序
  239. subButton.sub_button.Add(new SingleMiniProgramButton()
  240. {
  241. name = subSubButton.name,
  242. url = subSubButton.url,
  243. appid = subSubButton.appid,
  244. pagepath = subSubButton.pagepath,
  245. type = subSubButton.type
  246. });
  247. }
  248. else if (subSubButton.type.Equals("LOCATION_SELECT", StringComparison.OrdinalIgnoreCase))
  249. {
  250. //弹出地理位置选择器
  251. subButton.sub_button.Add(new SingleLocationSelectButton()
  252. {
  253. name = subSubButton.name,
  254. key = subSubButton.key,
  255. type = subSubButton.type
  256. });
  257. }
  258. else if (subSubButton.type.Equals("PIC_PHOTO_OR_ALBUM", StringComparison.OrdinalIgnoreCase))
  259. {
  260. //弹出拍照或者相册发图
  261. subButton.sub_button.Add(new SinglePicPhotoOrAlbumButton()
  262. {
  263. name = subSubButton.name,
  264. key = subSubButton.key,
  265. type = subSubButton.type
  266. });
  267. }
  268. else if (subSubButton.type.Equals("PIC_SYSPHOTO", StringComparison.OrdinalIgnoreCase))
  269. {
  270. //弹出系统拍照发图
  271. subButton.sub_button.Add(new SinglePicSysphotoButton()
  272. {
  273. name = subSubButton.name,
  274. key = subSubButton.key,
  275. type = subSubButton.type
  276. });
  277. }
  278. else if (subSubButton.type.Equals("PIC_WEIXIN", StringComparison.OrdinalIgnoreCase))
  279. {
  280. //弹出微信相册发图器
  281. subButton.sub_button.Add(new SinglePicWeixinButton()
  282. {
  283. name = subSubButton.name,
  284. key = subSubButton.key,
  285. type = subSubButton.type
  286. });
  287. }
  288. else if (subSubButton.type.Equals("SCANCODE_PUSH", StringComparison.OrdinalIgnoreCase))
  289. {
  290. //扫码推事件
  291. subButton.sub_button.Add(new SingleScancodePushButton()
  292. {
  293. name = subSubButton.name,
  294. key = subSubButton.key,
  295. type = subSubButton.type
  296. });
  297. }
  298. else if (subSubButton.type.Equals("MEDIA_ID", StringComparison.OrdinalIgnoreCase))
  299. {
  300. //扫码推事件
  301. subButton.sub_button.Add(new SingleMediaIdButton()
  302. {
  303. name = subSubButton.name,
  304. media_id = subSubButton.media_id,
  305. type = subSubButton.type
  306. });
  307. }
  308. else if (subSubButton.type.Equals("VIEW_LIMITED", StringComparison.OrdinalIgnoreCase))
  309. {
  310. //扫码推事件
  311. subButton.sub_button.Add(new SingleViewLimitedButton()
  312. {
  313. name = subSubButton.name,
  314. media_id = subSubButton.media_id,
  315. type = subSubButton.type
  316. });
  317. }
  318. else
  319. {
  320. //扫码推事件且弹出“消息接收中”提示框
  321. subButton.sub_button.Add(new SingleScancodeWaitmsgButton()
  322. {
  323. name = subSubButton.name,
  324. key = subSubButton.key,
  325. type = subSubButton.type
  326. });
  327. }
  328. }
  329. }
  330. }
  331. }
  332. /// <summary>
  333. /// 根据微信返回的Json数据得到可用的GetMenuResult结果
  334. /// </summary>
  335. /// <param name="resultFull"></param>
  336. /// <param name="buttonGroupBase">ButtonGroupBase的衍生类型,可以为ButtonGroup或ConditionalButtonGroup。返回的GetMenuResult中的menu属性即为此示例。</param>
  337. /// <returns></returns>
  338. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "CommonApi.GetMenuFromJsonResult", true)]
  339. public static GetMenuResult GetMenuFromJsonResult(GetMenuResultFull resultFull, ButtonGroupBase buttonGroupBase)
  340. {
  341. GetMenuResult result = null;
  342. if (buttonGroupBase == null)
  343. {
  344. throw new ArgumentNullException("buttonGroupBase不可以为空!");
  345. }
  346. try
  347. {
  348. //重新整理按钮信息
  349. ButtonGroupBase buttonGroup = buttonGroupBase; // ?? new ButtonGroup();
  350. var rootButtonList = resultFull.menu.button;
  351. GetButtonGroup(rootButtonList, buttonGroup);//设置默认菜单
  352. result = new GetMenuResult(buttonGroupBase)
  353. {
  354. menu = buttonGroup,
  355. //conditionalmenu = resultFull.conditionalmenu
  356. };
  357. //设置个性化菜单列表
  358. if (resultFull.conditionalmenu != null)
  359. {
  360. var conditionalMenuList = new List<ConditionalButtonGroup>();
  361. foreach (var conditionalMenu in resultFull.conditionalmenu)
  362. {
  363. var conditionalButtonGroup = new ConditionalButtonGroup();
  364. //fix bug 16030701 https://github.com/JeffreySu/WeiXinMPSDK/issues/169
  365. conditionalButtonGroup.matchrule = conditionalMenu.matchrule;
  366. conditionalButtonGroup.menuid = conditionalMenu.menuid;
  367. //fix bug 16030701 end
  368. GetButtonGroup(conditionalMenu.button, conditionalButtonGroup);//设置默认菜单
  369. conditionalMenuList.Add(conditionalButtonGroup);
  370. }
  371. result.conditionalmenu = conditionalMenuList;
  372. }
  373. }
  374. catch (Exception ex)
  375. {
  376. throw new WeixinMenuException(ex.Message, ex);
  377. }
  378. return result;
  379. }
  380. }
  381. }