Example #1
0
        /// <summary>
        /// 发送 Get 请求, 返回结果对象;如遇 access_token 超时错误, 会自动获取新的 access_token 并重试
        /// </summary>
        /// <typeparam name="T">结果对象类型</typeparam>
        /// <param name="url">接口网址, 里边的 $acac$ 会被自动替换成 access_token=xxx </param>
        /// <param name="config"></param>
        /// <exception cref="ApiException">返回的 JSON 字符串中包含了错误信息</exception>
        public static async Task <T> GetResult <T>(string url, ApiConfig config = null)
            where T : IApiResult
        {
            var token = new AsyncOutParameter <string>();

            try
            {
                var text = await GetStringWithToken(url, config, token).ConfigureAwait(false);

                return(BuildResult <T>(text, config));
            }
            catch (ApiException ex)
            {
                if (ex.Code == ErrorAccessTokenExpired || ex.Code == ErrorAccessTokenInvalid)
                {
                    var m = config?.AccessTokenManager ?? _defaultConfig.AccessTokenManager;
                    await m.RefreshTokenInfo(token.Value).ConfigureAwait(false);

                    var text = await GetString(url, config).ConfigureAwait(false);

                    return(BuildResult <T>(text, config));
                }

                throw;
            }
        }
Example #2
0
        /// <summary>
        /// 调用接口
        /// </summary>
        /// <param name="outcoming">请求参数</param>
        /// <param name="stream">正常情况下返回的数据流, 内容是 CSV 格式的数据</param>
        /// <param name="incoming">出错时的返回结果</param>
        /// <returns>正常情况: true, 出错时: false</returns>
        public async Task <bool> Invoke(Outcoming outcoming, AsyncOutParameter <Stream> stream, AsyncOutParameter <Incoming> incoming)
        {
            var url      = Stage.GetApiRootUrl(_sandbox) + "pay/downloadbill";
            var response = await _requester.GetResponse(url, false, outcoming).ConfigureAwait(false);

            var netStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

            var peekStream = new PeekableStream(netStream, 1);
            var buffer     = new byte[1];
            await peekStream.PeekAsync(buffer, 0, 1).ConfigureAwait(false);

            if (buffer[0] != '<')
            {
                stream.SetValue(peekStream);
                return(true);
            }

            using (var reader = new StreamReader(peekStream, Encoding.UTF8))
            {
                var responseBody = await reader.ReadToEndAsync().ConfigureAwait(false);

                incoming.SetValue(_requester.ParseResponse <Incoming, ErrorCode>(responseBody, _checkSignature));
                return(false);
            }
        }
Example #3
0
        /// <summary>
        /// 上传文件, 并检查返回结果是否用错误;如遇 access_token 超时错误, 会自动获取新的 access_token 并重试
        /// </summary>
        /// <param name="url">接口网址, 里边的 $acac$ 会被自动替换成 access_token=xxx </param>
        /// <param name="fieldName">文件字段名称</param>
        /// <param name="fileName">文件名</param>
        /// <param name="fileStream">文件内容流</param>
        /// <param name="additionalFields">要在 POST 内容中发送的其它字段</param>
        /// <param name="config"></param>
        /// <exception cref="ApiException">返回的 JSON 字符串中包含了错误信息</exception>
        public static async Task UploadVoid(string url, string fieldName, string fileName, Stream fileStream, KeyValuePair <string, string>[] additionalFields = null, ApiConfig config = null)
        {
            var token = new AsyncOutParameter <string>();

            try
            {
                var text = await UploadStringWithToken(url, fieldName, fileName, fileStream, additionalFields, config, token).ConfigureAwait(false);

                BuildVoid(text, config);
            }
            catch (ApiException ex)
            {
                if (ex.Code == ErrorAccessTokenExpired || ex.Code == ErrorAccessTokenInvalid)
                {
                    var m = config?.AccessTokenManager ?? _defaultConfig.AccessTokenManager;
                    await m.RefreshTokenInfo(token.Value).ConfigureAwait(false);

                    var text = await UploadString(url, fieldName, fileName, fileStream, additionalFields, config).ConfigureAwait(false);

                    BuildVoid(text, config);
                    return;
                }

                throw;
            }
        }
Example #4
0
        /// <summary>
        /// 发送 Post 请求, 并检查返回结果是否用错误;如遇 access_token 超时错误, 会自动获取新的 access_token 并重试
        /// </summary>
        /// <param name="url">接口网址, 里边的 $acac$ 会被自动替换成 access_token=xxx </param>
        /// <param name="data">将会转换为 JSON 格式作为 Post 请求的正文内容</param>
        /// <param name="config"></param>
        /// <exception cref="ApiException">返回的 JSON 字符串中包含了错误信息</exception>
        public static async Task PostVoid(string url, object data, ApiConfig config = null)
        {
            var token = new AsyncOutParameter <string>();

            try
            {
                var text = await PostStringWithToken(url, data, config, token).ConfigureAwait(false);

                BuildVoid(text, config);
            }
            catch (ApiException ex)
            {
                if (ex.Code == ErrorAccessTokenExpired || ex.Code == ErrorAccessTokenInvalid)
                {
                    var m = config?.AccessTokenManager ?? _defaultConfig.AccessTokenManager;
                    await m.RefreshTokenInfo(token.Value).ConfigureAwait(false);

                    var text = await PostString(url, data, config).ConfigureAwait(false);

                    BuildVoid(text, config);
                    return;
                }

                throw;
            }
        }
 public static void SetValue <T>(this AsyncOutParameter <T> parameter, T value)
 {
     if (parameter != null)
     {
         parameter.Value = value;
     }
 }
Example #6
0
        private static async Task <string> FormatUrl(string url, ApiConfig config, AsyncOutParameter <string> token)
        {
            if (url.IndexOf("$acac$", StringComparison.InvariantCulture) < 0)
            {
                return(url);
            }

            var m           = config?.AccessTokenManager ?? _defaultConfig.AccessTokenManager;
            var accessToken = await m.GetToken().ConfigureAwait(false);

            var escapedToken = Uri.EscapeDataString(accessToken);

            token.SetValue(accessToken);

            return(url.Replace("$acac$", "access_token=" + escapedToken));
        }
Example #7
0
        private static async Task <Stream> GetStreamWithToken(string url, ApiConfig config, AsyncOutParameter <string> token)
        {
            url = await FormatUrl(url, config, token).ConfigureAwait(false);

            var http = config?.HttpClient ?? _defaultConfig.HttpClient;

            return(await http.GetStreamAsync(url).ConfigureAwait(false));
        }
Example #8
0
        private static async Task <string> GetStringWithToken(string url, ApiConfig config, AsyncOutParameter <string> token)
        {
            var stream = await GetStreamWithToken(url, config, token).ConfigureAwait(false);

            using (var reader = new StreamReader(stream, Encoding.UTF8))
            {
                return(await reader.ReadToEndAsync().ConfigureAwait(false));
            }
        }
Example #9
0
        private static async Task <string> UploadStringWithToken(string url, string fieldName, string fileName, Stream fileStream, KeyValuePair <string, string>[] additionalFields, ApiConfig config, AsyncOutParameter <string> token)
        {
            var content = BuildUploadContent(fieldName, fileName, fileStream, additionalFields);

            url = await FormatUrl(url, config, token).ConfigureAwait(false);

            var http = config?.HttpClient ?? _defaultConfig.HttpClient;

            var response = await http.PostAsync(url, content).ConfigureAwait(false);

            return(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
        }
Example #10
0
        private static async Task <Stream> PostStreamWithToken(string url, object data, ApiConfig config, AsyncOutParameter <string> token)
        {
            url = await FormatUrl(url, config, token).ConfigureAwait(false);

            var parser = config?.JsonParser ?? _defaultConfig.JsonParser;
            var body   = parser.ToString(data);

            var http     = config?.HttpClient ?? _defaultConfig.HttpClient;
            var response = await http.PostAsync(url, new StringContent(body)).ConfigureAwait(false);

            return(await response.Content.ReadAsStreamAsync().ConfigureAwait(false));
        }
Example #11
0
        /// <summary>
        /// 发送 Get 请求, 返回流
        /// </summary>
        /// <param name="url">网址</param>
        /// <param name="config"></param>
        /// <returns></returns>
        public static async Task <Stream> GetStream(string url, ApiConfig config = null)
        {
            var token = new AsyncOutParameter <string>();
            var ms    = new MemoryStream();

            try
            {
                using (var s = await GetStreamWithToken(url, config, token).ConfigureAwait(false))
                {
                    await s.CopyToAsync(ms).ConfigureAwait(false);

                    //估计错误消息应该不会大于400字节
                    if (ms.Length < 400)
                    {
                        var buffer = ms.ToArray();
                        var text   = Encoding.UTF8.GetString(buffer);

                        if (Regex.IsMatch(text, @"^\s*{"))
                        {
                            //如果是失败消息, 这里会抛出异常
                            BuildVoid(text, config);
                        }
                    }

                    ms.Position = 0;
                    return(ms);
                }
            }
            catch (ApiException ex)
            {
                if (ex.Code == ErrorAccessTokenExpired || ex.Code == ErrorAccessTokenInvalid)
                {
                    ms.SetLength(0);

                    var m = config?.AccessTokenManager ?? _defaultConfig.AccessTokenManager;
                    await m.RefreshTokenInfo(token.Value).ConfigureAwait(false);

                    using (var s = await GetStreamWithToken(url, config, null).ConfigureAwait(false))
                    {
                        await s.CopyToAsync(ms).ConfigureAwait(false);

                        //估计错误消息应该不会大于400字节
                        if (ms.Length < 400)
                        {
                            var buffer = ms.ToArray();
                            var text   = Encoding.UTF8.GetString(buffer);

                            if (Regex.IsMatch(text, @"^\s*{"))
                            {
                                //如果是失败消息, 这里会抛出异常
                                BuildVoid(text, config);
                            }
                        }

                        ms.Position = 0;
                        return(ms);
                    }
                }

                throw;
            }
        }