public static AccessTokenResult GetToken(string appid, string secret, string grant_type = "client_credential") { //注意:此方法不能再使用ApiHandlerWapper.TryCommonApi(),否则会循环 var url = string.Format(Config.ApiMpHost + "/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", grant_type.AsUrlData(), appid.AsUrlData(), secret.AsUrlData()); AccessTokenResult result = Get.GetJson <AccessTokenResult>(url);//此处为最原始接口,不再使用重试获取的封装 if (Config.ThrownWhenJsonResultFaild && result.errcode != ReturnCode.请求成功) { var unregisterAppIdEx = new UnRegisterAppIdException(null, $"尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!模块:{NeuChar.PlatformType.WeChat_OfficialAccount}"); throw unregisterAppIdEx;//抛出异常 } return(result); }
public static AccessTokenResult GetToken(string corpId, string corpSecret) { #region 主动调用的频率限制 /* * 当你获取到AccessToken时,你的应用就可以成功调用企业号后台所提供的各种接口以管理或访问企业号后台的资源或给企业号成员发消息。 * * 为了防止企业应用的程序错误而引发企业号服务器负载异常,默认情况下,每个企业号调用接口都有一定的频率限制,当超过此限制时,调用对应接口会收到相应错误码。 * * 以下是当前默认的频率限制,企业号后台可能会根据运营情况调整此阈值: * * 基础频率 * 每企业调用单个cgi/api不可超过1000次/分,30000次/小时 * * 每ip调用单个cgi/api不可超过2000次/分,60000次/小时 * * 每ip获取AccessToken不可超过300次/小时 * * 发消息频率 * 每企业不可超过200次/分钟;不可超过帐号上限数*30人次/天 * * 创建帐号频率 * 每企业创建帐号数不可超过帐号上限数*3/月 */ #endregion var url = string.Format(Config.ApiWorkHost + "/cgi-bin/gettoken?corpid={0}&corpsecret={1}", corpId.AsUrlData(), corpSecret.AsUrlData()); var result = CommonJsonSend.Send <AccessTokenResult>(null, url, null, CommonJsonSendType.GET); if (Config.ThrownWhenJsonResultFaild && result.errcode != ReturnCode_Work.请求成功) { var unregisterAppIdEx = new UnRegisterAppIdException(null, $"尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!模块:{NeuChar.PlatformType.WeChat_Work}"); throw unregisterAppIdEx;//抛出异常 } return(result); }
/// <summary> /// TryCommonApi 方法的基类 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="platformType">平台类型,PlatformType枚举</param> /// <param name="accessTokenContainer_GetFirstOrDefaultAppIdAsyncFunc">AccessTokenContainer中的GetFirstOrDefaultAppId()方法</param> /// <param name="accessTokenContainer_CheckRegisteredAsyncFunc">AccessTokenContainer中的bool CheckRegistered(appId,getNew)方法</param> /// <param name="accessTokenContainer_GetAccessTokenResultAsyncFunc">AccessTokenContainer中的AccessTokenResult GetAccessTokenResultAsync(appId)方法(异步方法)</param> /// <param name="invalidCredentialValue">"ReturnCode.获取access_token时AppSecret错误或者access_token无效"枚举的值</param> /// <param name="fun"></param> /// <param name="accessTokenOrAppId">公众号、小程序中的 AppId,或企业微信中的 AppKey(由AppId+AppSecret组成)</param> /// <param name="retryIfFaild"></param> /// <returns></returns> public static async Task <T> TryCommonApiBaseAsync <T>( PlatformType platformType, Func <Task <string> > accessTokenContainer_GetFirstOrDefaultAppIdAsyncFunc, Func <string, Task <bool> > accessTokenContainer_CheckRegisteredAsyncFunc, Func <string, bool, Task <IAccessTokenResult> > accessTokenContainer_GetAccessTokenResultAsyncFunc, int invalidCredentialValue, Func <string, Task <T> > fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : BaseJsonResult, new() { //ApiHandlerWapperFactory.ApiHandlerWapperFactoryCollection["s"] = ()=> new Senparc.Weixin.MP.AdvancedAPIs.User.UserInfoJson(); //var platform = ApiHandlerWapperFactory.CurrentPlatform;//当前平台 string appId = null; string accessToken = null; if (accessTokenOrAppId == null) { appId = await accessTokenContainer_GetFirstOrDefaultAppIdAsyncFunc().ConfigureAwait(false);// AccessTokenContainer.GetFirstOrDefaultAppId(); if (appId == null) { var unregisterAppIdEx = new UnRegisterAppIdException(null, $"尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!模块:{platformType}"); if (Config.ThrownWhenJsonResultFaild) { throw unregisterAppIdEx;//抛出异常 } else { return(GetConfigErrorResult <T>(unregisterAppIdEx.Message));//返回 Json 错误结果 } } } else if (ApiUtility.IsAppId(accessTokenOrAppId, platformType)) { //if (!AccessTokenContainer.CheckRegistered(accessTokenOrAppId)) if (!await accessTokenContainer_CheckRegisteredAsyncFunc(accessTokenOrAppId)) { var unregisterAppIdEx = new UnRegisterAppIdException(null, $"此appId({accessTokenOrAppId})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!模块:{platformType}"); if (Config.ThrownWhenJsonResultFaild) { throw unregisterAppIdEx;//抛出异常 } else { return(GetConfigErrorResult <T>(unregisterAppIdEx.Message));//返回 Json 错误结果 } } appId = accessTokenOrAppId; } else { accessToken = accessTokenOrAppId; //accessToken } T result = null; try { if (accessToken == null) { var accessTokenResult = await accessTokenContainer_GetAccessTokenResultAsyncFunc(appId, false);//AccessTokenContainer.GetAccessTokenResultAsync(appId, false); accessToken = accessTokenResult.access_token; } result = await fun(accessToken).ConfigureAwait(false); //当系统不抛出异常,且当前返回结果不成功,且允许重试的时候,在内部抛出一个异常,以便进行 Retry if (!Config.ThrownWhenJsonResultFaild && result is WxJsonResult && (result as WxJsonResult).errcode != ReturnCode.请求成功 && retryIfFaild ) { var errorResult = result as WxJsonResult; throw new ErrorJsonResultException( string.Format("微信请求发生错误!错误代码:{0},说明:{1}", (int)errorResult.errcode, errorResult.errmsg), null, errorResult); } } catch (ErrorJsonResultException ex) { if (retryIfFaild && appId != null //如果 appId 为 null,已经没有重试的意义(直接提供的 AccessToken 是错误的) //&& ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效) && (int)ex.JsonResult.errcode == invalidCredentialValue) { //尝试重新验证(如果是低版本VS,此处不能使用await关键字,可以直接使用xx.Result输出。VS2013不支持:无法在 catch 字句体中等待) var accessTokenResult = await accessTokenContainer_GetAccessTokenResultAsyncFunc(appId, true).ConfigureAwait(false);//AccessTokenContainer.GetAccessTokenResultAsync(appId, true); //强制获取并刷新最新的AccessToken accessToken = accessTokenResult.access_token; result = await TryCommonApiBaseAsync(platformType, accessTokenContainer_GetFirstOrDefaultAppIdAsyncFunc, accessTokenContainer_CheckRegisteredAsyncFunc, accessTokenContainer_GetAccessTokenResultAsyncFunc, invalidCredentialValue, fun, accessToken, false).ConfigureAwait(false); //result = TryCommonApiAsync(fun, appId, false); } else { //如果要求抛出异常,并且传入的是 AccessToken(AppId 为 null),那么已经没有必要重试,直接抛出异常 if (Config.ThrownWhenJsonResultFaild && appId == null) { throw;//抛出异常 } else { return(GetJsonErrorResult <T>(ex.JsonResult));//返回 Json 错误结果 } } } catch (WeixinException ex) { ex.AccessTokenOrAppId = accessTokenOrAppId; //判断如果传进来的是 AccessToken,并且不抛出异常,那么这里不throw if (Config.ThrownWhenJsonResultFaild && ApiUtility.IsAppId(accessTokenOrAppId, platformType)) { throw;//抛出异常 } else { return(GetConfigErrorResult <T>(ex.Message));//返回 Json 错误结果 } } return(result); }