lijin
2025-11-20 1d03ddefc1b5458eede592d5b5780c3c2b10dfca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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 checkExist = await channelWalletTransactionRepository.GetQueryable()
                .AnyAsync(it => it.WalletId == wallet.Id && it.OutCode == request.OutCode);
            if (checkExist) throw Oops.Oh(EnumErrorCodeType.s405, "交易单号");
 
            var transaction = new ChannelWalletTransaction();
            transaction.Type = EnumWalletTransactionType.Transfer;
            transaction.WalletId = wallet.Id;
            transaction.OutCode = request.OutCode;
            transaction.ConcurrencyLock = $"{logier.ChannelId}:{transaction.OutCode}";
            transaction.Amount = request.Amount;
            transaction.Remark = request.Remark;
            transaction.TransactionStatus = EnumWalletTransactionStatus.WaitSubmit;
            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);
            await channelWalletService.Transfer(wallet, transaction);
            return new SubmitChannelWalletTransferCommandResult
            {
                Id = transaction.Id,
                Code = transaction.Code,
                TransactionStatus = transaction.TransactionStatus,
                ErrorCode = transaction.ErrorCode,
                FailReason = transaction.FailReason,
            };
        }
    }
}