///// 使用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));
        }
Example #2
0
        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);
        }
Example #3
0
        /// <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
                });
            }
        }
Example #4
0
        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));
        }
Example #5
0
        /// <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);
        }
Example #6
0
        /// <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);
        }
Example #7
0
        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);
            }
        }
Example #8
0
        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);
            }
        }
Example #9
0
        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);
        }
Example #10
0
        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]);
        }
Example #11
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);
        }
Example #12
0
        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);
            }
        }
Example #13
0
        ///// 使用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);
        }