99 lines
3.4 KiB
C#
99 lines
3.4 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace YD_Event.Application.Event;
|
|
|
|
/// <summary>
|
|
/// 支付超时处理后台服务
|
|
/// </summary>
|
|
public class PaymentExpirationBackgroundService : BackgroundService
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly ILogger<PaymentExpirationBackgroundService> _logger;
|
|
private readonly PeriodicTimer _timer;
|
|
|
|
public PaymentExpirationBackgroundService(
|
|
IServiceProvider serviceProvider,
|
|
ILogger<PaymentExpirationBackgroundService> 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<ISqlSugarRepository<EventRegistration>>();
|
|
var orderRepository = scope.ServiceProvider.GetRequiredService<ISqlSugarRepository<YD_Event.Core.Entities.Order>>();
|
|
|
|
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();
|
|
}
|
|
}
|