///// 使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试 ///// </summary> ///// <typeparam name="T"></typeparam> ///// <param name="appId"></param> ///// <param name="appSecret"></param> ///// <param name="fun">第一个参数为accessToken</param> ///// <param name="retryIfFaild"></param> ///// <returns></returns> //[Obsolete("请使用TryCommonApi()方法")] //public static T Do<T>(Func<string, T> fun, string appId, string appSecret, bool retryIfFaild = true) // where T : WxJsonResult //{ // T result = null; // try // { // var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret, false); // result = fun(accessToken); // } // catch (ErrorJsonResultException ex) // { // if (retryIfFaild && ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效) // { // //尝试重新验证 // var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret, true); // result = Do(fun, appId, appSecret, false); // } // } // return result; //} #endregion #endregion #region 异步方法 /// <summary> /// 【异步方法】使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。 /// 使用此方法之前必须使用AccessTokenContainer.Register(_appId, _appSecret);或JsApiTicketContainer.Register(_appId, _appSecret);方法对账号信息进行过注册,否则会出错。 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fun"></param> /// <param name="accessTokenOrAppId">AccessToken或AppId。如果为null,则自动取已经注册的第一个appId/appSecret来信息获取AccessToken。</param> /// <param name="retryIfFaild">请保留默认值true,不用输入。</param> /// <returns></returns> public static async Task <T> TryCommonApiAsync <T>(Func <string, Task <T> > fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : WxJsonResult, new() { Func <Task <string> > accessTokenContainer_GetFirstOrDefaultAppIdAsyncFunc = async() => await AccessTokenContainer.GetFirstOrDefaultAppIdAsync(PlatformType.MP).ConfigureAwait(false); Func <string, Task <bool> > accessTokenContainer_CheckRegisteredAsyncFunc = async appId => await AccessTokenContainer.CheckRegisteredAsync(appId).ConfigureAwait(false); Func <string, bool, Task <IAccessTokenResult> > accessTokenContainer_GetAccessTokenResultAsyncFunc = (appId, getNewToken) => AccessTokenContainer.GetAccessTokenResultAsync(appId, getNewToken); int invalidCredentialValue = (int)ReturnCode.获取access_token时AppSecret错误或者access_token无效; var result = ApiHandlerWapperBase. TryCommonApiBaseAsync( PlatformType.MP, accessTokenContainer_GetFirstOrDefaultAppIdAsyncFunc, accessTokenContainer_CheckRegisteredAsyncFunc, accessTokenContainer_GetAccessTokenResultAsyncFunc, invalidCredentialValue, fun, accessTokenOrAppId, retryIfFaild); return(await result.ConfigureAwait(false)); }
public void GetTokenResultAsyncTest() { //注册 AccessTokenContainer.Register(base._appId, base._appSecret); //模拟多线程获取 List <string> accessTokenList = new List <string>(); int threadsCount = 5; //数字不易过大,否则超过微信允许同一个客户端同时并发数量,将可能看不到效果 int round = 10; //测试多少轮 //同步 TimeSpan syncTime = new TimeSpan(); var dt1 = SystemTime.Now; for (int j = 0; j < round; j++) { Console.WriteLine("同步第{0}轮", j + 1); Parallel.For(0, threadsCount, (i) => { var dts = SystemTime.Now; var accessTokenResult = AccessTokenContainer.GetAccessTokenResult(base._appId, true); var dte = SystemTime.Now; accessTokenList.Add(accessTokenResult.access_token);//同时多次获取 Console.WriteLine("{0}同步线程耗时:{1}ms", i, (dte - dts).TotalMilliseconds); syncTime = syncTime.Add((dte - dts)); //Console.WriteLine(accessTokenResult.access_token); }); } var dt2 = SystemTime.Now; Console.WriteLine("线程用时总和:{0}ms", syncTime.TotalMilliseconds); Console.WriteLine("{0}线程{1}轮同步时间:{2}ms", threadsCount, round, (dt2 - dt1).TotalMilliseconds); Console.WriteLine("================="); //异步 TimeSpan asyncTime = new TimeSpan(); var dt3 = SystemTime.Now; for (int j = 0; j < round; j++) { Console.WriteLine("异步第{0}轮", j + 1); Parallel.For(0, threadsCount, (i) => { var dts = SystemTime.Now; var accessTokenResult = AccessTokenContainer.GetAccessTokenResultAsync(base._appId, true).Result; var dte = SystemTime.Now; accessTokenList.Add(accessTokenResult.access_token); //同时多次获取 Console.WriteLine("{0}异步线程耗时:{1}ms", i, (dte - dts).TotalMilliseconds); asyncTime = syncTime.Add((dte - dts)); //Console.WriteLine(accessTokenResult.access_token); }); } var dt4 = SystemTime.Now; Console.WriteLine("线程用时总和:{0}ms", asyncTime.TotalMilliseconds); Console.WriteLine("{0}个线程{1}轮异步时间:{2}ms", threadsCount, round, (dt4 - dt3).TotalMilliseconds); }
/// <summary> /// 接口调用access_token。统一管理access_token,防止滥用; /// </summary> /// <param name="appId"></param> /// <returns></returns> public async Task <object> GetAccessTokenAsync(string appId) { try { var ret = (Senparc.Weixin.MP.Entities.AccessTokenResult) await AccessTokenContainer.GetAccessTokenResultAsync(appId); if (ret.errcode == ReturnCode.请求成功) { return(new { ret.access_token, ret.expires_in }); } else { return(new { ret.errcode, ret.errmsg }); } } catch (Exception ex) { return(new { errcode = "获取Token出错", ex.Message }); } }
public async Task <object> GetMenus(string appId) { var token = await AccessTokenContainer.GetAccessTokenResultAsync(appId); var url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=" + token.access_token; return(Get.GetJson <object>(url)); }
/// <summary> /// 异步方法】使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。 /// 使用此方法之前必须使用AccessTokenContainer.Register(_clientId, _clientSecret); /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fun"></param> /// <param name="requestPolicy"></param> /// <param name="retryIfFaild"></param> /// <returns></returns> public static async Task <T> TryCommonApiAsync <T>( Func <Com.Alibaba.Entities.Request.RequestPolicy, Task <T> > fun, Com.Alibaba.Entities.Request.RequestPolicy requestPolicy, bool retryIfFaild = true) where T : AliJsonResult { if (string.IsNullOrEmpty(requestPolicy.ClientId)) { requestPolicy.ClientId = AccessTokenContainer.GetFirstOrDefaultClientId(); if (string.IsNullOrEmpty(requestPolicy.ClientId)) { throw new UnRegisterClientIdException(null, "尚无已经注册的ClientId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!"); } } else { if (!AccessTokenContainer.CheckRegistered(requestPolicy.ClientId)) { throw new UnRegisterClientIdException(requestPolicy.ClientId, string.Format("此clientId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!", requestPolicy.ClientId)); } } Task <T> result = null; try { if (string.IsNullOrEmpty(requestPolicy.AccessToken)) { var accessTokenResult = await AccessTokenContainer.GetAccessTokenResultAsync(requestPolicy.ClientId, false, requestPolicy.SessionType, requestPolicy.RequestSchema); requestPolicy.AccessToken = accessTokenResult.access_token; } result = fun(requestPolicy); } catch (ErrorJsonResultException ex) { if (retryIfFaild && !string.IsNullOrEmpty(requestPolicy.ClientId) && (ex.JsonResult.code > 0 || !string.IsNullOrEmpty(ex.JsonResult.errorCode))) { //尝试重新验证 //var accessTokenResult = AccessTokenContainer.GetAccessTokenResultAsync(clientId, true, sessionType); var accessTokenResult = AccessTokenContainer.RefreshAccessTokenResultAsync(requestPolicy.ClientId, requestPolicy.SessionType, requestPolicy.RequestSchema); //强制获取并刷新最新的AccessToken requestPolicy.AccessToken = accessTokenResult.Result.access_token; result = TryCommonApiAsync(fun, requestPolicy, false); } else { throw; } } return(await result); }
/// <summary> /// 【异步方法】使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。 /// 使用此方法之前必须使用AccessTokenContainer.Register(_clientId, _clientSecret); /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fun"></param> /// <param name="accessTokenOrClientId">AccessToken或ClientId。如果为null,则自动取已经注册的第一个clientId/appSecret来信息获取AccessToken。</param> /// <param name="retryIfFaild">请保留默认值true,不用输入。</param> /// <returns></returns> public static async Task <T> TryCommonApiAsync <T>(Func <string, Task <T> > fun, string clientId = null, string accessToken = null, SessionType sessionType = SessionType.Prod, bool retryIfFaild = true) where T : WishJsonResult { if (clientId == null) { clientId = AccessTokenContainer.GetFirstOrDefaultClientId(); if (clientId == null) { throw new UnRegisterClientIdException(null, "尚无已经注册的ClientId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!"); } } else { if (!AccessTokenContainer.CheckRegistered(clientId)) { throw new UnRegisterClientIdException(clientId, string.Format("此clientId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!", clientId)); } } Task <T> result = null; try { if (accessToken == null) { var accessTokenResult = await AccessTokenContainer.GetAccessTokenResultAsync(clientId, false, sessionType); accessToken = accessTokenResult.data.access_token; } result = fun(accessToken); } catch (ErrorJsonResultException ex) { if (retryIfFaild && clientId != null && ex.JsonResult.code > 0) { //尝试重新验证 //var accessTokenResult = AccessTokenContainer.GetAccessTokenResultAsync(clientId, true, sessionType); var accessTokenResult = AccessTokenContainer.RefreshAccessTokenResultAsync(clientId, sessionType); //强制获取并刷新最新的AccessToken accessToken = accessTokenResult.Result.data.access_token; result = TryCommonApiAsync(fun, clientId, accessToken, sessionType, false); } else { throw; } } return(await result); }
public void ContainerAsyncTest() { //注册 AccessTokenContainer.Register(base._appId, base._appSecret); //获取Token完整结果(包括当前过期秒数) DateTime dt1 = DateTime.Now; var tokenResult = AccessTokenContainer.GetAccessTokenResultAsync(base._appId).Result; DateTime dt2 = DateTime.Now; Assert.IsNotNull(tokenResult); Console.WriteLine(tokenResult.access_token); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); //只获取Token字符串 dt1 = DateTime.Now; var token = AccessTokenContainer.GetAccessTokenAsync(base._appId).Result; dt2 = DateTime.Now; Assert.AreEqual(tokenResult.access_token, token); Console.WriteLine(tokenResult.access_token); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); //getNewToken { dt1 = DateTime.Now; token = AccessTokenContainer.TryGetAccessTokenAsync(base._appId, base._appSecret, false).Result; dt2 = DateTime.Now; Assert.AreEqual(tokenResult.access_token, token); Console.WriteLine(tokenResult.access_token); Console.WriteLine("强制重新获取AccessToken"); dt1 = DateTime.Now; token = AccessTokenContainer.TryGetAccessTokenAsync(base._appId, base._appSecret, true).Result; dt2 = DateTime.Now; Assert.AreNotEqual(tokenResult.access_token, token);//如果微信服务器缓存,此处会相同 Console.WriteLine(tokenResult.access_token); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); } { tokenResult = AccessTokenContainer.GetAccessTokenResultAsync(base._appId).Result; Console.WriteLine("HashCode:{0}", tokenResult.GetHashCode()); dt1 = DateTime.Now; var allItems = AccessTokenContainer.GetAllItems(); dt2 = DateTime.Now; Assert.IsTrue(allItems.Count > 0); Assert.AreSame(tokenResult, allItems[0].AccessTokenResult);//证明缓存成功 Console.WriteLine("All Items:{0}", allItems.Count); Console.WriteLine("HashCode:{0}", allItems[0].AccessTokenResult.GetHashCode()); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); } }
public async Task <object> MatchMenus(string appId, string openIdPara) { using (var ms = new MemoryStream()) { var bytes = Encoding.UTF8.GetBytes(openIdPara); ms.Write(bytes, 0, bytes.Length); ms.Seek(0, SeekOrigin.Begin); var token = await AccessTokenContainer.GetAccessTokenResultAsync(appId); var url = "https://api.weixin.qq.com/cgi-bin/menu/trymatch?access_token=" + token.access_token; var result = Post.PostGetJson <object>(url, null, ms); return(result); } }
public async Task <object> GetMPAccessToken(string appId, string appsecret) { MPAccessTokenInfo result = new MPAccessTokenInfo(); try { DateTime dateTime = DateTime.Now; var accessTokenResult = await AccessTokenContainer.GetAccessTokenResultAsync(_options.Value.AppId); var accessTokenBag = BaseContainer <AccessTokenBag> .TryGetItem(_options.Value.AppId); result.access_token = accessTokenResult.access_token; DateTime expireTime = accessTokenBag.AccessTokenExpireTime.DateTime; result.expires_in = (long)(expireTime - dateTime).TotalSeconds; } catch (Exception ex) { throw ex; } return(result); }
public void GetTokenResultTest() { //注册 AccessTokenContainer.Register(base._appId, base._appSecret); //模拟多线程获取 List <string> accessTokenList = new List <string>(); int[] threads = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var accessTokenResultInit = AccessTokenContainer.GetAccessTokenResult(base._appId, false);//先获取一次 Parallel.For(0, threads.Length, (i) => { var accessTokenResult = AccessTokenContainer.GetAccessTokenResultAsync(base._appId, false).Result; accessTokenList.Add(accessTokenResult.access_token);//同时多次获取 Console.WriteLine(accessTokenResult.access_token); }); Assert.AreEqual(threads.Length, accessTokenList.Count()); //只存在同一个Token,实际不会多次刷新 Assert.AreEqual(1, accessTokenList.Distinct().Count()); //只存在同一个Token,实际不会多次刷新 Console.WriteLine(accessTokenList[0]); }
/// <summary> /// 【异步方法】使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。 /// 使用此方法之前必须使用AccessTokenContainer.Register(_appId, _appSecret);或JsApiTicketContainer.Register(_appId, _appSecret);方法对账号信息进行过注册,否则会出错。 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fun"></param> /// <param name="accessTokenOrAppId">AccessToken或AppId。如果为null,则自动取已经注册的第一个appId/appSecret来信息获取AccessToken。</param> /// <param name="retryIfFaild">请保留默认值true,不用输入。</param> /// <returns></returns> public static async Task <T> TryCommonApiAsync <T>(Func <string, Task <T> > fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : WxOpenJsonResult { Func <string> accessTokenContainer_GetFirstOrDefaultAppIdFunc = () => AccessTokenContainer.GetFirstOrDefaultAppId(PlatformType.WeChat_MiniProgram); Func <string, bool> accessTokenContainer_CheckRegisteredFunc = appId => AccessTokenContainer.CheckRegistered(appId); Func <string, bool, Task <IAccessTokenResult> > accessTokenContainer_GetAccessTokenResultAsyncFunc = (appId, getNewToken) => AccessTokenContainer.GetAccessTokenResultAsync(appId, getNewToken); int invalidCredentialValue = (int)ReturnCode.获取access_token时AppSecret错误或者access_token无效; var result = ApiHandlerWapperBase. TryCommonApiBaseAsync( PlatformType.WeChat_OfficialAccount, accessTokenContainer_GetFirstOrDefaultAppIdFunc, accessTokenContainer_CheckRegisteredFunc, accessTokenContainer_GetAccessTokenResultAsyncFunc, invalidCredentialValue, fun, accessTokenOrAppId, retryIfFaild); return(await result); }
public void ContainerAsyncTest() { bool useRedis = true; if (useRedis) { var redisConfiguration = "localhost:6379"; RedisManager.ConfigurationOption = redisConfiguration; CacheStrategyFactory.RegisterObjectCacheStrategy(() => RedisObjectCacheStrategy.Instance);//Redis } //注册 AccessTokenContainer.Register(base._appId, base._appSecret); //获取Token完整结果(包括当前过期秒数) var dt1 = SystemTime.Now; var tokenResult = AccessTokenContainer.GetAccessTokenResultAsync(base._appId).Result; var dt2 = SystemTime.Now; Assert.IsNotNull(tokenResult); Console.WriteLine(tokenResult.access_token); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); //只获取Token字符串 dt1 = SystemTime.Now; var token = AccessTokenContainer.GetAccessTokenAsync(base._appId).Result; dt2 = SystemTime.Now; Assert.AreEqual(tokenResult.access_token, token); Console.WriteLine(tokenResult.access_token); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); //getNewToken { dt1 = SystemTime.Now; token = AccessTokenContainer.TryGetAccessTokenAsync(base._appId, base._appSecret, false).Result; dt2 = SystemTime.Now; Assert.AreEqual(tokenResult.access_token, token); Console.WriteLine(tokenResult.access_token); Console.WriteLine("强制重新获取AccessToken"); dt1 = SystemTime.Now; token = AccessTokenContainer.TryGetAccessTokenAsync(base._appId, base._appSecret, true).Result; dt2 = SystemTime.Now; Assert.AreNotEqual(tokenResult.access_token, token);//如果微信服务器缓存,此处会相同 Console.WriteLine(tokenResult.access_token); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); } { tokenResult = AccessTokenContainer.GetAccessTokenResultAsync(base._appId).Result; Console.WriteLine("HashCode:{0}", tokenResult.GetHashCode()); dt1 = SystemTime.Now; var allItems = AccessTokenContainer.GetAllItems(); dt2 = SystemTime.Now; Assert.IsTrue(allItems.Count > 0); Assert.AreSame(tokenResult, allItems[0].AccessTokenResult);//证明缓存成功 Console.WriteLine("All Items:{0}", allItems.Count); Console.WriteLine("HashCode:{0}", allItems[0].AccessTokenResult.GetHashCode()); Console.WriteLine("耗时:{0}毫秒", (dt2 - dt1).TotalMilliseconds); } }
///// 使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试 ///// </summary> ///// <typeparam name="T"></typeparam> ///// <param name="appId"></param> ///// <param name="appSecret"></param> ///// <param name="fun">第一个参数为accessToken</param> ///// <param name="retryIfFaild"></param> ///// <returns></returns> //[Obsolete("请使用TryCommonApi()方法")] //public static T Do<T>(Func<string, T> fun, string appId, string appSecret, bool retryIfFaild = true) // where T : WxJsonResult //{ // T result = null; // try // { // var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret, false); // result = fun(accessToken); // } // catch (ErrorJsonResultException ex) // { // if (retryIfFaild && ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效) // { // //尝试重新验证 // var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret, true); // result = Do(fun, appId, appSecret, false); // } // } // return result; //} #endregion #endregion #region 异步方法 /// <summary> /// 【异步方法】使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。 /// 使用此方法之前必须使用AccessTokenContainer.Register(_appId, _appSecret);或JsApiTicketContainer.Register(_appId, _appSecret);方法对账号信息进行过注册,否则会出错。 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fun"></param> /// <param name="accessTokenOrAppId">AccessToken或AppId。如果为null,则自动取已经注册的第一个appId/appSecret来信息获取AccessToken。</param> /// <param name="retryIfFaild">请保留默认值true,不用输入。</param> /// <returns></returns> public static async Task <T> TryCommonApiAsync <T>(Func <string, Task <T> > fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : WxJsonResult { string appId = null; string accessToken = null; if (accessTokenOrAppId == null) { appId = AccessTokenContainer.GetFirstOrDefaultAppId(); if (appId == null) { throw new UnRegisterAppIdException(null, "尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!"); } } else if (ApiUtility.IsAppId(accessTokenOrAppId)) { if (!AccessTokenContainer.CheckRegistered(accessTokenOrAppId)) { throw new UnRegisterAppIdException(accessTokenOrAppId, string.Format("此appId({0})尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!", accessTokenOrAppId)); } appId = accessTokenOrAppId; } else { accessToken = accessTokenOrAppId; //accessToken } Task <T> result = null; try { if (accessToken == null) { var accessTokenResult = await AccessTokenContainer.GetAccessTokenResultAsync(appId, false); accessToken = accessTokenResult.access_token; } result = fun(accessToken); } catch (ErrorJsonResultException ex) { if (retryIfFaild && appId != null && ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效) { //尝试重新验证 var accessTokenResult = AccessTokenContainer.GetAccessTokenResultAsync(appId, true); //强制获取并刷新最新的AccessToken accessToken = accessTokenResult.Result.access_token; result = TryCommonApiAsync(fun, appId, false); } else { throw; } } return(await result); }