using Aop.Api.Domain; using ApiTools.Core; using Consul; using Furion.FriendlyException; using Mapster; using Medallion.Threading; using MediatR; using Microsoft.EntityFrameworkCore; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ApiTools.Application { public class ChannelWalletCommandHandler( IDistributedLockProvider distributedLockProvider, ChannelWalletRepository channelWalletRepository, ChannelWalletTransactionRepository channelWalletTransactionRepository, ChannelWalletService channelWalletService ) : IRequestHandler, IRequestHandler { private readonly IDistributedLockProvider distributedLockProvider = distributedLockProvider; private readonly ChannelWalletRepository channelWalletRepository = channelWalletRepository; private readonly ChannelWalletTransactionRepository channelWalletTransactionRepository = channelWalletTransactionRepository; private readonly ChannelWalletService channelWalletService = channelWalletService; /// /// 保存渠道平安银行钱包 /// /// /// /// public async Task Handle(SaveChannelPingAnPayWalletCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var wallet = await channelWalletRepository.GetQueryable(false) .Where(it => it.ChannelId == logier.ChannelId && it.OutWalletId == request.OutWalletId) .FirstOrDefaultAsync(); if (wallet == null) { wallet = new ChannelWallet(); wallet.ChannelId = logier.ChannelId; wallet.Access = EnumWalletAccess.PingAnPay; wallet.Bank = "平安银行"; wallet.SignStatus = EnumWalletSignStatus.Apply; request.Adapt(wallet); await channelWalletRepository.SetCode(wallet); await channelWalletRepository.InsertNowAsync(wallet); } else { wallet.SignStatus = EnumWalletSignStatus.Apply; request.Adapt(wallet); await channelWalletRepository.UpdateNowAsync(wallet); } await channelWalletService.GetEnterpriseWalletBalance(wallet); return new SaveChannelPingAnPayWalletCommandResult { Id = wallet.Id, Balance = wallet.Balance, }; } /// /// 提交渠道钱包转账 /// /// /// /// public async Task Handle(SubmitChannelWalletTransferCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); await using var handle = await distributedLockProvider.TryAcquireAsync( channelWalletService.GetLockKey(logier.ChannelId.Value, request.OutWalletId), TimeSpan.FromMinutes(30)); if (handle == null) throw Oops.Oh(EnumErrorCodeType.s429); var wallet = await channelWalletRepository.GetQueryable(false) .Where(it => it.ChannelId == logier.ChannelId && it.OutWalletId == request.OutWalletId) .FirstOrDefaultAsync(); if (wallet == null) throw Oops.Oh(EnumErrorCodeType.s404, "未开通钱包"); if (wallet.SignStatus != EnumWalletSignStatus.Normal) throw Oops.Oh(EnumErrorCodeType.s404, "钱包未签约"); await channelWalletService.GetEnterpriseWalletBalance(wallet); if (request.Amount > wallet.Balance) throw Oops.Oh(EnumErrorCodeType.s404, "余额不足"); var transaction = await channelWalletTransactionRepository.GetQueryable() .Include(it => it.PingAnPay) .Where(it => it.WalletId == wallet.Id && it.OutCode == request.OutCode) .FirstOrDefaultAsync(); if (transaction == null) { transaction = new ChannelWalletTransaction(); transaction.Type = EnumWalletTransactionType.Transfer; transaction.WalletId = wallet.Id; transaction.OutCode = request.OutCode; transaction.ConcurrencyLock = $"{logier.ChannelId}:{transaction.OutCode}"; transaction.TransactionStatus = EnumWalletTransactionStatus.WaitSubmit; transaction.Amount = request.Amount; transaction.Balance = wallet.Balance; transaction.AfterBalance = wallet.Balance - transaction.Amount; transaction.OutOperatorId = request.OutOperatorId; transaction.OperatorTime = request.OperatorTime; transaction.PayerName = wallet.Name; transaction.PayerAccount = wallet.Identity; transaction.PayerBank = wallet.Bank; transaction.PayerBankBranch = wallet.BankBranch; transaction.OutReceiveId = request.OutReceiveId; transaction.ReceiveBank = request.ReceiveBank; transaction.ReceiveBankBranch = request.ReceiveBankBranch; transaction.ReceiveName = request.ReceiveName; transaction.ReceiveIdentity = request.ReceiveIdentity; transaction.ReceiveAccount = request.ReceiveAccount; transaction.Currency = request.Currency; transaction.Purpose = request.Purpose; transaction.Remark = request.Remark; await channelWalletTransactionRepository.SetCode(transaction); await channelWalletTransactionRepository.InsertNowAsync(transaction); } else { switch (transaction.TransactionStatus) { case EnumWalletTransactionStatus.WaitSubmit: throw Oops.Oh(EnumErrorCodeType.s510, "已存在正在处理的转账,请勿重复操作"); case EnumWalletTransactionStatus.WaitPay: case EnumWalletTransactionStatus.Dealing: throw Oops.Oh(EnumErrorCodeType.s510, "转账正在进行中,请勿重复操作"); case EnumWalletTransactionStatus.Success: throw Oops.Oh(EnumErrorCodeType.s510, "已转账,请勿重复操作"); case EnumWalletTransactionStatus.Refund: case EnumWalletTransactionStatus.Fail: transaction.TransactionStatus = EnumWalletTransactionStatus.WaitSubmit; transaction.Amount = request.Amount; transaction.Balance = wallet.Balance; transaction.AfterBalance = wallet.Balance - transaction.Amount; transaction.OutOperatorId = request.OutOperatorId; transaction.OperatorTime = request.OperatorTime; transaction.PayerName = wallet.Name; transaction.PayerAccount = wallet.Identity; transaction.PayerBank = wallet.Bank; transaction.PayerBankBranch = wallet.BankBranch; transaction.OutReceiveId = request.OutReceiveId; transaction.ReceiveBank = request.ReceiveBank; transaction.ReceiveBankBranch = request.ReceiveBankBranch; transaction.ReceiveName = request.ReceiveName; transaction.ReceiveIdentity = request.ReceiveIdentity; transaction.ReceiveAccount = request.ReceiveAccount; transaction.Currency = request.Currency; transaction.Purpose = request.Purpose; transaction.Remark = request.Remark; await channelWalletTransactionRepository.UpdateNowAsync(transaction); break; default: break; } } await channelWalletService.Transfer(wallet, transaction); return new SubmitChannelWalletTransferCommandResult { Id = transaction.Id, Code = transaction.Code, TransactionStatus = transaction.TransactionStatus, ErrorCode = transaction.ErrorCode, FailReason = transaction.FailReason, }; } } }