From fdf165b0531b13c6ae5c70dd634d7357fe69be0b Mon Sep 17 00:00:00 2001 From: coolcalf <28551@qq.com> Date: Mon, 22 Jul 2024 17:37:19 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=B0=86=E5=BE=AE=E4=BF=A1=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E5=85=B3=E9=97=AD=E7=8A=B6=E6=80=81(CLOSED)=E5=86=99?= =?UTF-8?q?=E5=85=A5=E5=88=B0=E6=94=AF=E4=BB=98=E8=AE=B0=E5=BD=95=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Service/Common/SysCommonService.cs | 2 ++ .../Service/Wechat/SysWechatPayService.cs | 35 ++++++++++++------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs index e4f34edf..4ce3d6bd 100644 --- a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs @@ -91,6 +91,8 @@ public class SysCommonService : IDynamicApiController, ITransient // 接口分组/控制器信息 var controllerActionDescriptor = action.ActionDescriptor as ControllerActionDescriptor; + if (controllerActionDescriptor == null) + continue; var apiDescription = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttribute(true); var controllerName = controllerActionDescriptor.ControllerName; if (!apiOuput.Children.Exists(u => u.Name == controllerName)) diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs index 905974f6..4220ac1d 100644 --- a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs @@ -38,7 +38,10 @@ public class SysWechatPayService : IDynamicApiController, ITransient /// private WechatTenpayClient CreateTenpayClient() { - var cerFilePath = App.WebHostEnvironment.ContentRootPath + _wechatPayOptions.MerchantCertificatePrivateKey; + var cerFilePath = _wechatPayOptions.MerchantCertificatePrivateKey; + + if (!File.Exists(cerFilePath)) + throw Oops.Oh("商户证书文件不存在:" + cerFilePath); var tenpayClientOptions = new WechatTenpayClientOptions() { @@ -353,6 +356,12 @@ public class SysWechatPayService : IDynamicApiController, ITransient [DisplayName("微信支付订单号查询(校正)")] public async Task GetPayTransactionByIdAsync(string transactionId) { + if (string.IsNullOrEmpty(transactionId)) + throw Oops.Oh("TransactionId 不能为空"); + + if (string.IsNullOrEmpty(_wechatPayOptions.MerchantId) || string.IsNullOrEmpty(_wechatPayOptions.MerchantCertificateSerialNumber)) + throw Oops.Oh("商户号或证书序列号不能为空,请检查支付配置"); + var request = new GetPayTransactionByIdRequest() { MerchantId = _wechatPayOptions.MerchantId, @@ -360,21 +369,18 @@ public class SysWechatPayService : IDynamicApiController, ITransient WechatpayCertificateSerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber }; var response = await _wechatTenpayClient.ExecuteGetPayTransactionByIdAsync(request); - if (response.TradeState == "SUCCESS") + if (response.TradeState == "SUCCESS" || response.TradeState == "CLOSED") { // 修正订单支付状态 - var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.TransactionId == transactionId && u.MerchantId == request.MerchantId); + var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.TransactionId == request.TransactionId && u.MerchantId == request.MerchantId); if (wechatPay != null && string.IsNullOrEmpty(wechatPay.TradeState)) { - wechatPay.TransactionId = response.TransactionId; // 支付订单号 wechatPay.TradeType = response.TradeType; // 交易类型 wechatPay.TradeState = response.TradeState; // 交易状态 wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 - wechatPay.BankType = response.BankType; // 付款银行类型 - wechatPay.Total = response.Amount.Total; // 订单总金额 - wechatPay.PayerTotal = response.Amount.PayerTotal; // 用户支付金额 + wechatPay.BankType = response.BankType; // 付款银行类型 + wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 wechatPay.SuccessTime = response.SuccessTime; // 支付完成时间 - await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); return wechatPay.Adapt(); } @@ -391,6 +397,12 @@ public class SysWechatPayService : IDynamicApiController, ITransient [DisplayName("微信商户订单号查询(校正)")] public async Task GetPayTransactionByOutTradeNumberAsync(string outTradeNumber) { + if (string.IsNullOrEmpty(outTradeNumber)) + throw Oops.Oh("商户订单号(OutTradeNumber)不能为空"); + + if (string.IsNullOrEmpty(_wechatPayOptions.MerchantId) || string.IsNullOrEmpty(_wechatPayOptions.MerchantCertificateSerialNumber)) + throw Oops.Oh("商户号或证书序列号不能为空,请检查支付配置"); + var request = new GetPayTransactionByOutTradeNumberRequest() { MerchantId = _wechatPayOptions.MerchantId, @@ -398,7 +410,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient WechatpayCertificateSerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber }; var response = await _wechatTenpayClient.ExecuteGetPayTransactionByOutTradeNumberAsync(request); - if (response.TradeState == "SUCCESS") + if (response.TradeState == "SUCCESS" || response.TradeState == "CLOSED") { // 修正订单支付状态 var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == outTradeNumber && u.MerchantId == request.MerchantId); @@ -408,9 +420,8 @@ public class SysWechatPayService : IDynamicApiController, ITransient wechatPay.TradeType = response.TradeType; // 交易类型 wechatPay.TradeState = response.TradeState; // 交易状态 wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 - wechatPay.BankType = response.BankType; // 付款银行类型 - wechatPay.Total = response.Amount.Total; // 订单总金额 - wechatPay.PayerTotal = response.Amount.PayerTotal; // 用户支付金额 + wechatPay.BankType = response.BankType; // 付款银行类型 + wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 wechatPay.SuccessTime = response.SuccessTime; // 支付完成时间 await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); return wechatPay.Adapt(); From 89949d4dc7fc94c50754f67519402c13adde1d54 Mon Sep 17 00:00:00 2001 From: zuohuaijun Date: Mon, 22 Jul 2024 22:52:56 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=98=8E=E4=BB=A3=E7=A0=81=E6=B8=85?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin.NET.Core/Admin.NET.Core.csproj | 2 +- .../Admin.NET.Core/Attribute/DictAttribute.cs | 2 +- .../EventBus/RedisEventSourceStorer.cs | 34 +++++++++++-------- .../Service/Wechat/SysWechatPayService.cs | 12 +++---- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj index 7fe0210b..0930f88d 100644 --- a/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj +++ b/Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj @@ -38,7 +38,7 @@ - + diff --git a/Admin.NET/Admin.NET.Core/Attribute/DictAttribute.cs b/Admin.NET/Admin.NET.Core/Attribute/DictAttribute.cs index d252cf03..84e52f64 100644 --- a/Admin.NET/Admin.NET.Core/Attribute/DictAttribute.cs +++ b/Admin.NET/Admin.NET.Core/Attribute/DictAttribute.cs @@ -40,7 +40,7 @@ public class DictAttribute : ValidationAttribute, ITransient // 是否忽略空字符串 if (AllowEmptyStrings && string.IsNullOrEmpty(valueAsString)) return ValidationResult.Success; - var sysDictDataServiceProvider = validationContext.GetRequiredService(); + var sysDictDataServiceProvider = App.GetRequiredService(); var dictDataList = sysDictDataServiceProvider.GetDataList(DictTypeCode).Result; // 使用HashSet来提高查找效率 diff --git a/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs b/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs index 475bdf41..f507e7ba 100644 --- a/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs +++ b/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs @@ -1,4 +1,4 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // @@ -35,10 +35,7 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable private RedisStream _queueBroadcast; - /// - /// 路由键 - /// - private readonly string _routeKey; + private ILogger _logger; /// /// 构造函数 @@ -48,6 +45,8 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable /// 存储器最多能够处理多少消息,超过该容量进入等待写入 public RedisEventSourceStorer(ICacheProvider cacheProvider, string routeKey, int capacity) { + _logger = App.GetRequiredService>(); + // 配置通道,设置超出默认容量后进入等待 var boundedChannelOptions = new BoundedChannelOptions(capacity) { @@ -58,7 +57,6 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable _channel = Channel.CreateBounded(boundedChannelOptions); //_redis = redis as FullRedis; - _routeKey = routeKey; // 创建广播消息订阅者,即所有服务器节点都能收到消息(用来发布重启、Reload配置等消息) FullRedis redis = (FullRedis)cacheProvider.Cache; @@ -73,23 +71,29 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable _eventConsumer = new EventConsumer(_queueSingle); // 订阅消息写入 Channel - _eventConsumer.Received += (send, cr) => + _eventConsumer.Received += async (send, cr) => { - var oriColor = Console.ForegroundColor; - ChannelEventSource ces = (ChannelEventSource)cr; - ConsumeChannelEventSource(ces); + // var oriColor = Console.ForegroundColor; + try + { + ChannelEventSource ces = (ChannelEventSource)cr; + await ConsumeChannelEventSourceAsync(ces, ces.CancellationToken); + } + catch (Exception e) + { + _logger.LogError(e, "处理Received中的消息产生错误!"); + } }; _eventConsumer.Start(); } - private Task OnConsumeBroadcast(string source, Message message, CancellationToken token) + private async Task OnConsumeBroadcast(string source, Message message, CancellationToken token) { ChannelEventSource ces = JsonConvert.DeserializeObject(source); - ConsumeChannelEventSource(ces); - return Task.CompletedTask; + await ConsumeChannelEventSourceAsync(ces, token); } - private void ConsumeChannelEventSource(ChannelEventSource ces) + private async Task ConsumeChannelEventSourceAsync(ChannelEventSource ces, CancellationToken cancel = default) { // 打印测试事件 if (ces.EventId != null && ces.EventId.IndexOf(":Test") > 0) @@ -99,7 +103,7 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable Console.WriteLine($"有消息要处理{ces.EventId},{ces.Payload}"); Console.ForegroundColor = oriColor; } - _channel.Writer.WriteAsync(ces); + await _channel.Writer.WriteAsync(ces, cancel); } /// diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs index 4220ac1d..04dd1969 100644 --- a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs @@ -19,10 +19,10 @@ public class SysWechatPayService : IDynamicApiController, ITransient private readonly WechatTenpayClient _wechatTenpayClient; - public SysWechatPayService(SqlSugarRepository sysWechatPayRep - , SqlSugarRepository sysWechatRefundRep - , IOptions wechatPayOptions - , IOptions payCallBackOptions) + public SysWechatPayService(SqlSugarRepository sysWechatPayRep, + SqlSugarRepository sysWechatRefundRep, + IOptions wechatPayOptions, + IOptions payCallBackOptions) { _sysWechatPayRep = sysWechatPayRep; this._sysWechatRefundRep = sysWechatRefundRep; @@ -378,7 +378,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient wechatPay.TradeType = response.TradeType; // 交易类型 wechatPay.TradeState = response.TradeState; // 交易状态 wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 - wechatPay.BankType = response.BankType; // 付款银行类型 + wechatPay.BankType = response.BankType; // 付款银行类型 wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 wechatPay.SuccessTime = response.SuccessTime; // 支付完成时间 await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); @@ -420,7 +420,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient wechatPay.TradeType = response.TradeType; // 交易类型 wechatPay.TradeState = response.TradeState; // 交易状态 wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述 - wechatPay.BankType = response.BankType; // 付款银行类型 + wechatPay.BankType = response.BankType; // 付款银行类型 wechatPay.PayerTotal = response.Amount?.PayerTotal; // 用户支付金额 wechatPay.SuccessTime = response.SuccessTime; // 支付完成时间 await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync(); From e3feb6cad8f0d00bff5d7f88670c41515d021d4a Mon Sep 17 00:00:00 2001 From: coolcalf <28551@qq.com> Date: Mon, 22 Jul 2024 23:01:56 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fixed:=20=E5=BE=AE=E4=BF=A1=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E8=AF=81=E4=B9=A6=E8=B7=AF=E5=BE=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin.NET.Core/Service/Wechat/SysWechatPayService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs index 04dd1969..a977263c 100644 --- a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs @@ -38,10 +38,10 @@ public class SysWechatPayService : IDynamicApiController, ITransient /// private WechatTenpayClient CreateTenpayClient() { - var cerFilePath = _wechatPayOptions.MerchantCertificatePrivateKey; + var cerFilePath = App.WebHostEnvironment.ContentRootPath + _wechatPayOptions.MerchantCertificatePrivateKey; if (!File.Exists(cerFilePath)) - throw Oops.Oh("商户证书文件不存在:" + cerFilePath); + Log.Warning("商户证书文件不存在:" + cerFilePath); var tenpayClientOptions = new WechatTenpayClientOptions() {