internal async Task <ApiResponse> MakeApiRequestAsync(string pathAndQuery, ApiRequestMethod method) { ApiResponse result = CreateResponse(pathAndQuery, method); try { HttpResponseMessage responseMessage; switch (method) { case ApiRequestMethod.DELETE: responseMessage = await this.client.DeleteAsync(result.RequestUri); break; default: responseMessage = await this.client.GetAsync(result.RequestUri); break; } await result.SetResponseAsync(responseMessage); } catch (OperationCanceledException) { throw; } catch (Exception ex) { result.WebError = ex; } return(result); }
internal ApiResponse(Uri url, ApiRequestMethod method, string content, HttpContent httpContent) { this.RequestUri = url; this.RequestMethod = method; this.RequestContent = content; this.RequestHttpContent = httpContent; }
public void ListAll() { requestMethod = ApiRequestMethod.GET; response = client.MakeApiRequestAsync("/Api/values?All=list", requestMethod); result = response.Result; models = result.Deserialize <CalculationResultModel>(); Assert.IsNotNull(models); }
/// <summary> /// 自动绑定属性 /// </summary> /// <param name="category">目录(平台类型),用于输出 API 的 Url 时分组</param> /// <param name="name">平台内唯一名称(如使用 PlatformType.General,请使用宇宙唯一名称)</param> /// <param name="apiRequestMethod">当前 API 请求的类型,如果为 null,则使用本次引擎全局定义的 </param> /// <param name="baseApiControllerType">ApiController 的基类,默认为 ControllerBase</param> /// <param name="baseApiControllerOrder">ApiController 的基类排序,最后会使用数字最大的一个(支持负数)</param> public ApiBindAttribute(string category, string name, ApiRequestMethod apiRequestMethod, Type baseApiControllerType, short baseApiControllerOrder) { Category = category; Name = name; ApiRequestMethod = apiRequestMethod; BaseApiControllerType = baseApiControllerType; BaseApiControllerOrder = baseApiControllerOrder; }
public void Sum33_33_66() { requestMethod = ApiRequestMethod.GET; response = client.MakeApiRequestAsync("/Api/values?a=22&b=22", requestMethod); result = response.Result; model = result.Deserialize <CalculationResultItemModel>(); Assert.IsNotNull(model); Assert.AreEqual(44, model.Result); }
protected HttpMethod GetHttpMethod(ApiRequestMethod requestMethod) { return(requestMethod switch { ApiRequestMethod.GET => HttpMethod.Get, ApiRequestMethod.POST => HttpMethod.Post, ApiRequestMethod.PUT => HttpMethod.Put, ApiRequestMethod.PATCH => HttpMethod.Patch, ApiRequestMethod.DELETE => HttpMethod.Delete, _ => throw new ArgumentOutOfRangeException(nameof(requestMethod)), });
public void Delete() { int Id = 36; string resultD = ""; requestMethod = ApiRequestMethod.DELETE; response = client.MakeApiRequestAsync("/Api/values?Id=" + Id, requestMethod); result = response.Result; resultD = result.Deserialize <string>(); Assert.IsNotNull(resultD); Assert.AreEqual("Delete by Id = " + Id, resultD); }
/// <param name="defaultRequestMethod">默认请求方式(全局默认为 Post)</param> /// <param name="baseApiControllerType">全局 ApiController 的基类,默认为 ControllerBase</param> /// <param name="taskCount">同时执行线程数</param> /// <param name="showDetailApiLog">是否在控制台输出详细 API 创建日志</param> /// <param name="copyCustomAttributes">是否复制自定义特性</param> /// <param name="defaultAction">默认请求类型,如 Post,Get</param> /// <param name="additionalAttributeFunc">额外需要绑定的特性</param> /// <param name="forbiddenExternalAccess">是否允许外部访问,默认为 false,只允许本机访问自动生成的 WebApi</param> /// <param name="addApiControllerAttribute">知否在自动生成的接口类(Controller)上自动添加 [ApiController] 标签</param> public WebApiEngineOptions(string docXmlPath = null, ApiRequestMethod defaultRequestMethod = ApiRequestMethod.Post, Type baseApiControllerType = null, bool copyCustomAttributes = true, int taskCount = 4, bool showDetailApiLog = false, Func <MethodInfo, IEnumerable <CustomAttributeBuilder> > additionalAttributeFunc = null, bool forbiddenExternalAccess = true, bool addApiControllerAttribute = true) { DocXmlPath = docXmlPath; DefaultRequestMethod = defaultRequestMethod; BaseApiControllerType = baseApiControllerType; CopyCustomAttributes = copyCustomAttributes; TaskCount = taskCount; ShowDetailApiLog = showDetailApiLog; AdditionalAttributeFunc = additionalAttributeFunc; ForbiddenExternalAccess = forbiddenExternalAccess; AddApiControllerAttribute = addApiControllerAttribute; }
/// <summary> /// 通过 ApiRequestMethod 枚举获取对应的 Http 请求特性 /// </summary> /// <param name="apiRequestMethod"></param> /// <returns></returns> private Type GetRequestMethodAttribute(ApiRequestMethod apiRequestMethod) { return(apiRequestMethod switch { ApiRequestMethod.GlobalDefault => throw new CO2NET.Exceptions.HttpException($"{nameof(ApiRequestMethod.GlobalDefault)} 不是有效的请求类型"), ApiRequestMethod.Get => typeof(HttpGetAttribute), ApiRequestMethod.Head => typeof(HttpHeadAttribute), ApiRequestMethod.Post => typeof(HttpPostAttribute), ApiRequestMethod.Put => typeof(HttpPutAttribute), ApiRequestMethod.Delete => typeof(HttpDeleteAttribute), ApiRequestMethod.Options => typeof(HttpOptionsAttribute), ApiRequestMethod.Patch => typeof(HttpPatchAttribute), _ => typeof(HttpPostAttribute),//默认都使用 Post });
/// <summary> /// WebApiEngine /// </summary> /// <param name="options"> WebApiEngine 配置</param> public WebApiEngine(Action <WebApiEngineOptions> options = null) { WebApiEngineOptions opt = new(); options?.Invoke(opt); _ = opt.DefaultRequestMethod == ApiRequestMethod.GlobalDefault ? throw new Exception($"{nameof(opt.DefaultRequestMethod)} 不能作为默认请求类型!") : true; DocXmlPath = opt.DocXmlPath; _findWeixinApiService = new Lazy <FindApiService>(new FindApiService()); _defaultRequestMethod = opt.DefaultRequestMethod; _baseApiControllerType = opt.BaseApiControllerType ?? typeof(ControllerBase); _copyCustomAttributes = opt.CopyCustomAttributes; TaskCount = opt.TaskCount; _showDetailApiLog = opt.ShowDetailApiLog; _addApiControllerAttribute = opt.AddApiControllerAttribute; Register.ForbiddenExternalAccess = opt.ForbiddenExternalAccess; WebApiEngine.AdditionalAttributeFunc = opt.AdditionalAttributeFunc; }
/// <summary> /// 获取 HttpResponseMessage 对象 /// </summary> /// <param name="url"></param> /// <param name="data">如果为 GET 请求,此参数可为 null</param> /// <param name="timeOut"></param> /// <param name="requestMethod"></param> /// <param name="checkDataNotNull">非 GET 请求情况下,是否强制检查 data 参数不能为 null,默认为 true</param> /// <returns></returns> public async Task <HttpResponseMessage> GetHttpResponseMessageAsync(string url, object data, int timeOut = Config.TIME_OUT, ApiRequestMethod requestMethod = ApiRequestMethod.POST, bool checkDataNotNull = true) { try { //var co2netHttpClient = CO2NET.HttpUtility.RequestUtility.HttpPost_Common_NetCore(serviceProvider, url, out var hc, contentType: "application/json"); ////设置参数 //var mchid = _tenpayV3Setting.TenPayV3_MchId; //var ser_no = _tenpayV3Setting.TenPayV3_SerialNumber; //var privateKey = _tenpayV3Setting.TenPayV3_PrivateKey; ////使用微信支付参数,配置 HttpHandler //TenPayHttpHandler httpHandler = new(mchid, ser_no, privateKey); //TODO:此处重构使用ISenparcWeixinSettingForTenpayV3 TenPayHttpHandler httpHandler = new(_tenpayV3Setting); //创建 HttpClient HttpClient client = new HttpClient(httpHandler); //设置超时时间 client.Timeout = TimeSpan.FromMilliseconds(timeOut); //设置 HTTP 请求头 SetHeader(client); HttpResponseMessage responseMessage = null; switch (requestMethod) { case ApiRequestMethod.GET: responseMessage = await client.GetAsync(url); WeixinTrace.Log(url); //记录Get的Json数据 break; case ApiRequestMethod.POST: case ApiRequestMethod.PUT: case ApiRequestMethod.PATCH: //检查是否为空 if (checkDataNotNull) { _ = data ?? throw new ArgumentNullException($"{nameof(data)} 不能为 null!"); } //设置请求 Json 字符串 //var jsonString = SerializerHelper.GetJsonString(data, new CO2NET.Helpers.Serializers.JsonSetting(true)); string jsonString = data != null ? data.ToJson(false, new Newtonsoft.Json.JsonSerializerSettings() { NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore }) : ""; WeixinTrace.SendApiPostDataLog(url, jsonString); //记录Post的Json数据 //设置 HttpContent var hc = new StringContent(jsonString, Encoding.UTF8, mediaType: "application/json"); //获取响应结果 responseMessage = requestMethod switch { ApiRequestMethod.POST => await client.PostAsync(url, hc), ApiRequestMethod.PUT => await client.PutAsync(url, hc), ApiRequestMethod.PATCH => await client.PatchAsync(url, hc), _ => throw new ArgumentOutOfRangeException(nameof(requestMethod)) }; break; default: throw new ArgumentOutOfRangeException(nameof(requestMethod)); } return(responseMessage); } catch (Exception) { throw; } }
/// <summary> /// 请求参数,获取结果 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="url"></param> /// <param name="data">如果为 GET 请求,此参数可为 null</param> /// <returns></returns> public async Task <T> RequestAsync <T>(string url, object data, int timeOut = Config.TIME_OUT, ApiRequestMethod requestMethod = ApiRequestMethod.POST, bool checkSign = true, Func <T> createDefaultInstance = null) where T : ReturnJsonBase/*, new()*/ { T result = null; try { HttpResponseMessage responseMessage = await GetHttpResponseMessageAsync(url, data, timeOut, requestMethod); //获取响应结果 string content = await responseMessage.Content.ReadAsStringAsync();//TODO:如果不正确也要返回详情 //检查响应代码 TenPayApiResultCode resutlCode = TenPayApiResultCode.TryGetCode(responseMessage.StatusCode, content); if (resutlCode.Success) { //TODO:待测试 //验证微信签名 //result.Signed = VerifyTenpaySign(responseMessage.Headers, content); var wechatpayTimestamp = responseMessage.Headers.GetValues("Wechatpay-Timestamp").First(); var wechatpayNonce = responseMessage.Headers.GetValues("Wechatpay-Nonce").First(); var wechatpaySignatureBase64 = responseMessage.Headers.GetValues("Wechatpay-Signature").First();//后续需要base64解码 var wechatpaySerial = responseMessage.Headers.GetValues("Wechatpay-Serial").First(); result = content.GetObject <T>(); if (checkSign) { try { var pubKey = await TenPayV3InfoCollection.GetAPIv3PublicKeyAsync(this._tenpayV3Setting, wechatpaySerial); result.VerifySignSuccess = TenPaySignHelper.VerifyTenpaySign(wechatpayTimestamp, wechatpayNonce, wechatpaySignatureBase64, content, pubKey); } catch (Exception ex) { throw new TenpayApiRequestException("RequestAsync 签名验证失败:" + ex.Message, ex); } } } else { result = createDefaultInstance?.Invoke() ?? GetInstance <T>(true); resutlCode.Additional = content; } //T result = resutlCode.Success ? (await responseMessage.Content.ReadAsStringAsync()).GetObject<T>() : new T(); result.ResultCode = resutlCode; return(result); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); result = createDefaultInstance?.Invoke() ?? GetInstance <T>(false); if (result != null) { result.ResultCode = new() { ErrorMessage = ex.Message }; } return(result); } }
public async Task <T> SendAsync <T>(string url, object data, int timeOut = Senparc.Weixin.Config.TIME_OUT, ApiRequestMethod requestMethod = ApiRequestMethod.POST, bool checkSign = true, Func <T> createDefaultInstance = null) where T : ReturnJsonBase /*, new()*/ { T result = null; HttpMethod method = GetHttpMethod(requestMethod); try { var request = new HttpRequestMessage(method, url); //设置超时时间 _client.Timeout = TimeSpan.FromMilliseconds(timeOut); //设置请求 Json 字符串 string jsonString = data != null ? data.ToJson(false, new Newtonsoft.Json.JsonSerializerSettings() { NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore }) : ""; WeixinTrace.SendApiPostDataLog(url, jsonString); //记录Post的Json数据 request.Content = new StringContent(jsonString, Encoding.UTF8, mediaType: "application/json"); // 进行签名 var authorization = await GenerateAuthorizationHeader(request); request.Headers.Add("Authorization", $"WECHATPAY2-{_signer.GetAlgorithm()} {authorization}"); // 发送请求 var responseMessage = await _client.SendAsync(request); //获取响应结果 string content = await responseMessage.Content.ReadAsStringAsync();//TODO:如果不正确也要返回详情 #if DEBUG Console.WriteLine("Content:" + content + ",,Headers:" + responseMessage.Headers.ToString()); #endif //检查响应代码 TenPayApiResultCode resutlCode = TenPayApiResultCode.TryGetCode(responseMessage.StatusCode, content); if (resutlCode.Success) { result = content.GetObject <T>(); if (checkSign) { result.VerifySignSuccess = await VerifyResponseMessage(responseMessage, content); } } else { result = createDefaultInstance?.Invoke() ?? GetInstance <T>(true); resutlCode.Additional = content; } result.ResultCode = resutlCode; return(result); } catch (Exception ex) { SenparcTrace.BaseExceptionLog(ex); result = createDefaultInstance?.Invoke() ?? GetInstance <T>(false); if (result != null) { result.ResultCode = new() { ErrorMessage = ex.Message }; } return(result); } }
/// <summary> /// 自动绑定属性 /// </summary> /// <param name="category">目录(平台类型),用于输出 API 的 Url 时分组</param> /// <param name="name">平台内唯一名称(如使用 PlatformType.General,请使用宇宙唯一名称)</param> /// <param name="apiRequestMethod">当前 API 请求的类型,如果为 null,则使用本次引擎全局定义的 </param> public ApiBindAttribute(string category, string name, ApiRequestMethod apiRequestMethod) : this(category, name, WebApi.ApiRequestMethod.GlobalDefault, null, 0) { }
private ApiResponse CreateResponse(string pathAndQuery, ApiRequestMethod method) { string url = string.Concat(this.Endpoint, pathAndQuery); return(new ApiResponse(new Uri(url), method, null, null)); }