using Aop.Api.Domain; using Furion; using Furion.DatabaseAccessor; using Furion.DistributedIDGenerator; using Furion.FriendlyException; using Furion.Schedule; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.Xml; using System.Text; using System.Threading; using System.Threading.Tasks; using static Microsoft.EntityFrameworkCore.DbLoggerCategory; namespace FlexJobApi.Core.Jobs { public class RefreshEnterpriseWalletTransactionStatusJob( IRepository rep, IRepository repUserWalletTransaction, IRepository repEnterpriseWallet, IRepository repUserWallet, AlipayUtils alipayUtils ) : IJob { private readonly IRepository rep = rep; private readonly IRepository repUserWalletTransaction = repUserWalletTransaction; private readonly IRepository repEnterpriseWallet = repEnterpriseWallet; private readonly IRepository repUserWallet = repUserWallet; private readonly AlipayUtils alipayUtils = alipayUtils; [UnitOfWork(false)] public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { var env = App.GetConfig("Environment"); if (env != "Local") { var entities = await rep.AsQueryable() .Where(it => it.TransactionStatus == EnumWalletTransactionStatus.WaitPay || it.TransactionStatus == EnumWalletTransactionStatus.Dealing) .ToListAsync(); if (entities.IsNotNull()) { var ids = entities.Select(it => it.Id).ToList(); var withdraws = await repUserWalletTransaction.AsQueryable() .Where(it => it.EnterpriseWalletTransactionId.HasValue && ids.Contains(it.EnterpriseWalletTransactionId.Value)) .ToListAsync(); var userWalletIds = withdraws.DistinctSelect(it => it.WalletId).ToList(); var userWallets = await repUserWallet.AsQueryable() .Where(it => userWalletIds.Contains(it.Id)) .ToListAsync(); foreach (var entity in entities) { var response = alipayUtils.FundTransCommonQuery(new Aop.Api.Domain.AlipayFundTransCommonQueryModel { ProductCode = entity.ProductCode, BizScene = entity.BizScene, OutBizNo = entity.Code }); if (response.IsError) { entity.ErrorCode = response.ErrorCode; entity.FailReason = response.FailReason; } else { entity.OrderId = response.OrderId; entity.InflowSettleSerialNo = response.InflowSettleSerialNo; entity.SettleSerialNo = response.SettleSerialNo; entity.ReceiverOpenId = response.ReceiverOpenId; entity.ReceiverUserId = response.ReceiverUserId; entity.PayFundOrderId = response.PayFundOrderId; entity.ArrivalTimeEnd = response.ArrivalTimeEnd.ToDateTime(); entity.OrderFee = response.OrderFee.ToDecimal(); entity.ErrorCode = response.ErrorCode; entity.FailReason = response.FailReason; entity.FailInstReason = response.FailInstReason; entity.FailInstName = response.FailInstName; entity.FailInstErrorCode = response.FailInstErrorCode; entity.SubStatus = response.SubStatus; entity.TransDate = response.PayDate.ToDateTime(); entity.Status = response.Status; entity.TransactionStatus = response.Status == "SUCCESS" ? EnumWalletTransactionStatus.Success : response.Status == "DEALING" ? EnumWalletTransactionStatus.Dealing : response.Status == "REFUND" ? EnumWalletTransactionStatus.Refund : EnumWalletTransactionStatus.Fail; } await rep.UpdateNowAsync(entity); var withdraw = withdraws.FirstOrDefault(it => it.EnterpriseWalletTransactionId == entity.Id); if (withdraw != null) { var userWallet = userWallets.FirstOrDefault(it => it.Id == withdraw.WalletId); if (userWallet != null) { withdraw.ErrorCode = entity.ErrorCode; withdraw.FailReason = entity.FailReason; withdraw.EnterpriseWalletTransactionId = entity.Id; withdraw.TransactionStatus = entity.TransactionStatus; withdraw.TransDate = entity.TransDate; withdraw.ArrivalTimeEnd = entity.ArrivalTimeEnd; withdraw.ServiceFee = entity.OrderFee ?? 0; if (withdraw.TransactionStatus == EnumWalletTransactionStatus.Success) { withdraw.ActualAmount = withdraw.Amount; } else { withdraw.ActualAmount = 0; var order = new UserWalletTransaction(); order.WalletId = withdraw.WalletId; order.Type = EnumUserWalletTransactionType.Income; order.OperatorUserId = withdraw.OperatorUserId; order.OperatorTime = withdraw.OperatorTime; order.Title = $"收入-提现失败退款"; order.Amount = withdraw.Amount; order.ActualAmount = order.Amount; order.Balance = userWallet.Balance; order.AfterBalance = userWallet.Balance + order.Amount; order.TransDate = DateTime.Now; order.TransactionStatus = EnumWalletTransactionStatus.Success; await SetCode(order); await repUserWalletTransaction.InsertNowAsync(order); userWallet.Balance = order.AfterBalance; await repUserWallet.UpdateNowAsync(userWallet); } } } } var walletIds = entities .Where(it => it.TransactionStatus == EnumWalletTransactionStatus.Success) .Select(it => it.WalletId) .Distinct() .ToList(); if (walletIds.IsNotNull()) { var wallets = await repEnterpriseWallet.AsQueryable() .Where(it => walletIds.Contains(it.Id)) .ToListAsync(); foreach (var wallet in wallets) { var response = alipayUtils.FundAccountbookQuery(new AlipayFundAccountbookQueryModel { AccountBookId = wallet.AccountBookId, SceneCode = "SATF_FUND_BOOK", MerchantUserId = wallet.Code, }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); wallet.Balance = response.AvailableAmount.ToDecimal() ?? 0; await repEnterpriseWallet.UpdateAsync(wallet); } } } } } private async Task SetCode(UserWalletTransaction entity) { entity.Code = $"{DateTime.Now:yyyyMMddHHmmss}{new Random(IDGen.NextID().GetHashCode()).Next(1000, 9999)}"; var exist = await repUserWalletTransaction.AsQueryable().AsNoTracking() .AnyAsync(it => it.Code == entity.Code); if (exist) { await SetCode(entity); } } } }