ApiHandlerWapper.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. 文件名:ApiHandlerWapper.cs(v12之前原AccessTokenHandlerWapper.cs)
  17. 文件功能描述:使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试
  18. 创建标识:Senparc - 20150211
  19. 修改标识:Senparc - 20150303
  20. 修改描述:整理接口
  21. 修改标识:Senparc - 20150703
  22. 修改描述:添加TryCommonApi()方法
  23. 修改标识:Senparc - 20170102
  24. 修改描述:v14.3.116 TryCommonApi抛出ErrorJsonResultException、WeixinException异常时加入了accessTokenOrAppId参数
  25. 修改标识:Senparc - 20170123
  26. 修改描述:v14.3.121 TryCommonApiAsync方法返回代码改为return await result;避免死锁。
  27. 修改标识:Senparc - 20180917
  28. 修改描述:BaseContainer.GetFirstOrDefaultAppId() 方法添加 PlatformType 属性
  29. ----------------------------------------------------------------*/
  30. using System;
  31. using System.Threading.Tasks;
  32. using Senparc.Weixin.Entities;
  33. using Senparc.Weixin.Exceptions;
  34. using Senparc.Weixin.MP.CommonAPIs;
  35. using Senparc.Weixin.MP.Containers;
  36. using Senparc.Weixin.Utilities.WeixinUtility;
  37. using Senparc.Weixin.CommonAPIs;
  38. using Senparc.Weixin.CommonAPIs.ApiHandlerWapper;
  39. namespace Senparc.Weixin.MP
  40. {
  41. /// <summary>
  42. /// 针对AccessToken无效或过期的自动处理类
  43. /// </summary>
  44. public static class ApiHandlerWapper
  45. {
  46. #region 同步方法
  47. /// <summary>
  48. /// 使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。
  49. /// 使用此方法之前必须使用AccessTokenContainer.Register(_appId, _appSecret);或JsApiTicketContainer.Register(_appId, _appSecret);方法对账号信息进行过注册,否则会出错。
  50. /// </summary>
  51. /// <typeparam name="T"></typeparam>
  52. /// <param name="fun"></param>
  53. /// <param name="accessTokenOrAppId">AccessToken或AppId。如果为null,则自动取已经注册的第一个appId/appSecret来信息获取AccessToken。</param>
  54. /// <param name="retryIfFaild">请保留默认值true,不用输入。</param>
  55. /// <returns></returns>
  56. public static T TryCommonApi<T>(Func<string, T> fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : WxJsonResult
  57. {
  58. Func<string> accessTokenContainer_GetFirstOrDefaultAppIdFunc =
  59. () => AccessTokenContainer.GetFirstOrDefaultAppId(PlatformType.MP);
  60. Func<string, bool> accessTokenContainer_CheckRegisteredFunc =
  61. appId => AccessTokenContainer.CheckRegistered(appId);
  62. Func<string, bool, IAccessTokenResult> accessTokenContainer_GetAccessTokenResultFunc =
  63. (appId, getNewToken) => AccessTokenContainer.GetAccessTokenResult(appId, getNewToken);
  64. int invalidCredentialValue = (int)ReturnCode.获取access_token时AppSecret错误或者access_token无效;
  65. var result = ApiHandlerWapperBase.
  66. TryCommonApiBase(
  67. PlatformType.MP,
  68. accessTokenContainer_GetFirstOrDefaultAppIdFunc,
  69. accessTokenContainer_CheckRegisteredFunc,
  70. accessTokenContainer_GetAccessTokenResultFunc,
  71. invalidCredentialValue,
  72. fun, accessTokenOrAppId, retryIfFaild);
  73. return result;
  74. #region V1.0方法
  75. //ApiHandlerWapperFactory.ApiHandlerWapperFactoryCollection["s"] = ()=> new Senparc.Weixin.MP.AdvancedAPIs.User.UserInfoJson();
  76. //var platform = ApiHandlerWapperFactory.CurrentPlatform;//当前平台
  77. //string appId = null;
  78. //string accessToken = null;
  79. //if (accessTokenOrAppId == null)
  80. //{
  81. // appId = AccessTokenContainer.GetFirstOrDefaultAppId();
  82. // if (appId == null)
  83. // {
  84. // throw new UnRegisterAppIdException(null,
  85. // "尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!");
  86. // }
  87. //}
  88. //else if (ApiUtility.IsAppId(accessTokenOrAppId))
  89. //{
  90. // if (!AccessTokenContainer.CheckRegistered(accessTokenOrAppId))
  91. // {
  92. // throw new UnRegisterAppIdException(accessTokenOrAppId, string.Format("此appId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!", accessTokenOrAppId));
  93. // }
  94. // appId = accessTokenOrAppId;
  95. //}
  96. //else
  97. //{
  98. // accessToken = accessTokenOrAppId;//accessToken
  99. //}
  100. //T result = null;
  101. //try
  102. //{
  103. // if (accessToken == null)
  104. // {
  105. // var accessTokenResult = AccessTokenContainer.GetAccessTokenResult(appId, false);
  106. // accessToken = accessTokenResult.access_token;
  107. // }
  108. // result = fun(accessToken);
  109. //}
  110. //catch (ErrorJsonResultException ex)
  111. //{
  112. // if (retryIfFaild
  113. // && appId != null
  114. // && ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效)
  115. // {
  116. // //尝试重新验证
  117. // var accessTokenResult = AccessTokenContainer.GetAccessTokenResult(appId, true);
  118. // //强制获取并刷新最新的AccessToken
  119. // accessToken = accessTokenResult.access_token;
  120. // result = TryCommonApi(fun, appId, false);
  121. // }
  122. // else
  123. // {
  124. // ex.AccessTokenOrAppId = accessTokenOrAppId;
  125. // throw;
  126. // }
  127. //}
  128. //catch (WeixinException ex)
  129. //{
  130. // ex.AccessTokenOrAppId = accessTokenOrAppId;
  131. // throw;
  132. //}
  133. //return result;
  134. #endregion
  135. }
  136. #region 淘汰方法
  137. ///// 使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试
  138. ///// </summary>
  139. ///// <typeparam name="T"></typeparam>
  140. ///// <param name="appId"></param>
  141. ///// <param name="appSecret"></param>
  142. ///// <param name="fun">第一个参数为accessToken</param>
  143. ///// <param name="retryIfFaild"></param>
  144. ///// <returns></returns>
  145. //[Obsolete("请使用TryCommonApi()方法")]
  146. //public static T Do<T>(Func<string, T> fun, string appId, string appSecret, bool retryIfFaild = true)
  147. // where T : WxJsonResult
  148. //{
  149. // T result = null;
  150. // try
  151. // {
  152. // var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret, false);
  153. // result = fun(accessToken);
  154. // }
  155. // catch (ErrorJsonResultException ex)
  156. // {
  157. // if (retryIfFaild && ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效)
  158. // {
  159. // //尝试重新验证
  160. // var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret, true);
  161. // result = Do(fun, appId, appSecret, false);
  162. // }
  163. // }
  164. // return result;
  165. //}
  166. #endregion
  167. #endregion
  168. #if !NET35 && !NET40
  169. #region 异步方法
  170. /// <summary>
  171. /// 【异步方法】使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。
  172. /// 使用此方法之前必须使用AccessTokenContainer.Register(_appId, _appSecret);或JsApiTicketContainer.Register(_appId, _appSecret);方法对账号信息进行过注册,否则会出错。
  173. /// </summary>
  174. /// <typeparam name="T"></typeparam>
  175. /// <param name="fun"></param>
  176. /// <param name="accessTokenOrAppId">AccessToken或AppId。如果为null,则自动取已经注册的第一个appId/appSecret来信息获取AccessToken。</param>
  177. /// <param name="retryIfFaild">请保留默认值true,不用输入。</param>
  178. /// <returns></returns>
  179. public static async Task<T> TryCommonApiAsync<T>(Func<string, Task<T>> fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : WxJsonResult
  180. {
  181. Func<string> accessTokenContainer_GetFirstOrDefaultAppIdFunc =
  182. () => AccessTokenContainer.GetFirstOrDefaultAppId(PlatformType.MP);
  183. Func<string, bool> accessTokenContainer_CheckRegisteredFunc =
  184. appId => AccessTokenContainer.CheckRegistered(appId);
  185. Func<string, bool, Task<IAccessTokenResult>> accessTokenContainer_GetAccessTokenResultAsyncFunc =
  186. (appId, getNewToken) => AccessTokenContainer.GetAccessTokenResultAsync(appId, getNewToken);
  187. int invalidCredentialValue = (int)ReturnCode.获取access_token时AppSecret错误或者access_token无效;
  188. var result = ApiHandlerWapperBase.
  189. TryCommonApiBaseAsync(
  190. PlatformType.MP,
  191. accessTokenContainer_GetFirstOrDefaultAppIdFunc,
  192. accessTokenContainer_CheckRegisteredFunc,
  193. accessTokenContainer_GetAccessTokenResultAsyncFunc,
  194. invalidCredentialValue,
  195. fun, accessTokenOrAppId, retryIfFaild);
  196. return await result;
  197. }
  198. #region 淘汰方法
  199. ///// <summary>
  200. ///// 【异步方法】使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试
  201. ///// </summary>
  202. ///// <typeparam name="T"></typeparam>
  203. ///// <param name="appId"></param>
  204. ///// <param name="appSecret"></param>
  205. ///// <param name="fun">第一个参数为accessToken</param>
  206. ///// <param name="retryIfFaild"></param>
  207. ///// <returns></returns>
  208. //[Obsolete("请使用TryCommonApiAsync()方法")]
  209. //public static async Task<T> DoAsync<T>(Func<string, Task<T>> fun, string appId, string appSecret, bool retryIfFaild = true)
  210. // where T : WxJsonResult
  211. //{
  212. // T result = null;
  213. // try
  214. // {
  215. // var accessToken = await AccessTokenContainer.TryGetAccessTokenAsync(appId, appSecret, false);
  216. // result = fun(accessToken).Result;
  217. // }
  218. // catch (ErrorJsonResultException ex)
  219. // {
  220. // if (retryIfFaild && ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效)
  221. // {
  222. // //尝试重新验证
  223. // var accessToken = AccessTokenContainer.TryGetAccessTokenAsync(appId, appSecret, true);
  224. // result = DoAsync(fun, appId, appSecret, false).Result;
  225. // }
  226. // }
  227. // return result;
  228. //}
  229. #endregion
  230. #endregion
  231. #endif
  232. }
  233. }