using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace YD_Event.Application.Event; /// /// 支付超时处理后台服务 /// public class PaymentExpirationBackgroundService : BackgroundService { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; private readonly PeriodicTimer _timer; public PaymentExpirationBackgroundService( IServiceProvider serviceProvider, ILogger logger) { _serviceProvider = serviceProvider; _logger = logger; _timer = new PeriodicTimer(TimeSpan.FromMinutes(5)); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("支付超时处理后台服务已启动"); try { while (await _timer.WaitForNextTickAsync(stoppingToken)) { await ProcessExpiredPaymentsAsync(stoppingToken); } } catch (OperationCanceledException) { _logger.LogInformation("支付超时处理后台服务已停止"); } } private async Task ProcessExpiredPaymentsAsync(CancellationToken stoppingToken) { try { _logger.LogInformation("开始处理超时未支付订单"); using var scope = _serviceProvider.CreateScope(); var registrationRepository = scope.ServiceProvider.GetRequiredService>(); var orderRepository = scope.ServiceProvider.GetRequiredService>(); var now = DateTime.Now; var expirationTime = now.AddMinutes(-30); var expiredRegistrations = await registrationRepository.AsQueryable() .Where(x => x.PaymentMethod == 2 && x.PaymentStatus == 0 && x.CreatedTime <= expirationTime && !x.DeleteMark) .ToListAsync(stoppingToken); if (expiredRegistrations.Any()) { _logger.LogInformation("发现 {Count} 个超时未支付的线上订单", expiredRegistrations.Count); var idsToCancel = expiredRegistrations.Select(x => x.Id).ToList(); var orderNos = expiredRegistrations.Where(x => !string.IsNullOrEmpty(x.OrderNo)).Select(x => x.OrderNo).ToList(); await registrationRepository.UpdateAsync(x => new EventRegistration { PaymentStatus = 4, UpdatedTime = now }, x => idsToCancel.Contains(x.Id)); if (orderNos.Any()) { await orderRepository.UpdateAsync(x => new YD_Event.Core.Entities.Order { OrderStatus = OrderStatus.Cancelled, UpdatedTime = now }, x => orderNos.Contains(x.OrderNo)); } _logger.LogInformation("已成功取消 {Count} 个超时未支付订单", expiredRegistrations.Count); } } catch (Exception ex) { _logger.LogError(ex, "处理超时未支付订单时发生错误"); } } public override void Dispose() { _timer.Dispose(); base.Dispose(); } }