mirror of https://github.com/EasyAbp/EShop.git
41 changed files with 5778 additions and 14 deletions
@ -0,0 +1,7 @@ |
|||||
|
namespace EasyAbp.EShop.Orders |
||||
|
{ |
||||
|
public static class OrdersConsts |
||||
|
{ |
||||
|
public static string CancellationReason = "Order payment timed out and not paid"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,66 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.BackgroundJobs; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities.Events; |
||||
|
using Volo.Abp.EventBus; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.Timing; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
[Dependency(TryRegister = true)] |
||||
|
[UnitOfWork] |
||||
|
public class DefaultUnpaidOrderAutoCancelProvider : |
||||
|
IUnpaidOrderAutoCancelProvider, |
||||
|
ILocalEventHandler<EntityCreatedEventData<Order>>, |
||||
|
ILocalEventHandler<OrderPaymentIdChangedEto>, |
||||
|
ITransientDependency |
||||
|
{ |
||||
|
private readonly IClock _clock; |
||||
|
private readonly IOrderManager _orderManager; |
||||
|
private readonly IBackgroundJobManager _backgroundJobManager; |
||||
|
|
||||
|
public DefaultUnpaidOrderAutoCancelProvider( |
||||
|
IClock clock, |
||||
|
IOrderManager orderManager, |
||||
|
IBackgroundJobManager backgroundJobManager) |
||||
|
{ |
||||
|
_clock = clock; |
||||
|
_orderManager = orderManager; |
||||
|
_backgroundJobManager = backgroundJobManager; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task HandleEventAsync(EntityCreatedEventData<Order> eventData) |
||||
|
{ |
||||
|
if (!eventData.Entity.PaymentExpiration.HasValue) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var args = new UnpaidOrderAutoCancelArgs |
||||
|
{ |
||||
|
TenantId = eventData.Entity.TenantId, |
||||
|
OrderId = eventData.Entity.Id |
||||
|
}; |
||||
|
|
||||
|
await _backgroundJobManager.EnqueueAsync( |
||||
|
args: args, |
||||
|
delay: eventData.Entity.PaymentExpiration.Value.Subtract(_clock.Now) // Todo: use a absolute time.
|
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task HandleEventAsync(OrderPaymentIdChangedEto eventData) |
||||
|
{ |
||||
|
if (!eventData.Order.PaymentExpiration.HasValue || eventData.ToPaymentId.HasValue) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (_clock.Now > eventData.Order.PaymentExpiration.Value && !eventData.Order.CanceledTime.HasValue) |
||||
|
{ |
||||
|
await _orderManager.CancelAsync(eventData.Order, OrdersConsts.CancellationReason); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
public interface IUnpaidOrderAutoCancelProvider |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
[Serializable] |
||||
|
public class OrderPaymentIdChangedEto : IMultiTenant |
||||
|
{ |
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
public Order Order { get; set; } |
||||
|
|
||||
|
public Guid? FromPaymentId { get; set; } |
||||
|
|
||||
|
public Guid? ToPaymentId { get; set; } |
||||
|
|
||||
|
public OrderPaymentIdChangedEto(Guid? tenantId, Order order, Guid? fromPaymentId, Guid? toPaymentId) |
||||
|
{ |
||||
|
TenantId = tenantId; |
||||
|
Order = order; |
||||
|
FromPaymentId = fromPaymentId; |
||||
|
ToPaymentId = toPaymentId; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.BackgroundJobs; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
[BackgroundJobName("EShopUnpaidOrderAutoCancel")] |
||||
|
public class UnpaidOrderAutoCancelArgs : IMultiTenant |
||||
|
{ |
||||
|
public Guid? TenantId { get; set; } |
||||
|
|
||||
|
public Guid OrderId { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using EasyAbp.PaymentService.Payments; |
||||
|
using Volo.Abp.BackgroundJobs; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
public class UnpaidOrderAutoCancelJob : AsyncBackgroundJob<UnpaidOrderAutoCancelArgs>, ITransientDependency |
||||
|
{ |
||||
|
private readonly ICurrentTenant _currentTenant; |
||||
|
private readonly IOrderManager _orderManager; |
||||
|
private readonly IOrderRepository _orderRepository; |
||||
|
private readonly IDistributedEventBus _distributedEventBus; |
||||
|
|
||||
|
public UnpaidOrderAutoCancelJob( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IOrderManager orderManager, |
||||
|
IOrderRepository orderRepository, |
||||
|
IDistributedEventBus distributedEventBus) |
||||
|
{ |
||||
|
_currentTenant = currentTenant; |
||||
|
_orderManager = orderManager; |
||||
|
_orderRepository = orderRepository; |
||||
|
_distributedEventBus = distributedEventBus; |
||||
|
} |
||||
|
|
||||
|
[UnitOfWork] |
||||
|
public override async Task ExecuteAsync(UnpaidOrderAutoCancelArgs args) |
||||
|
{ |
||||
|
using var changeTenant = _currentTenant.Change(args.TenantId); |
||||
|
|
||||
|
var order = await _orderRepository.FindAsync(args.OrderId); |
||||
|
|
||||
|
if (order is not {CanceledTime: null} || order.IsPaid()) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (order.IsInPayment()) |
||||
|
{ |
||||
|
// Cancel the payment and cancel the order in EasyAbp.EShop.Orders.Orders.PaymentCanceledEventHandler
|
||||
|
await _distributedEventBus.PublishAsync(new CancelPaymentEto(args.TenantId, order.PaymentId!.Value)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
await _orderManager.CancelAsync(order, OrdersConsts.CancellationReason); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using EasyAbp.EShop.Payments; |
||||
|
using EasyAbp.EShop.Payments.Payments; |
||||
|
using EasyAbp.PaymentService.Payments; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.EventBus.Distributed; |
||||
|
using Volo.Abp.Uow; |
||||
|
|
||||
|
namespace EasyAbp.EShop.Orders.Orders |
||||
|
{ |
||||
|
[UnitOfWork] |
||||
|
public class CancelPaymentEventHandler : IDistributedEventHandler<CancelPaymentEto>, ITransientDependency |
||||
|
{ |
||||
|
private readonly IOrderRepository _orderRepository; |
||||
|
private readonly IDistributedEventBus _distributedEventBus; |
||||
|
|
||||
|
public CancelPaymentEventHandler( |
||||
|
IOrderRepository orderRepository, |
||||
|
IDistributedEventBus distributedEventBus) |
||||
|
{ |
||||
|
_orderRepository = orderRepository; |
||||
|
_distributedEventBus = distributedEventBus; |
||||
|
} |
||||
|
|
||||
|
public async Task HandleEventAsync(CancelPaymentEto eventData) |
||||
|
{ |
||||
|
await _distributedEventBus.PublishAsync(new EShopPaymentCanceledEto(new EShopPaymentEto |
||||
|
{ |
||||
|
TenantId = eventData.TenantId, |
||||
|
Id = eventData.PaymentId, |
||||
|
PaymentItems = new List<EShopPaymentItemEto> |
||||
|
{ |
||||
|
new() |
||||
|
{ |
||||
|
Id = Guid.NewGuid(), |
||||
|
ItemType = PaymentsConsts.PaymentItemType, |
||||
|
ItemKey = (await _orderRepository.FirstAsync()).Id.ToString() |
||||
|
} |
||||
|
} |
||||
|
})); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -0,0 +1,44 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace EShopSample.Migrations |
||||
|
{ |
||||
|
public partial class AddedPaymentExpireInAndPaymentExpireIn : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.AddColumn<TimeSpan>( |
||||
|
name: "PaymentExpireIn", |
||||
|
table: "EasyAbpEShopProductsProductSkus", |
||||
|
type: "time", |
||||
|
nullable: true); |
||||
|
|
||||
|
migrationBuilder.AddColumn<TimeSpan>( |
||||
|
name: "PaymentExpireIn", |
||||
|
table: "EasyAbpEShopProductsProducts", |
||||
|
type: "time", |
||||
|
nullable: true); |
||||
|
|
||||
|
migrationBuilder.AddColumn<DateTime>( |
||||
|
name: "PaymentExpiration", |
||||
|
table: "EasyAbpEShopOrdersOrders", |
||||
|
type: "datetime2", |
||||
|
nullable: true); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "PaymentExpireIn", |
||||
|
table: "EasyAbpEShopProductsProductSkus"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "PaymentExpireIn", |
||||
|
table: "EasyAbpEShopProductsProducts"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "PaymentExpiration", |
||||
|
table: "EasyAbpEShopOrdersOrders"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue