Files
TakeoutSaaS.AdminApi/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/VerifyPaymentCommandHandler.cs
2026-01-04 21:22:26 +08:00

74 lines
2.6 KiB
C#

using MediatR;
using TakeoutSaaS.Application.App.Billings.Commands;
using TakeoutSaaS.Application.App.Billings.Dto;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;
namespace TakeoutSaaS.Application.App.Billings.Handlers;
/// <summary>
/// 审核支付命令处理器。
/// </summary>
public sealed class VerifyPaymentCommandHandler(
ITenantPaymentRepository paymentRepository,
ITenantBillingRepository billingRepository,
ICurrentUserAccessor currentUserAccessor)
: IRequestHandler<VerifyPaymentCommand, PaymentRecordDto>
{
/// <inheritdoc />
public async Task<PaymentRecordDto> Handle(VerifyPaymentCommand request, CancellationToken cancellationToken)
{
// 1. 校验操作者身份
if (!currentUserAccessor.IsAuthenticated || currentUserAccessor.UserId <= 0)
{
throw new BusinessException(ErrorCodes.Unauthorized, "未登录或无效的操作者身份");
}
// 2. 查询支付记录
var payment = await paymentRepository.FindByIdAsync(request.PaymentId, cancellationToken);
if (payment is null)
{
throw new BusinessException(ErrorCodes.NotFound, "支付记录不存在");
}
// 3. 查询关联账单
var billing = await billingRepository.FindByIdAsync(payment.BillingStatementId, cancellationToken);
if (billing is null)
{
throw new BusinessException(ErrorCodes.NotFound, "关联账单不存在");
}
// 4. 归一化审核备注
var normalizedNotes = string.IsNullOrWhiteSpace(request.Notes) ? null : request.Notes.Trim();
// 5. 根据审核结果更新支付与账单状态
if (request.Approved)
{
payment.Verify(currentUserAccessor.UserId);
payment.Notes = normalizedNotes;
billing.MarkAsPaid(payment.Amount, payment.TransactionNo ?? string.Empty);
}
else
{
payment.Reject(currentUserAccessor.UserId, normalizedNotes ?? string.Empty);
payment.Notes = normalizedNotes;
}
// 6. 持久化更新状态
await paymentRepository.UpdateAsync(payment, cancellationToken);
if (request.Approved)
{
await billingRepository.UpdateAsync(billing, cancellationToken);
}
// 7. 保存数据库更改
await paymentRepository.SaveChangesAsync(cancellationToken);
// 8. 返回 DTO
return payment.ToPaymentRecordDto();
}
}