refactor(commerce): split administration services

This commit is contained in:
2026-08-04 09:29:20 +08:00
parent 4d85463a87
commit 0bd075e20d
29 changed files with 1187 additions and 952 deletions

View File

@@ -0,0 +1,72 @@
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Tiku.Application.Commerce;
using Tiku.Application.Jobs;
using Tiku.Domain.Commerce;
namespace Tiku.Infrastructure.Commerce;
internal sealed partial class RefundAdministrationService
{
public async Task<CommerceRefundRequest> ProcessRefundNotificationAsync(
Guid tenantId,
RefundNotificationCommand command,
CancellationToken cancellationToken = default)
{
var provider = NormalizeProvider(command.Provider);
var refund = await dbContext.CommerceRefundRequests.SingleOrDefaultAsync(
item => item.TenantId == tenantId && item.RefundNo == command.RefundNo,
cancellationToken) ?? throw new CommerceException("Refund request was not found.", "refund_not_found");
var eventId = string.IsNullOrWhiteSpace(command.EventId)
? $"{provider}:{command.RefundNo}:{command.Status}"
: command.EventId.Trim();
var duplicate = await dbContext.PaymentEvents.AnyAsync(
item => item.TenantId == tenantId &&
item.Provider == provider &&
item.EventType == "refund" &&
item.EventId == eventId,
cancellationToken);
if (duplicate) return refund;
dbContext.PaymentEvents.Add(new PaymentEvent
{
TenantId = tenantId,
Provider = provider,
EventType = "refund",
EventId = eventId,
SignatureValid = true,
Payload = JsonObjectOrDefault(command.Payload),
ProcessedAt = DateTimeOffset.UtcNow
});
var fromStatus = refund.Status;
if (fromStatus != command.Status && IsAllowedRefundTransition(fromStatus, command.Status))
{
refund.Status = command.Status;
refund.ProviderRefundNo = string.IsNullOrWhiteSpace(command.ProviderRefundNo)
? refund.ProviderRefundNo
: command.ProviderRefundNo.Trim();
if (command.Status == CommerceRefundStatus.Succeeded)
{
refund.SucceededAt = DateTimeOffset.UtcNow;
await ApplyRefundToOrderAsync(refund, cancellationToken);
}
else if (command.Status == CommerceRefundStatus.Failed)
{
refund.FailedAt = DateTimeOffset.UtcNow;
}
dbContext.CommerceRefundEvents.Add(new CommerceRefundEvent
{
TenantId = tenantId,
RefundRequestId = refund.Id,
FromStatus = fromStatus,
ToStatus = command.Status,
EventType = "provider_notify",
Details = JsonObjectOrDefault(command.Payload)
});
}
await dbContext.SaveChangesAsync(cancellationToken);
return refund;
}
}