Files
CMS/src/CMSMicroservice.Application/PackageCQ/Commands/VerifyPackagePurchase/VerifyPackagePurchaseCommandHandler.cs

190 lines
7.1 KiB
C#

using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.Common.Models;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Enums;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ValidationException = FluentValidation.ValidationException;
namespace CMSMicroservice.Application.PackageCQ.Commands.VerifyPackagePurchase;
public class VerifyPackagePurchaseCommandHandler
: IRequestHandler<VerifyPackagePurchaseCommand, bool>
{
private readonly IApplicationDbContext _context;
private readonly IPaymentGatewayService _paymentGateway;
private readonly ILogger<VerifyPackagePurchaseCommandHandler> _logger;
public VerifyPackagePurchaseCommandHandler(
IApplicationDbContext context,
IPaymentGatewayService paymentGateway,
ILogger<VerifyPackagePurchaseCommandHandler> logger)
{
_context = context;
_paymentGateway = paymentGateway;
_logger = logger;
}
public async Task<bool> Handle(
VerifyPackagePurchaseCommand request,
CancellationToken cancellationToken)
{
try
{
_logger.LogInformation(
"Verifying package purchase. OrderId: {OrderId}, Authority: {Authority}",
request.OrderId,
request.Authority
);
// 1. پیدا کردن سفارش
var order = await _context.UserOrders
.Include(o => o.Package)
.Include(o => o.User)
.FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
if (order == null)
{
_logger.LogWarning("Order not found: {OrderId}", request.OrderId);
throw new NotFoundException(nameof(UserOrder), request.OrderId);
}
// 2. بررسی اینکه سفارش قبلاً پرداخت نشده باشد
if (order.PaymentStatus == PaymentStatus.Success)
{
_logger.LogWarning("Order {OrderId} is already paid", request.OrderId);
return true;
}
// 3. Verify با درگاه بانکی
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
request.Authority,
request.Authority // verificationToken - در بعضی درگاه‌ها همان Authority است
);
if (!verifyResult.IsSuccess)
{
_logger.LogWarning(
"Payment verification failed for OrderId {OrderId}: {Message}",
request.OrderId,
verifyResult.Message
);
order.PaymentStatus = PaymentStatus.Reject;
await _context.SaveChangesAsync(cancellationToken);
throw new ValidationException($"تراکنش ناموفق: {verifyResult.Message}");
}
// 4. شارژ کیف پول کاربر
var wallet = await _context.UserWallets
.FirstOrDefaultAsync(w => w.UserId == order.UserId, cancellationToken);
if (wallet == null)
{
_logger.LogError("Wallet not found for UserId: {UserId}", order.UserId);
throw new NotFoundException($"کیف پول کاربر با شناسه {order.UserId} یافت نشد");
}
// شارژ Balance (موجودی عادی)
var oldBalance = wallet.Balance;
wallet.Balance += order.Amount;
_logger.LogInformation(
"Charging Balance for UserId {UserId}: {OldBalance} -> {NewBalance}",
order.UserId,
oldBalance,
wallet.Balance
);
// شارژ DiscountBalance (موجودی تخفیف)
var oldDiscountBalance = wallet.DiscountBalance;
wallet.DiscountBalance += order.Amount;
_logger.LogInformation(
"Charging DiscountBalance for UserId {UserId}: {OldBalance} -> {NewBalance}",
order.UserId,
oldDiscountBalance,
wallet.DiscountBalance
);
// 5. ثبت Transaction
var transaction = new Transaction
{
Amount = order.Amount,
Description = $"خرید پکیج از درگاه - سفارش #{order.Id}",
PaymentStatus = PaymentStatus.Success,
PaymentDate = DateTime.Now,
RefId = verifyResult.RefId,
Type = TransactionType.DepositIpg
};
_context.Transactions.Add(transaction);
await _context.SaveChangesAsync(cancellationToken);
// 6. ثبت لاگ تغییر Balance
var balanceLog = new UserWalletChangeLog
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
ChangeValue = order.Amount,
CurrentNetworkBalance = wallet.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = wallet.DiscountBalance - order.Amount, // قبل از شارژ DiscountBalance
ChangeDiscountValue = 0,
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(balanceLog, cancellationToken);
// 7. ثبت لاگ تغییر DiscountBalance
var discountLog = new UserWalletChangeLog
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
ChangeValue = 0,
CurrentNetworkBalance = wallet.NetworkBalance,
ChangeNerworkValue = 0,
CurrentDiscountBalance = wallet.DiscountBalance,
ChangeDiscountValue = order.Amount,
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(discountLog, cancellationToken);
// 8. به‌روزرسانی Order
order.TransactionId = transaction.Id;
order.PaymentStatus = PaymentStatus.Success;
order.PaymentDate = DateTime.Now;
order.PaymentMethod = PaymentMethod.IPG;
// 9. تغییر User.PackagePurchaseMethod
order.User.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
await _context.SaveChangesAsync(cancellationToken);
_logger.LogInformation(
"Package purchase verified successfully. " +
"OrderId: {OrderId}, UserId: {UserId}, TransactionId: {TransactionId}, RefId: {RefId}",
order.Id,
order.UserId,
transaction.Id,
verifyResult.RefId
);
return true;
}
catch (Exception ex)
{
_logger.LogError(
ex,
"Error in VerifyPackagePurchaseCommand. OrderId: {OrderId}",
request.OrderId
);
throw;
}
}
}