using System; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Flurl.Http; namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.ExtendedSDK.Global { using _ROOT_ = SKIT.FlurlHttpClient.Wechat.TenpayV3; using SKIT.FlurlHttpClient.Wechat.TenpayV3.Constants; /// /// 一个微信支付 Global API HTTP 客户端。 /// public class WechatTenpayGlobalClient : CommonClientBase, ICommonClient { internal WechatTenpayClient ProxyClient { get; } /// /// 获取当前客户端使用的微信支付商户凭证。 /// public Settings.Credentials Credentials { get; } /// /// 获取当前客户端使用的微信支付平台证书管理器。 /// public _ROOT_.Settings.ICertificateManager PlatformCertificateManager { get; } /// /// 获取是否自动加密请求中的敏感信息字段。 /// protected internal bool AutoEncryptRequestSensitiveProperty { get; } /// /// 获取是否自动解密请求中的敏感信息字段。 /// protected internal bool AutoDecryptResponseSensitiveProperty { get; } /// /// 用指定的配置项初始化 类的新实例。 /// /// 配置项。 public WechatTenpayGlobalClient(WechatTenpayGlobalClientOptions options) : this(options, null) { } /// /// /// /// /// /// internal protected WechatTenpayGlobalClient(WechatTenpayGlobalClientOptions options, HttpClient? httpClient, bool disposeClient = true) : base(httpClient, disposeClient) { if (options is null) throw new ArgumentNullException(nameof(options)); ProxyClient = new WechatTenpayClient(new WechatTenpayClientOptions() { Timeout = options.Timeout, Endpoint = options.Endpoint, AcceptLanguage = options.AcceptLanguage, SignScheme = options.SignScheme, MerchantId = options.MerchantId, MerchantV3Secret = options.MerchantV3Secret, MerchantCertificateSerialNumber = options.MerchantCertificateSerialNumber, MerchantCertificatePrivateKey = options.MerchantCertificatePrivateKey, PlatformAuthScheme = _ROOT_.Settings.PlatformAuthScheme.Certificate, PlatformCertificateManager = options.PlatformCertificateManager, AutoEncryptRequestSensitiveProperty = options.AutoEncryptRequestSensitiveProperty, AutoDecryptResponseSensitiveProperty = options.AutoDecryptResponseSensitiveProperty }, httpClient, disposeClient); Credentials = new Settings.Credentials(options); PlatformCertificateManager = options.PlatformCertificateManager; AutoEncryptRequestSensitiveProperty = options.AutoEncryptRequestSensitiveProperty; AutoDecryptResponseSensitiveProperty = options.AutoDecryptResponseSensitiveProperty; FlurlClient.BaseUrl = options.Endpoint ?? WechatTenpayGlobalEndpoints.DEFAULT; FlurlClient.WithHeader(HttpHeaders.Accept, "application/json"); FlurlClient.WithHeader(HttpHeaders.AcceptLanguage, options.AcceptLanguage); FlurlClient.WithHeader(HttpHeaders.UserAgent, $"OS/{Environment.OSVersion.Platform} SKIT.FlurlHttpClient.Wechat.Tenpay/{AssemblyProps.VERSION}"); FlurlClient.WithTimeout(options.Timeout <= 0 ? Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(options.Timeout)); Interceptors.Add(new Interceptors.WechatTenpayRequestSigningInterceptor( scheme: options.SignScheme, mchId: options.MerchantId, mchCertSn: options.MerchantCertificateSerialNumber, mchCertPk: options.MerchantCertificatePrivateKey )); } /// /// 使用当前客户端生成一个新的 对象。 /// /// /// /// /// public IFlurlRequest CreateFlurlRequest(WechatTenpayGlobalRequest request, HttpMethod httpMethod, params object[] urlSegments) { return base.CreateFlurlRequest(request, httpMethod, urlSegments); } /// /// 异步发起请求。 /// /// /// /// /// /// public async Task SendFlurlRequestAsync(IFlurlRequest flurlRequest, HttpContent? httpContent = null, CancellationToken cancellationToken = default) where T : WechatTenpayGlobalResponse, new() { if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest)); using IFlurlResponse flurlResponse = await base.SendFlurlRequestAsync(flurlRequest, httpContent, cancellationToken).ConfigureAwait(false); return await WrapFlurlResponseAsJsonAsync(flurlResponse, cancellationToken).ConfigureAwait(false); } /// /// 异步发起请求。 /// /// /// /// /// /// public async Task SendFlurlRequestAsJsonAsync(IFlurlRequest flurlRequest, object? data = null, CancellationToken cancellationToken = default) where T : WechatTenpayGlobalResponse, new() { if (flurlRequest is null) throw new ArgumentNullException(nameof(flurlRequest)); bool isSimpleRequest = data is null || flurlRequest.Verb == HttpMethod.Get || flurlRequest.Verb == HttpMethod.Head || flurlRequest.Verb == HttpMethod.Options; using IFlurlResponse flurlResponse = isSimpleRequest ? await base.SendFlurlRequestAsync(flurlRequest, null, cancellationToken).ConfigureAwait(false) : await base.SendFlurlRequestAsJsonAsync(flurlRequest, data, cancellationToken).ConfigureAwait(false); return await WrapFlurlResponseAsJsonAsync(flurlResponse, cancellationToken).ConfigureAwait(false); } private new async Task WrapFlurlResponseAsJsonAsync(IFlurlResponse flurlResponse, CancellationToken cancellationToken = default) where TResponse : WechatTenpayGlobalResponse, new() { TResponse result = await base.WrapFlurlResponseAsJsonAsync(flurlResponse, cancellationToken).ConfigureAwait(false); if (AutoDecryptResponseSensitiveProperty && result.IsSuccessful()) { this.DecryptResponseSensitiveProperty(result); } return result; } } }