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<SaveChannelPingAnPayWalletCommand, SaveChannelPingAnPayWalletCommandResult>,
|
IRequestHandler<SubmitChannelWalletTransferCommand, SubmitChannelWalletTransferCommandResult>
|
{
|
private readonly IDistributedLockProvider distributedLockProvider = distributedLockProvider;
|
private readonly ChannelWalletRepository channelWalletRepository = channelWalletRepository;
|
private readonly ChannelWalletTransactionRepository channelWalletTransactionRepository = channelWalletTransactionRepository;
|
private readonly ChannelWalletService channelWalletService = channelWalletService;
|
|
/// <summary>
|
/// 保存渠道平安银行钱包
|
/// </summary>
|
/// <param name="request"></param>
|
/// <param name="cancellationToken"></param>
|
/// <returns></returns>
|
public async Task<SaveChannelPingAnPayWalletCommandResult> 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,
|
};
|
}
|
|
/// <summary>
|
/// 提交渠道钱包转账
|
/// </summary>
|
/// <param name="request"></param>
|
/// <param name="cancellationToken"></param>
|
/// <returns></returns>
|
public async Task<SubmitChannelWalletTransferCommandResult> 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()
|
.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,
|
};
|
}
|
}
|
}
|