ApiHandlerWapperBase.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. 文件名:ApiHandlerWapperBase.cs
  17. 文件功能描述:提供ApiHandlerWapper的公共基础方法
  18. 创建标识:Senparc - 20170702
  19. 修改标识:Senparc - 201700704
  20. 修改描述:优化TryCommonApiBaseAsync方法
  21. 修改标识:Senparc - 20170730
  22. 修改描述:v4.13.5 完善AppId未注册提示
  23. 修改标识:Senparc - 20181027
  24. 修改描述:v6.1.10 改进 TryCommonApiBase 方法
  25. ----------------------------------------------------------------*/
  26. using System;
  27. using System.Collections.Generic;
  28. using System.Linq;
  29. using System.Text;
  30. using System.Threading.Tasks;
  31. using Senparc.Weixin.Entities;
  32. using Senparc.Weixin.Exceptions;
  33. using Senparc.Weixin.Utilities.WeixinUtility;
  34. namespace Senparc.Weixin.CommonAPIs.ApiHandlerWapper
  35. {
  36. /// <summary>
  37. /// 所有子模块ApiHandlerWapper方法调用的基础方法
  38. /// </summary>
  39. public class ApiHandlerWapperBase
  40. {
  41. #region 同步方法
  42. /// <summary>
  43. /// TryCommonApi 方法的基类
  44. /// </summary>
  45. /// <typeparam name="T"></typeparam>
  46. /// <param name="platformType">平台类型,PlatformType枚举</param>
  47. /// <param name="accessTokenContainer_GetFirstOrDefaultAppIdFunc">AccessTokenContainer中的GetFirstOrDefaultAppId()方法</param>
  48. /// <param name="accessTokenContainer_CheckRegisteredFunc">AccessTokenContainer中的bool CheckRegistered(appId,getNew)方法</param>
  49. /// <param name="accessTokenContainer_GetAccessTokenResultFunc">AccessTokenContainer中的AccessTokenResult GetAccessTokenResult(appId)方法</param>
  50. /// <param name="invalidCredentialValue">"ReturnCode.获取access_token时AppSecret错误或者access_token无效"枚举的值</param>
  51. /// <param name="fun"></param>
  52. /// <param name="accessTokenOrAppId"></param>
  53. /// <param name="retryIfFaild"></param>
  54. /// <returns></returns>
  55. public static T TryCommonApiBase<T>(
  56. PlatformType platformType,
  57. Func<string> accessTokenContainer_GetFirstOrDefaultAppIdFunc,
  58. Func<string, bool> accessTokenContainer_CheckRegisteredFunc,
  59. Func<string, bool, IAccessTokenResult> accessTokenContainer_GetAccessTokenResultFunc,
  60. int invalidCredentialValue,
  61. Func<string, T> fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : BaseJsonResult
  62. {
  63. //ApiHandlerWapperFactory.ApiHandlerWapperFactoryCollection["s"] = ()=> new Senparc.Weixin.MP.AdvancedAPIs.User.UserInfoJson();
  64. //var platform = ApiHandlerWapperFactory.CurrentPlatform;//当前平台
  65. /*
  66. * 对于企业微信来说,AppId = key = CorpId+CorpSecret
  67. */
  68. string appId = null;
  69. string accessToken = null;
  70. if (accessTokenOrAppId == null)
  71. {
  72. appId = accessTokenContainer_GetFirstOrDefaultAppIdFunc != null ? accessTokenContainer_GetFirstOrDefaultAppIdFunc() : null;// AccessTokenContainer.GetFirstOrDefaultAppId();
  73. if (appId == null)
  74. {
  75. throw new UnRegisterAppIdException(null,
  76. "尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!模块:" + platformType);
  77. }
  78. }
  79. else if (ApiUtility.IsAppId(accessTokenOrAppId, platformType))
  80. {
  81. //if (!AccessTokenContainer.CheckRegistered(accessTokenOrAppId))
  82. if (!accessTokenContainer_CheckRegisteredFunc(accessTokenOrAppId))
  83. {
  84. throw new UnRegisterAppIdException(accessTokenOrAppId, string.Format("此appId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!模块:" + platformType, accessTokenOrAppId));
  85. }
  86. appId = accessTokenOrAppId;
  87. }
  88. else
  89. {
  90. accessToken = accessTokenOrAppId;//accessToken
  91. }
  92. T result = null;
  93. try
  94. {
  95. if (accessToken == null)
  96. {
  97. var accessTokenResult = accessTokenContainer_GetAccessTokenResultFunc(appId, false); //AccessTokenContainer.GetAccessTokenResult(appId, false);
  98. accessToken = accessTokenResult.access_token;
  99. }
  100. result = fun(accessToken);
  101. }
  102. catch (ErrorJsonResultException ex)
  103. {
  104. if (retryIfFaild
  105. && appId != null //如果 appId 为 null,已经没有重试的意义(直接提供的 AccessToken 是错误的)
  106. //&& ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效)
  107. && (int)ex.JsonResult.errcode == invalidCredentialValue)
  108. {
  109. //尝试重新验证
  110. var accessTokenResult = accessTokenContainer_GetAccessTokenResultFunc(appId, true);//AccessTokenContainer.GetAccessTokenResult(appId, true);
  111. //强制获取并刷新最新的AccessToken
  112. accessToken = accessTokenResult.access_token;
  113. result = TryCommonApiBase(platformType,
  114. accessTokenContainer_GetFirstOrDefaultAppIdFunc,
  115. accessTokenContainer_CheckRegisteredFunc,
  116. accessTokenContainer_GetAccessTokenResultFunc,
  117. invalidCredentialValue,
  118. fun, accessToken, false);
  119. }
  120. else
  121. {
  122. ex.AccessTokenOrAppId = accessTokenOrAppId;
  123. throw;
  124. }
  125. }
  126. catch (WeixinException ex)
  127. {
  128. ex.AccessTokenOrAppId = accessTokenOrAppId;
  129. throw;
  130. }
  131. return result;
  132. }
  133. #endregion
  134. #if !NET35 && !NET40
  135. #region 异步方法
  136. /// <summary>
  137. /// TryCommonApi 方法的基类
  138. /// </summary>
  139. /// <typeparam name="T"></typeparam>
  140. /// <param name="platformType">平台类型,PlatformType枚举</param>
  141. /// <param name="accessTokenContainer_GetFirstOrDefaultAppIdFunc">AccessTokenContainer中的GetFirstOrDefaultAppId()方法</param>
  142. /// <param name="accessTokenContainer_CheckRegisteredFunc">AccessTokenContainer中的bool CheckRegistered(appId,getNew)方法</param>
  143. /// <param name="accessTokenContainer_GetAccessTokenResultAsyncFunc">AccessTokenContainer中的AccessTokenResult GetAccessTokenResultAsync(appId)方法(异步方法)</param>
  144. /// <param name="invalidCredentialValue">"ReturnCode.获取access_token时AppSecret错误或者access_token无效"枚举的值</param>
  145. /// <param name="fun"></param>
  146. /// <param name="accessTokenOrAppId"></param>
  147. /// <param name="retryIfFaild"></param>
  148. /// <returns></returns>
  149. public static async Task<T> TryCommonApiBaseAsync<T>(
  150. PlatformType platformType,
  151. Func<string> accessTokenContainer_GetFirstOrDefaultAppIdFunc,
  152. Func<string, bool> accessTokenContainer_CheckRegisteredFunc,
  153. Func<string, bool, Task<IAccessTokenResult>> accessTokenContainer_GetAccessTokenResultAsyncFunc,
  154. int invalidCredentialValue,
  155. Func<string, Task<T>> fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : BaseJsonResult
  156. {
  157. //ApiHandlerWapperFactory.ApiHandlerWapperFactoryCollection["s"] = ()=> new Senparc.Weixin.MP.AdvancedAPIs.User.UserInfoJson();
  158. //var platform = ApiHandlerWapperFactory.CurrentPlatform;//当前平台
  159. string appId = null;
  160. string accessToken = null;
  161. if (accessTokenOrAppId == null)
  162. {
  163. appId = accessTokenContainer_GetFirstOrDefaultAppIdFunc();// AccessTokenContainer.GetFirstOrDefaultAppId();
  164. if (appId == null)
  165. {
  166. throw new UnRegisterAppIdException(null,
  167. "尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!");
  168. }
  169. }
  170. else if (ApiUtility.IsAppId(accessTokenOrAppId, platformType))
  171. {
  172. //if (!AccessTokenContainer.CheckRegistered(accessTokenOrAppId))
  173. if (!accessTokenContainer_CheckRegisteredFunc(accessTokenOrAppId))
  174. {
  175. throw new UnRegisterAppIdException(accessTokenOrAppId,
  176. string.Format("此appId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!",
  177. accessTokenOrAppId));
  178. }
  179. appId = accessTokenOrAppId;
  180. }
  181. else
  182. {
  183. accessToken = accessTokenOrAppId; //accessToken
  184. }
  185. T result = null;
  186. try
  187. {
  188. if (accessToken == null)
  189. {
  190. var accessTokenResult = await accessTokenContainer_GetAccessTokenResultAsyncFunc(appId, false);//AccessTokenContainer.GetAccessTokenResultAsync(appId, false);
  191. accessToken = accessTokenResult.access_token;
  192. }
  193. result = await fun(accessToken);
  194. }
  195. catch (ErrorJsonResultException ex)
  196. {
  197. if (retryIfFaild
  198. && appId != null //如果 appId 为 null,已经没有重试的意义(直接提供的 AccessToken 是错误的)
  199. //&& ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效)
  200. && (int)ex.JsonResult.errcode == invalidCredentialValue)
  201. {
  202. //尝试重新验证(如果是低版本VS,此处不能使用await关键字,可以直接使用xx.Result输出。VS2013不支持:无法在 catch 字句体中等待)
  203. var accessTokenResult = await accessTokenContainer_GetAccessTokenResultAsyncFunc(appId, true);//AccessTokenContainer.GetAccessTokenResultAsync(appId, true);
  204. //强制获取并刷新最新的AccessToken
  205. accessToken = accessTokenResult.access_token;
  206. result = await TryCommonApiBaseAsync(platformType,
  207. accessTokenContainer_GetFirstOrDefaultAppIdFunc,
  208. accessTokenContainer_CheckRegisteredFunc,
  209. accessTokenContainer_GetAccessTokenResultAsyncFunc,
  210. invalidCredentialValue,
  211. fun, appId, false);
  212. //result = TryCommonApiAsync(fun, appId, false);
  213. }
  214. else
  215. {
  216. throw;
  217. }
  218. }
  219. return result;
  220. }
  221. #endregion
  222. #endif
  223. }
  224. }