From 56ed274c40eedc1c3ffa8fa518869f9d9dfa5c35 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 4 Jun 2025 23:53:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/WechatApi/Sample.md | 2 +- docs/WechatTenpayV3/Sample.md | 4 +- .../Options/TenpayOptions.cs | 4 + ...yCertificateRefreshingBackgroundService.cs | 3 +- .../IWechatTenpayPublicKeyManagerFactory.cs | 9 + .../Implements/WechatTenpayClientFactory.cs | 30 +- .../WechatTenpayPublicKeyManagerFactory.cs | 41 +++ .../Startup.cs | 3 +- .../appsettings.json | 4 +- .../App_Start/RouteRegistration.cs | 10 - .../Controllers/TenpayOrderController.cs | 43 --- .../Controllers/TenpayRefundController.cs | 46 --- .../Global.asax | 1 - .../Global.asax.cs | 33 -- .../Properties/AssemblyInfo.cs | 16 - ...enpayCertificateRefreshingBackgroundJob.cs | 54 --- .../Web.Debug.config | 5 - .../Web.Release.config | 6 - .../packages.config | 36 -- .../App_Start/AutofacConfig.cs} | 14 +- .../App_Start/FilterConfig.cs} | 6 +- .../App_Start/HangfireConfig.cs} | 4 +- .../App_Start/RouteConfig.cs | 19 ++ .../App_Start/WebApiConfig.cs} | 6 +- .../Controllers/TenpayNotifyController.cs | 18 +- .../Controllers/TenpayOrderController.cs | 54 +++ .../Controllers/TenpayRefundController.cs | 57 ++++ .../Global.asax | 1 + .../Global.asax.cs | 32 ++ .../Models/CreateOrderByJsapiRequest.cs | 0 .../Models/CreateRefundRequest.cs | 0 .../Options/TenpayOptions.cs | 11 + .../Properties/AssemblyInfo.cs | 35 ++ ...hat.TenpayV3.Sample_NetFramework48.csproj} | 311 +++++++++--------- ...enpayCertificateRefreshingBackgroundJob.cs | 65 ++++ .../IWechatTenpayCertificateManagerFactory.cs | 0 .../HttpClients/IWechatTenpayClientFactory.cs | 0 .../IWechatTenpayPublicKeyManagerFactory.cs | 9 + .../WechatTenpayCertificateManagerFactory.cs | 4 +- .../Implements/WechatTenpayClientFactory.cs | 25 +- .../WechatTenpayPublicKeyManagerFactory.cs | 36 ++ .../Web.Debug.config | 30 ++ .../Web.Release.config | 31 ++ .../Web.config | 124 +++---- .../packages.config | 50 +++ 45 files changed, 800 insertions(+), 492 deletions(-) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/RouteRegistration.cs delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayOrderController.cs delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayRefundController.cs delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax.cs delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Properties/AssemblyInfo.cs delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Debug.config delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Release.config delete mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/packages.config rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/AutofacInitializer.cs => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/AutofacConfig.cs} (73%) rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/FilterRegistration.cs => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/FilterConfig.cs} (61%) rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/HangfireInitializer.cs => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/HangfireConfig.cs} (90%) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/RouteConfig.cs rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/WebApiConfiguration.cs => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/WebApiConfig.cs} (73%) rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Controllers/TenpayNotifyController.cs (80%) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayOrderController.cs create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayRefundController.cs create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax.cs rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Models/CreateOrderByJsapiRequest.cs (100%) rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Models/CreateRefundRequest.cs (100%) rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Options/TenpayOptions.cs (81%) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Properties/AssemblyInfo.cs rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47.csproj => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48.csproj} (66%) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Services/HttpClients/IWechatTenpayCertificateManagerFactory.cs (100%) rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Services/HttpClients/IWechatTenpayClientFactory.cs (100%) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Services/HttpClients/Implements/WechatTenpayCertificateManagerFactory.cs (87%) rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Services/HttpClients/Implements/WechatTenpayClientFactory.cs (55%) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Debug.config create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Release.config rename samples/{SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 => SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48}/Web.config (54%) create mode 100644 samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/packages.config diff --git a/docs/WechatApi/Sample.md b/docs/WechatApi/Sample.md index 5c11ac92..3596182c 100644 --- a/docs/WechatApi/Sample.md +++ b/docs/WechatApi/Sample.md @@ -20,7 +20,7 @@ - 验证并接收微信服务器推送数据; -- 一个根据 OpenId 获取用户信息的 API。 +- 一个根据 OpenId 获取用户信息的 WebAPI。 --- diff --git a/docs/WechatTenpayV3/Sample.md b/docs/WechatTenpayV3/Sample.md index 6e63b306..16bb0dad 100644 --- a/docs/WechatTenpayV3/Sample.md +++ b/docs/WechatTenpayV3/Sample.md @@ -2,7 +2,7 @@ --- -示例项目基于 .NET Framework 4.7 和 .NET 6.0 实现,分别位于 _samples/SKIT.FlurlHttpClient.Wechat.Sample_NetFramework47_ 和 _samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6_。 +示例项目基于 .NET Framework 4.8 和 .NET 6.0 实现,分别位于 _samples/SKIT.FlurlHttpClient.Wechat.Sample_NetFramework48_ 和 _samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6_。 示例项目依赖以下第三方库: @@ -18,7 +18,7 @@ - 验证并接收微信服务器推送数据; -- 一个 JSAPI 下单和退款的 API。 +- 一个 JSAPI 下单和退款的 WebAPI。 --- diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Options/TenpayOptions.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Options/TenpayOptions.cs index 50b5b010..63d307fe 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Options/TenpayOptions.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Options/TenpayOptions.cs @@ -25,6 +25,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Options public string CertificateSerialNumber { get; set; } = string.Empty; public string CertificatePrivateKey { get; set; } = string.Empty; + + public string? PlatformPublicKeyId { get; set; } + + public string? PlatformPublicKey { get; set; } } } } diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/BackgroundServices/TenpayCertificateRefreshingBackgroundService.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/BackgroundServices/TenpayCertificateRefreshingBackgroundService.cs index 151c93f9..f7e40671 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/BackgroundServices/TenpayCertificateRefreshingBackgroundService.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/BackgroundServices/TenpayCertificateRefreshingBackgroundService.cs @@ -30,7 +30,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.BackgroundService { // NOTICE: // 2024-10-01 后微信支付新增了基于微信支付公钥的验证身份方式, - // 如果你已切换至使用平台公钥,则不再需要下载平台证书,可忽略此定时任务。 + // 如果你已切换至使用平台公钥,则不再需要下载平台证书,可删除此定时任务。 + while (!stoppingToken.IsCancellationRequested) { foreach (var tenpayMerchantOptions in _tenpayOptions.Merchants) diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs new file mode 100644 index 00000000..61e74eaf --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs @@ -0,0 +1,9 @@ +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients +{ + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; + + public interface IWechatTenpayPublicKeyManagerFactory + { + IPublicKeyManager Create(string merchantId); + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayClientFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayClientFactory.cs index b87ea371..369b163b 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayClientFactory.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayClientFactory.cs @@ -5,20 +5,25 @@ using Microsoft.Extensions.Options; namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients.Implements { + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; + internal partial class WechatTenpayClientFactory : IWechatTenpayClientFactory { private readonly IHttpClientFactory _httpClientFactory; private readonly Options.TenpayOptions _tenpayOptions; private readonly IWechatTenpayCertificateManagerFactory _tenpayCertificateManagerFactory; + private readonly IWechatTenpayPublicKeyManagerFactory _tenpayPublicKeyManagerFactory; public WechatTenpayClientFactory( IHttpClientFactory httpClientFactory, IOptions tenpayOptions, - IWechatTenpayCertificateManagerFactory tenpayCertificateManagerFactory) + IWechatTenpayCertificateManagerFactory tenpayCertificateManagerFactory, + IWechatTenpayPublicKeyManagerFactory tenpayPublicKeyManagerFactory) { _httpClientFactory = httpClientFactory; _tenpayOptions = tenpayOptions.Value; _tenpayCertificateManagerFactory = tenpayCertificateManagerFactory; + _tenpayPublicKeyManagerFactory = tenpayPublicKeyManagerFactory; } public WechatTenpayClient Create(string merchantId) @@ -27,19 +32,26 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients.Imple // 这里的工厂方法是为了演示多租户而存在的,可根据商户号生成不同的 API 客户端。 // 如果你的项目只存在唯一一个租户,那么直接注入 `WechatTenpayClient` 即可。 - var tenpayMerchantConfig = _tenpayOptions.Merchants?.FirstOrDefault(e => string.Equals(merchantId, e.MerchantId)); - if (tenpayMerchantConfig == null) + var tenpayMerchantOptions = _tenpayOptions.Merchants?.FirstOrDefault(e => string.Equals(merchantId, e.MerchantId)); + if (tenpayMerchantOptions == null) throw new Exception("未在配置项中找到该 MerchantId 对应的微信商户号。"); var wechatTenpayClientOptions = new WechatTenpayClientOptions() { - MerchantId = tenpayMerchantConfig.MerchantId, - MerchantV3Secret = tenpayMerchantConfig.SecretV3, - MerchantCertificateSerialNumber = tenpayMerchantConfig.CertificateSerialNumber, - MerchantCertificatePrivateKey = tenpayMerchantConfig.CertificatePrivateKey, - PlatformCertificateManager = _tenpayCertificateManagerFactory.Create(tenpayMerchantConfig.MerchantId), + MerchantId = tenpayMerchantOptions.MerchantId, + MerchantV3Secret = tenpayMerchantOptions.SecretV3, + MerchantCertificateSerialNumber = tenpayMerchantOptions.CertificateSerialNumber, + MerchantCertificatePrivateKey = tenpayMerchantOptions.CertificatePrivateKey, AutoEncryptRequestSensitiveProperty = false, - AutoDecryptResponseSensitiveProperty = false + AutoDecryptResponseSensitiveProperty = false, + + // 基于平台证书的认证方式还需设置以下参数: + PlatformAuthScheme = PlatformAuthScheme.Certificate, + PlatformCertificateManager = _tenpayCertificateManagerFactory.Create(tenpayMerchantOptions.MerchantId), + + // 基于平台公钥的认证方式还需设置以下参数: + //PlatformAuthScheme = PlatformAuthScheme.PublicKey, + //PlatformPublicKeyManager = _tenpayPublicKeyManagerFactory.Create(tenpayMerchantOptions.MerchantId) }; var wechatTenpayClient = WechatTenpayClientBuilder.Create(wechatTenpayClientOptions) .UseHttpClient(_httpClientFactory.CreateClient(), disposeClient: false) diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs new file mode 100644 index 00000000..533fa0f8 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Net.Http; +using Microsoft.Extensions.Options; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients.Implements +{ + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; + + internal partial class WechatTenpayPublicKeyManagerFactory : IWechatTenpayPublicKeyManagerFactory + { + private readonly ConcurrentDictionary _dict; + private readonly Options.TenpayOptions _tenpayOptions; + + public WechatTenpayPublicKeyManagerFactory( + IOptions tenpayOptions) + { + _dict = new ConcurrentDictionary(); + _tenpayOptions = tenpayOptions.Value; + } + + public IPublicKeyManager Create(string merchantId) + { + // NOTICE: + // 这里的工厂方法是为了演示多租户而存在的,可根据商户号生成不同的公钥管理器。 + // 如果你的项目只存在唯一一个租户,那么直接注入 `PublicKeyManager` 即可。 + + var tenpayMerchantOptions = _tenpayOptions.Merchants?.FirstOrDefault(e => string.Equals(merchantId, e.MerchantId)); + if (tenpayMerchantOptions == null) + throw new Exception("未在配置项中找到该 MerchantId 对应的微信商户号。"); + + return _dict.GetOrAdd(merchantId, (_) => + { + var manager = new InMemoryPublicKeyManager(); + manager.AddEntry(new PublicKeyEntry(PublicKeyEntry.ALGORITHM_TYPE_RSA, tenpayMerchantOptions.PlatformPublicKeyId!, tenpayMerchantOptions.PlatformPublicKey!)); + return manager; + }); + } + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Startup.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Startup.cs index 4edf9e6f..4e8add40 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Startup.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/Startup.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -25,6 +25,7 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample // 注入工厂 HTTP 客户端 services.AddHttpClient(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); // 注入后台任务 diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/appsettings.json b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/appsettings.json index b21440cd..b1feaee5 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/appsettings.json +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_Net6/appsettings.json @@ -15,7 +15,9 @@ "MerchantId": "填写商户号", "SecretV3": "填写商户 V3 API 密钥", "CertificateSerialNumber": "填写商户证书序列号", - "CertificatePrivateKey": "填写商户证书文件内容" + "CertificatePrivateKey": "填写商户证书文件内容", + "PlatformPublicKeyId": "填写平台公钥 ID(仅当基于平台公钥的认证方式时需要)", + "PlatformPublicKey": "填写平台公钥内容(仅当基于平台公钥的认证方式时需要)" } ], "NotifyUrl": "https://localhost:5001" diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/RouteRegistration.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/RouteRegistration.cs deleted file mode 100644 index ded73abe..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/RouteRegistration.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample -{ - public class RouteRegistration - { - public static void RegisterRoutes(RouteCollection routes) - { - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - } - } -} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayOrderController.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayOrderController.cs deleted file mode 100644 index c42217a2..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayOrderController.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Controllers -{ - [RoutePrefix("api/order")] - public class TenpayOrderController : ApiController - { - private readonly Services.HttpClients.IWechatTenpayClientFactory _wechatTenpayClientFactory; - - public TenpayOrderController( - Services.HttpClients.IWechatTenpayClientFactory wechatTenpayClientFactory) - { - _wechatTenpayClientFactory = wechatTenpayClientFactory; - } - - [HttpPost] - [Route("jsapi")] - public async Task CreateOrderByJsapi([FromBody] Models.CreateOrderByJsapiRequest requestModel, CancellationToken cancellationToken) - { - if (requestModel == null) - return BadRequest(); - - using var client = _wechatTenpayClientFactory.Create(requestModel.MerchantId); - var request = new CreatePayTransactionJsapiRequest() - { - OutTradeNumber = "SAMPLE_OTN_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"), - AppId = requestModel.AppId, - Description = "演示订单", - NotifyUrl = Options.TenpayOptions.Instance.Value.NotifyUrl, - Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = requestModel.Amount }, - Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = requestModel.OpenId } - }; - var response = await client.ExecuteCreatePayTransactionJsapiAsync(request, cancellationToken); - if (!response.IsSuccessful()) - { - Debug.WriteLine( - "JSAPI 下单失败(状态码:{0},错误代码:{1},错误描述:{2})。", - response.GetRawStatus(), response.ErrorCode, response.ErrorMessage - ); - } - - return Json(response); - } - } -} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayRefundController.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayRefundController.cs deleted file mode 100644 index cd612b13..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayRefundController.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Controllers -{ - [RoutePrefix("api/refund")] - public class TenpayRefundController : ApiController - { - private readonly Services.HttpClients.IWechatTenpayClientFactory _wechatTenpayClientFactory; - - public TenpayRefundController( - Services.HttpClients.IWechatTenpayClientFactory wechatTenpayClientFactory) - { - _wechatTenpayClientFactory = wechatTenpayClientFactory; - } - - [HttpPost] - [Route("")] - public async Task CreateRefund([FromBody] Models.CreateRefundRequest requestModel, CancellationToken cancellationToken) - { - if (requestModel == null) - return BadRequest(); - - using var client = _wechatTenpayClientFactory.Create(requestModel.MerchantId); - var request = new CreateRefundDomesticRefundRequest() - { - TransactionId = requestModel.TransactionId, - OutRefundNumber = "SAMPLE_ORN_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"), - Amount = new CreateRefundDomesticRefundRequest.Types.Amount() - { - Total = requestModel.OrderAmount, - Refund = requestModel.RefundAmount - }, - Reason = "示例退款", - NotifyUrl = Options.TenpayOptions.Instance.Value.NotifyUrl - }; - var response = await client.ExecuteCreateRefundDomesticRefundAsync(request, cancellationToken); - if (!response.IsSuccessful()) - { - Debug.WriteLine( - "申请退款失败(状态码:{0},错误代码:{1},错误描述:{2})。", - response.GetRawStatus(), response.ErrorCode, response.ErrorMessage - ); - } - - return Json(response); - } - } -} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax deleted file mode 100644 index 572899e7..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax +++ /dev/null @@ -1 +0,0 @@ -<%@ Application Codebehind="Global.asax.cs" Inherits="SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.WebApiApplication" Language="C#" %> diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax.cs deleted file mode 100644 index abf2b5ab..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Global.asax.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample -{ - public class WebApiApplication : HttpApplication - { - private Hangfire.BackgroundJobServer _backgroundJobServer; - - protected void Application_Start() - { - // 注册 WebAPI 区域 - AreaRegistration.RegisterAllAreas(); - - // 注册 WebAPI 配置 - GlobalConfiguration.Configure(WebApiConfiguration.Register); - - // 注册全局过滤器 - FilterRegistration.RegisterGlobalFilters(GlobalFilters.Filters); - - // 注册路由表 - RouteRegistration.RegisterRoutes(RouteTable.Routes); - - // 初始化 Autofac 依赖注入容器 - AutofacInitializer.Init(); - - // 初始化 Hangfire 定时任务 - _backgroundJobServer = HangfireInitializer.Init(); - } - - protected void Application_End() - { - _backgroundJobServer?.Dispose(); - } - } -} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Properties/AssemblyInfo.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Properties/AssemblyInfo.cs deleted file mode 100644 index 33677c7f..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,16 +0,0 @@ - -[assembly: AssemblyTitle("SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47")] -[assembly: AssemblyCopyright("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: Guid("41c93671-99b5-44ad-b0d4-6e2d8f5688ec")] - -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs deleted file mode 100644 index cc7dec40..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.BackgroundJobs -{ - internal class TenpayCertificateRefreshingBackgroundJob - { - private readonly HttpClients.IWechatTenpayClientFactory _wechatTenpayClientFactory; - - public TenpayCertificateRefreshingBackgroundJob( - HttpClients.IWechatTenpayClientFactory wechatTenpayClientFactory) - { - _wechatTenpayClientFactory = wechatTenpayClientFactory; - } - - public async Task ExecuteAsync() - { - // NOTICE: - // 2024-10-01 后微信支付新增了基于微信支付公钥的验证身份方式, - // 如果你已切换至使用平台公钥,则不再需要下载平台证书,可忽略此定时任务。 - foreach (var tenpayMerchantOptions in Options.TenpayOptions.Instance.Value.Merchants) - { - try - { - const string ALGORITHM_TYPE = "RSA"; - using var client = _wechatTenpayClientFactory.Create(tenpayMerchantOptions.MerchantId); - var request = new QueryCertificatesRequest() { AlgorithmType = ALGORITHM_TYPE }; - var response = await client.ExecuteQueryCertificatesAsync(request); - if (response.IsSuccessful()) - { - // NOTICE: - // 如果构造 Client 时启用了 `AutoDecryptResponseSensitiveProperty` 配置项,则无需再执行下面一行的手动解密方法: - response = client.DecryptResponseSensitiveProperty(response); - - foreach (var certificate in response.CertificateList) - { - client.CertificateManager.AddEntry(CertificateEntry.Parse(ALGORITHM_TYPE, certificate)); - } - - Debug.WriteLine("刷新微信商户平台证书成功。"); - } - else - { - Debug.WriteLine( - "刷新微信商户平台证书失败(状态码:{0},错误代码:{1},错误描述:{2})。", - response.GetRawStatus(), response.ErrorCode, response.ErrorMessage - ); - } - } - catch (Exception ex) - { - Debug.WriteLine("刷新微信商户平台证书遇到异常。\r\n{0}", ex); - } - } - } - } -} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Debug.config b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Debug.config deleted file mode 100644 index fc5e4b27..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Debug.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Release.config b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Release.config deleted file mode 100644 index 2f7b2f46..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.Release.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/packages.config b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/packages.config deleted file mode 100644 index 110d6b25..00000000 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/packages.config +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/AutofacInitializer.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/AutofacConfig.cs similarity index 73% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/AutofacInitializer.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/AutofacConfig.cs index 9441dca3..4dcb99cd 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/AutofacInitializer.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/AutofacConfig.cs @@ -1,6 +1,13 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample +using System.Reflection; +using System.Web.Mvc; +using Autofac; +using Autofac.Integration.Mvc; +using Autofac.Integration.WebApi; +using Hangfire; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample { - public class AutofacInitializer + public class AutofacConfig { public static void Init() { @@ -13,6 +20,9 @@ builder.RegisterType() .As() .SingleInstance(); + builder.RegisterType() + .As() + .SingleInstance(); builder.RegisterType() .As() .SingleInstance(); diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/FilterRegistration.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/FilterConfig.cs similarity index 61% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/FilterRegistration.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/FilterConfig.cs index 539a8744..dc0c1586 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/FilterRegistration.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/FilterConfig.cs @@ -1,6 +1,8 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample +using System.Web.Mvc; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample { - public class FilterRegistration + public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/HangfireInitializer.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/HangfireConfig.cs similarity index 90% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/HangfireInitializer.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/HangfireConfig.cs index c3a7809c..ed4a7168 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/HangfireInitializer.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/HangfireConfig.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; using Hangfire; namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample { - public class HangfireInitializer + public class HangfireConfig { public static BackgroundJobServer Init() { diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/RouteConfig.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/RouteConfig.cs new file mode 100644 index 00000000..2112fd27 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/RouteConfig.cs @@ -0,0 +1,19 @@ +using System.Web.Mvc; +using System.Web.Routing; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample +{ + public class RouteConfig + { + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + name: "Default", + url: "{controller}/{action}/{id}", + defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } + ); + } + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/WebApiConfiguration.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/WebApiConfig.cs similarity index 73% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/WebApiConfiguration.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/WebApiConfig.cs index 3383f2e7..65f2003a 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/App_Start/WebApiConfiguration.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/App_Start/WebApiConfig.cs @@ -1,6 +1,8 @@ -namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample +using System.Web.Http; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample { - public static class WebApiConfiguration + public static class WebApiConfig { public static void Register(HttpConfiguration config) { diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayNotifyController.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayNotifyController.cs similarity index 80% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayNotifyController.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayNotifyController.cs index c4b3f83b..a5991cdc 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Controllers/TenpayNotifyController.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayNotifyController.cs @@ -1,5 +1,15 @@ +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http; + namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Controllers { + using SKIT.FlurlHttpClient.Wechat.TenpayV3; + [RoutePrefix("api/notify")] public class TenpayNotifyController : ApiController { @@ -19,10 +29,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Controllers using (var stream = await Request.Content.ReadAsStreamAsync()) using (var reader = new StreamReader(stream, Encoding.UTF8)) { - string timestamp = Request.Headers.TryGetValues("Wechatpay-Timestamp", out _) ? Request.Headers.GetValues("Wechatpay-Timestamp").First() : null; - string nonce = Request.Headers.TryGetValues("Wechatpay-Nonce", out _) ? Request.Headers.GetValues("Wechatpay-Nonce").First() : null; - string signature = Request.Headers.TryGetValues("Wechatpay-Signature", out _) ? Request.Headers.GetValues("Wechatpay-Signature").First() : null; - string serialNumber = Request.Headers.TryGetValues("Wechatpay-Serial", out _) ? Request.Headers.GetValues("Wechatpay-Serial").First() : null; + string timestamp = Request.Headers.Contains("Wechatpay-Timestamp") ? Request.Headers.GetValues("Wechatpay-Timestamp").First() : null; + string nonce = Request.Headers.Contains("Wechatpay-Nonce") ? Request.Headers.GetValues("Wechatpay-Nonce").First() : null; + string signature = Request.Headers.Contains("Wechatpay-Signature") ? Request.Headers.GetValues("Wechatpay-Signature").First() : null; + string serialNumber = Request.Headers.Contains("Wechatpay-Serial") ? Request.Headers.GetValues("Wechatpay-Serial").First() : null; string content = await reader.ReadToEndAsync(); Debug.WriteLine("接收到微信支付推送的数据:{0}", content); diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayOrderController.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayOrderController.cs new file mode 100644 index 00000000..695fb8f4 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayOrderController.cs @@ -0,0 +1,54 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Controllers +{ + using SKIT.FlurlHttpClient.Wechat.TenpayV3; + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models; + + [RoutePrefix("api/order")] + public class TenpayOrderController : ApiController + { + private readonly Services.HttpClients.IWechatTenpayClientFactory _wechatTenpayClientFactory; + + public TenpayOrderController( + Services.HttpClients.IWechatTenpayClientFactory wechatTenpayClientFactory) + { + _wechatTenpayClientFactory = wechatTenpayClientFactory; + } + + [HttpPost] + [Route("jsapi")] + public async Task CreateOrderByJsapi([FromBody] Models.CreateOrderByJsapiRequest requestModel, CancellationToken cancellationToken) + { + if (requestModel == null) + return BadRequest(); + + using (var client = _wechatTenpayClientFactory.Create(requestModel.MerchantId)) + { + var request = new CreatePayTransactionJsapiRequest() + { + OutTradeNumber = "SAMPLE_OTN_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"), + AppId = requestModel.AppId, + Description = "演示订单", + NotifyUrl = Options.TenpayOptions.Instance.Value.NotifyUrl, + Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = requestModel.Amount }, + Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = requestModel.OpenId } + }; + var response = await client.ExecuteCreatePayTransactionJsapiAsync(request, cancellationToken); + if (!response.IsSuccessful()) + { + Debug.WriteLine( + "JSAPI 下单失败(状态码:{0},错误代码:{1},错误描述:{2})。", + response.GetRawStatus(), response.ErrorCode, response.ErrorMessage + ); + } + + return Json(response); + } + } + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayRefundController.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayRefundController.cs new file mode 100644 index 00000000..ed75471d --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Controllers/TenpayRefundController.cs @@ -0,0 +1,57 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Controllers +{ + using SKIT.FlurlHttpClient.Wechat.TenpayV3; + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models; + + [RoutePrefix("api/refund")] + public class TenpayRefundController : ApiController + { + private readonly Services.HttpClients.IWechatTenpayClientFactory _wechatTenpayClientFactory; + + public TenpayRefundController( + Services.HttpClients.IWechatTenpayClientFactory wechatTenpayClientFactory) + { + _wechatTenpayClientFactory = wechatTenpayClientFactory; + } + + [HttpPost] + [Route("")] + public async Task CreateRefund([FromBody] Models.CreateRefundRequest requestModel, CancellationToken cancellationToken) + { + if (requestModel == null) + return BadRequest(); + + using (var client = _wechatTenpayClientFactory.Create(requestModel.MerchantId)) + { + var request = new CreateRefundDomesticRefundRequest() + { + TransactionId = requestModel.TransactionId, + OutRefundNumber = "SAMPLE_ORN_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"), + Amount = new CreateRefundDomesticRefundRequest.Types.Amount() + { + Total = requestModel.OrderAmount, + Refund = requestModel.RefundAmount + }, + Reason = "示例退款", + NotifyUrl = Options.TenpayOptions.Instance.Value.NotifyUrl + }; + var response = await client.ExecuteCreateRefundDomesticRefundAsync(request, cancellationToken); + if (!response.IsSuccessful()) + { + Debug.WriteLine( + "申请退款失败(状态码:{0},错误代码:{1},错误描述:{2})。", + response.GetRawStatus(), response.ErrorCode, response.ErrorMessage + ); + } + + return Json(response); + } + } + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax new file mode 100644 index 00000000..35eb5a21 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax @@ -0,0 +1 @@ +<%@ Application Codebehind="Global.asax.cs" Inherits="SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.WebApiApplication" Language="C#" %> diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax.cs new file mode 100644 index 00000000..388421b1 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Global.asax.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Http; +using System.Web.Mvc; +using System.Web.Optimization; +using System.Web.Routing; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample +{ + public class WebApiApplication : System.Web.HttpApplication + { + private Hangfire.BackgroundJobServer _backgroundJobServer; + + protected void Application_Start() + { + AreaRegistration.RegisterAllAreas(); + GlobalConfiguration.Configure(WebApiConfig.Register); + FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); + RouteConfig.RegisterRoutes(RouteTable.Routes); + + AutofacConfig.Init(); + _backgroundJobServer = HangfireConfig.Init(); + } + + protected void Application_End() + { + _backgroundJobServer?.Dispose(); + } + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Models/CreateOrderByJsapiRequest.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Models/CreateOrderByJsapiRequest.cs similarity index 100% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Models/CreateOrderByJsapiRequest.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Models/CreateOrderByJsapiRequest.cs diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Models/CreateRefundRequest.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Models/CreateRefundRequest.cs similarity index 100% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Models/CreateRefundRequest.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Models/CreateRefundRequest.cs diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Options/TenpayOptions.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Options/TenpayOptions.cs similarity index 81% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Options/TenpayOptions.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Options/TenpayOptions.cs index 2fb90162..fd9e0e0f 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Options/TenpayOptions.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Options/TenpayOptions.cs @@ -1,3 +1,8 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web.Configuration; + namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Options { public partial class TenpayOptions @@ -19,6 +24,8 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Options SecretV3 = WebConfigurationManager.AppSettings[$"TenpayOptions_Merchant_{i}_SecretV3"], CertificateSerialNumber = WebConfigurationManager.AppSettings[$"TenpayOptions_Merchant_{i}_CertificateSerialNumber"], CertificatePrivateKey = WebConfigurationManager.AppSettings[$"TenpayOptions_Merchant_{i}_CertificatePrivateKey"], + PlatformPublicKeyId = WebConfigurationManager.AppSettings[$"TenpayOptions_Merchant_{i}_PlatformPublicKeyId"], + PlatformPublicKey = WebConfigurationManager.AppSettings[$"TenpayOptions_Merchant_{i}_PlatformPublicKey"], }) .ToArray(), NotifyUrl = WebConfigurationManager.AppSettings[$"TenpayOptions_NotifyUrl"] @@ -46,6 +53,10 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Options public string CertificateSerialNumber { get; set; } = string.Empty; public string CertificatePrivateKey { get; set; } = string.Empty; + + public string PlatformPublicKeyId { get; set; } + + public string PlatformPublicKey { get; set; } } } } diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Properties/AssemblyInfo.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..ab1051e7 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息是通过以下项进行控制的 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48")] +[assembly: AssemblyCopyright("版权所有(C) 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 将使此程序集中的类型 +// 对 COM 组件不可见。如果需要 +// COM,在该类型上将 ComVisible 属性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于 typelib 的 ID +[assembly: Guid("22aea3c5-d9af-4ec5-b208-73dc8795a1bb")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 你可以指定所有值,也可以让修订版本和内部版本号采用默认值, +// 方法是按如下所示使用 "*": +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47.csproj b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48.csproj similarity index 66% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47.csproj rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48.csproj index 4c255430..b5f0cf54 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47.csproj +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48.csproj @@ -1,30 +1,28 @@  + + Debug AnyCPU + + 2.0 - {7667F0D3-B41D-43C2-B69D-A68FE230EBF7} + {DFA229FF-0A4B-411E-9A11-681BA55DFBAE} {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties - SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample - SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47 - v4.7.2 + SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48 + SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48 + v4.8 false true - - - - - - - - - - - - + + 44339 + + + + @@ -46,37 +44,62 @@ prompt 4 - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - ..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.3.6.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - True + + ..\..\packages\Autofac.6.4.0\lib\netstandard2.0\Autofac.dll + + + ..\..\packages\Autofac.Mvc5.6.1.0\lib\net472\Autofac.Integration.Mvc.dll + + + ..\..\packages\Autofac.WebApi2.6.1.1\lib\net472\Autofac.Integration.WebApi.dll + + + ..\..\packages\Flurl.4.0.0\lib\net472\Flurl.dll + + + ..\..\packages\Flurl.Http.4.0.2\lib\net461\Flurl.Http.dll + + + ..\..\packages\Hangfire.AspNet.0.3.0\lib\net45\Hangfire.AspNet.dll + + + ..\..\packages\Hangfire.Autofac.2.7.0\lib\net45\Hangfire.Autofac.dll + + + ..\..\packages\Hangfire.Core.1.8.0\lib\net46\Hangfire.Core.dll + + + ..\..\packages\Hangfire.InMemory.1.0.0\lib\net451\Hangfire.InMemory.dll + + + ..\..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + + ..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll + + + ..\..\packages\Microsoft.Owin.Host.SystemWeb.3.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll + + + ..\..\packages\Owin.1.0\lib\net40\Owin.dll + + + ..\..\packages\SKIT.FlurlHttpClient.Common.3.1.1\lib\net462\SKIT.FlurlHttpClient.Common.dll ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll - - - - - - ..\..\packages\System.Diagnostics.DiagnosticSource.6.0.0\lib\net461\System.Diagnostics.DiagnosticSource.dll + + ..\..\packages\System.Diagnostics.DiagnosticSource.4.7.1\lib\net46\System.Diagnostics.DiagnosticSource.dll - + + ..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll - True - - - ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.9\lib\net45\System.Net.Http.Formatting.dll - True - - ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll @@ -84,124 +107,97 @@ ..\..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - - ..\..\packages\System.Text.Encodings.Web.6.0.0\lib\net461\System.Text.Encodings.Web.dll + + ..\..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\..\packages\System.Text.Json.8.0.5\lib\net462\System.Text.Json.dll ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + ..\..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + + + + + - - - - ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.Helpers.dll - True - - - ..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.9\lib\net45\System.Web.Http.dll - True - - - ..\..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.9\lib\net45\System.Web.Http.WebHost.dll - True - - - True - ..\..\packages\Microsoft.AspNet.Mvc.5.2.9\lib\net45\System.Web.Mvc.dll - - - ..\..\packages\Microsoft.AspNet.Razor.3.2.9\lib\net45\System.Web.Razor.dll - True - - - ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.WebPages.dll - True - - - ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.WebPages.Deployment.dll - True - - - ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.WebPages.Razor.dll - True - - - - ..\..\packages\Autofac.6.3.0\lib\netstandard2.0\Autofac.dll - - - ..\..\packages\Autofac.Mvc5.6.0.0\lib\net472\Autofac.Integration.Mvc.dll - - - ..\..\packages\Autofac.WebApi2.6.1.0\lib\net472\Autofac.Integration.WebApi.dll - - - ..\..\packages\Hangfire.AspNet.0.2.0\lib\net45\Hangfire.AspNet.dll - - - ..\..\packages\Hangfire.Autofac.2.3.1\lib\net45\Hangfire.Autofac.dll - - - ..\..\packages\Hangfire.Core.1.7.33\lib\net46\Hangfire.Core.dll - True - - - ..\..\packages\Hangfire.InMemory.0.3.6\lib\net45\Hangfire.InMemory.dll - True - - - ..\..\packages\Microsoft.AspNetCore.Html.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Html.Abstractions.dll - - - ..\..\packages\Microsoft.AspNetCore.Razor.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Razor.dll - - - ..\..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll - - - - ..\..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll - True - - - ..\..\packages\Microsoft.Owin.Host.SystemWeb.4.2.2\lib\net45\Microsoft.Owin.Host.SystemWeb.dll - True - - - ..\..\packages\Microsoft.AspNet.WebHelpers.3.2.9\lib\net45\Microsoft.Web.Helpers.dll - True - - + + + True ..\..\packages\Microsoft.Web.Infrastructure.2.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - + ..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll - True - - ..\..\packages\Owin.1.0\lib\net40\Owin.dll + - - - ..\..\packages\Microsoft.AspNet.WebPages.Data.3.2.9\lib\net45\WebMatrix.Data.dll - True + + ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.9\lib\net45\System.Net.Http.Formatting.dll - - ..\..\packages\Microsoft.AspNet.WebPages.WebData.3.2.9\lib\net45\WebMatrix.WebData.dll + + + True + ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.Helpers.dll + + + ..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.9\lib\net45\System.Web.Http.dll + + + ..\..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.9\lib\net45\System.Web.Http.WebHost.dll + + + True + ..\..\packages\Microsoft.AspNet.Mvc.5.2.9\lib\net45\System.Web.Mvc.dll + + + ..\..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll + + + True + ..\..\packages\Microsoft.AspNet.Razor.3.2.9\lib\net45\System.Web.Razor.dll + + + True + ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.WebPages.dll + + + True + ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.WebPages.Deployment.dll + + + True + ..\..\packages\Microsoft.AspNet.WebPages.3.2.9\lib\net45\System.Web.WebPages.Razor.dll + + + True + ..\..\packages\WebGrease.1.6.0\lib\WebGrease.dll + + + True + ..\..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll - - - - - + + ..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll + + + + + + + + @@ -213,10 +209,12 @@ + - + + - + @@ -229,38 +227,36 @@ - + + + + - {6fe502d4-c43d-49c9-9e57-d1ee566fd1c3} + {b9f2eb07-609c-d1b6-31de-1bfb32beee0d} SKIT.FlurlHttpClient.Wechat.TenpayV3 - - + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + - - - 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 - - - - True True - 8080 + 49987 / - http://localhost:8080/ + https://localhost:44339/ False False @@ -270,5 +266,16 @@ - + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + \ No newline at end of file diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs new file mode 100644 index 00000000..75152212 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/BackgroundJobs/TenpayCertificateRefreshingBackgroundJob.cs @@ -0,0 +1,65 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.BackgroundJobs +{ + using SKIT.FlurlHttpClient.Wechat.TenpayV3; + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models; + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; + + internal class TenpayCertificateRefreshingBackgroundJob + { + private readonly HttpClients.IWechatTenpayClientFactory _wechatTenpayClientFactory; + + public TenpayCertificateRefreshingBackgroundJob( + HttpClients.IWechatTenpayClientFactory wechatTenpayClientFactory) + { + _wechatTenpayClientFactory = wechatTenpayClientFactory; + } + + public async Task ExecuteAsync() + { + // NOTICE: + // 2024-10-01 后微信支付新增了基于微信支付公钥的验证身份方式, + // 如果你已切换至使用平台公钥,则不再需要下载平台证书,可删除此定时任务。 + + foreach (var tenpayMerchantOptions in Options.TenpayOptions.Instance.Value.Merchants) + { + try + { + const string ALGORITHM_TYPE = "RSA"; + using (var client = _wechatTenpayClientFactory.Create(tenpayMerchantOptions.MerchantId)) + { + var request = new QueryCertificatesRequest() { AlgorithmType = ALGORITHM_TYPE }; + var response = await client.ExecuteQueryCertificatesAsync(request); + if (response.IsSuccessful()) + { + // NOTICE: + // 如果构造 Client 时启用了 `AutoDecryptResponseSensitiveProperty` 配置项,则无需再执行下面一行的手动解密方法: + response = client.DecryptResponseSensitiveProperty(response); + + foreach (var certificate in response.CertificateList) + { + client.PlatformCertificateManager.AddEntry(CertificateEntry.Parse(ALGORITHM_TYPE, certificate)); + } + + Debug.WriteLine("刷新微信商户平台证书成功。"); + } + else + { + Debug.WriteLine( + "刷新微信商户平台证书失败(状态码:{0},错误代码:{1},错误描述:{2})。", + response.GetRawStatus(), response.ErrorCode, response.ErrorMessage + ); + } + } + } + catch (Exception ex) + { + Debug.WriteLine("刷新微信商户平台证书遇到异常。\r\n{0}", ex); + } + } + } + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/IWechatTenpayCertificateManagerFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayCertificateManagerFactory.cs similarity index 100% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/IWechatTenpayCertificateManagerFactory.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayCertificateManagerFactory.cs diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/IWechatTenpayClientFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayClientFactory.cs similarity index 100% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/IWechatTenpayClientFactory.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayClientFactory.cs diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs new file mode 100644 index 00000000..61e74eaf --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/IWechatTenpayPublicKeyManagerFactory.cs @@ -0,0 +1,9 @@ +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients +{ + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; + + public interface IWechatTenpayPublicKeyManagerFactory + { + IPublicKeyManager Create(string merchantId); + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/Implements/WechatTenpayCertificateManagerFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayCertificateManagerFactory.cs similarity index 87% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/Implements/WechatTenpayCertificateManagerFactory.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayCertificateManagerFactory.cs index bd45336c..5f6f80c4 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/Implements/WechatTenpayCertificateManagerFactory.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayCertificateManagerFactory.cs @@ -13,11 +13,11 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients.Imple _dict = new ConcurrentDictionary(); } - public CertificateManager Create(string merchantId) + public ICertificateManager Create(string merchantId) { // NOTICE: // 这里的工厂方法是为了演示多租户而存在的,可根据商户号生成不同的证书管理器。 - // 如果你的项目只存在唯一一个租户,那么直接注入 `CertificateManager` 即可。 + // 如果你的项目只存在唯一一个租户,那么直接注入 `PlatformCertificateManager` 即可。 return _dict.GetOrAdd(merchantId, new InMemoryCertificateManager()); } diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/Implements/WechatTenpayClientFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayClientFactory.cs similarity index 55% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/Implements/WechatTenpayClientFactory.cs rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayClientFactory.cs index 838208b3..7e4a1a2c 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Services/HttpClients/Implements/WechatTenpayClientFactory.cs +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayClientFactory.cs @@ -1,13 +1,21 @@ +using System; +using System.Linq; + namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients.Implements { + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; + internal partial class WechatTenpayClientFactory : IWechatTenpayClientFactory { private readonly IWechatTenpayCertificateManagerFactory _tenpayCertificateManagerFactory; + private readonly IWechatTenpayPublicKeyManagerFactory _tenpayPublicKeyManagerFactory; public WechatTenpayClientFactory( - IWechatTenpayCertificateManagerFactory tenpayCertificateManagerFactory) + IWechatTenpayCertificateManagerFactory tenpayCertificateManagerFactory, + IWechatTenpayPublicKeyManagerFactory tenpayPublicKeyManagerFactory) { _tenpayCertificateManagerFactory = tenpayCertificateManagerFactory; + _tenpayPublicKeyManagerFactory = tenpayPublicKeyManagerFactory; } public WechatTenpayClient Create(string merchantId) @@ -24,11 +32,18 @@ namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients.Imple { MerchantId = tenpayMerchantOptions.MerchantId, MerchantV3Secret = tenpayMerchantOptions.SecretV3, - MerchantCertSerialNumber = tenpayMerchantOptions.CertSerialNumber, - MerchantCertPrivateKey = tenpayMerchantOptions.CertPrivateKey, - CertificateManager = _tenpayCertificateManagerFactory.Create(tenpayMerchantOptions.MerchantId), + MerchantCertificateSerialNumber = tenpayMerchantOptions.CertificateSerialNumber, + MerchantCertificatePrivateKey = tenpayMerchantOptions.CertificatePrivateKey, AutoEncryptRequestSensitiveProperty = false, - AutoDecryptResponseSensitiveProperty = false + AutoDecryptResponseSensitiveProperty = false, + + // 基于平台证书的认证方式还需设置以下参数: + PlatformAuthScheme = PlatformAuthScheme.Certificate, + PlatformCertificateManager = _tenpayCertificateManagerFactory.Create(tenpayMerchantOptions.MerchantId), + + // 基于平台公钥的认证方式还需设置以下参数: + //PlatformAuthScheme = PlatformAuthScheme.PublicKey, + //PlatformPublicKeyManager = _tenpayPublicKeyManagerFactory.Create(tenpayMerchantOptions.MerchantId) }); } } diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs new file mode 100644 index 00000000..a8d83702 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Services/HttpClients/Implements/WechatTenpayPublicKeyManagerFactory.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Concurrent; +using System.Linq; + +namespace SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample.Services.HttpClients.Implements +{ + using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; + + internal partial class WechatTenpayPublicKeyManagerFactory : IWechatTenpayPublicKeyManagerFactory + { + private readonly ConcurrentDictionary _dict; + + public WechatTenpayPublicKeyManagerFactory() + { + _dict = new ConcurrentDictionary(); + } + + public IPublicKeyManager Create(string merchantId) + { + // NOTICE: + // 这里的工厂方法是为了演示多租户而存在的,可根据商户号生成不同的公钥管理器。 + // 如果你的项目只存在唯一一个租户,那么直接注入 `PlatformPublicKeyManager` 即可。 + + var tenpayMerchantOptions = Options.TenpayOptions.Instance.Value.Merchants?.FirstOrDefault(e => string.Equals(merchantId, e.MerchantId)); + if (tenpayMerchantOptions == null) + throw new Exception("未在配置项中找到该 MerchantId 对应的微信商户号。"); + + return _dict.GetOrAdd(merchantId, (_) => + { + var manager = new InMemoryPublicKeyManager(); + manager.AddEntry(new PublicKeyEntry(PublicKeyEntry.ALGORITHM_TYPE_RSA, tenpayMerchantOptions.PlatformPublicKeyId, tenpayMerchantOptions.PlatformPublicKey)); + return manager; + }); + } + } +} diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Debug.config b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Debug.config new file mode 100644 index 00000000..4bfe62fa --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Debug.config @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Release.config b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Release.config new file mode 100644 index 00000000..dd89ed89 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.Release.config @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.config b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.config similarity index 54% rename from samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.config rename to samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.config index 3123f842..c177efcb 100644 --- a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework47/Web.config +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/Web.config @@ -1,58 +1,52 @@ - + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -65,24 +59,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + - - - - - - - - - \ No newline at end of file + diff --git a/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/packages.config b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/packages.config new file mode 100644 index 00000000..d98666f8 --- /dev/null +++ b/samples/SKIT.FlurlHttpClient.Wechat.TenpayV3.Sample_NetFramework48/packages.config @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file