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.Text; using System.Threading; using System.Threading.Tasks; using static Microsoft.AspNetCore.Razor.Language.TagHelperMetadata; namespace FlexJobApi.Core { /// /// 完成任务结算T+1 /// public class CompleteTaskSettlementT1Job( IRepository rep, IRepository repTaskInfoUser, IRepository repEnterpriseWallet, IRepository repEnterpriseWalletTransaction, AlipayUtils alipayUtils ) : IJob { private readonly IRepository rep = rep; private readonly IRepository repTaskInfoUser = repTaskInfoUser; private readonly IRepository repEnterpriseWallet = repEnterpriseWallet; private readonly AlipayUtils alipayUtils = alipayUtils; [UnitOfWork(false)] public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { var env = App.GetConfig("Environment"); if (env != "Local") { var now = DateTime.Now; var q = rep.AsQueryable() .Where(it => it.SettlementStatus == EnumTaskSettlementStatus.InProcess); var minTime = env == "Test" ? now.AddMinutes(-5) : now.AddDays(-1); q = q.Where(it => it.SettlementStartTime.HasValue && it.SettlementStartTime < minTime); var tasks = await q.ToListAsync(); var enterpriseIds = tasks.DistinctSelect(it => it.EnterpriseId); var taskIds = tasks.DistinctSelect(it => it.Id); var taskUsers = await repTaskInfoUser .Where(it => taskIds.Contains(it.TaskInfoId) && it.SettlementStatus == EnumTaskSettlementStatus.InProcess) .ToListAsync(); var wallets = await repEnterpriseWallet.AsQueryable() .Where(it => enterpriseIds.Contains(it.EnterpriseId) && it.Access == EnumEnterpriseWalletAccess.Alipay) .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.UpdateNowAsync(wallet); } if (tasks.IsNotNull()) { foreach (var task in tasks) { var wallet = wallets.FirstOrDefault(it => it.EnterpriseId == task.EnterpriseId); task.SettlementStatus = EnumTaskSettlementStatus.Completed; task.SettlementTime = DateTime.Now; await rep.UpdateNowAsync(task); var users = taskUsers.Where(it => it.TaskInfoId == task.Id).ToList(); foreach (var user in users) { user.SettlementStatus = EnumTaskSettlementStatus.Completed; user.SettlementTime = DateTime.Now; await repTaskInfoUser.UpdateNowAsync(user); var order = new EnterpriseWalletTransaction(); order.Type = EnumEnterpriseWalletTransactionType.Recharge; order.WalletId = wallet.Id; order.TaskUserId = user.Id; order.Amount = user.ActualSettlementAmount ?? 0; order.Remark = user.SettlementRemark; order.ProductCode = "SINGLE_TRANSFER_NO_PWD"; order.BizScene = "ENTRUST_TRANSFER"; order.TransactionStatus = EnumEnterpriseWalletTransactionStatus.WaitSubmit; order.Balance = wallet.Balance; await SetCode(order); await repEnterpriseWalletTransaction.InsertNowAsync(order); var response = alipayUtils.FundTransUniTransfer(new AlipayFundTransUniTransferModel { OutBizNo = order.Code, TransAmount = order.Amount.ToString(), ProductCode = order.ProductCode, BizScene = order.BizScene, PayeeInfo = new Participant { IdentityType = "ALIPAY_LOGON_ID", Identity = user.ReceiveAccount, Name = user.ReceiveName, }, PayerInfo = new Participant { IdentityType = "ACCOUNT_BOOK_ID", Identity = wallet.AccountBookId, ExtInfo = new { agreement_no = wallet.AgreementNo, }.ToJson(), }, OrderTitle = order.Remark, Remark = order.Remark, BusinessParams = new { withdraw_timeliness = "T0" }.ToJson() }, "/api/user/enterpriseWallet/alipayFundTransOrderChangedNotify"); if (response.IsError) { order.ErrorCode = response.Code; order.FailReason = response.SubMsg ?? response.Msg; } else { order.OrderId = response.OrderId; order.PayFundOrderId = response.PayFundOrderId; order.SettleSerialNo = response.SettleSerialNo; order.TransDate = response.TransDate.ToDateTime(); order.Link = response.Link; order.Status = response.Status; order.SubStatus = response.SubStatus; order.TransactionStatus = response.Status == "SUCCESS" ? EnumEnterpriseWalletTransactionStatus.Success : response.Status == "DEALING" ? EnumEnterpriseWalletTransactionStatus.Dealing : response.Status == "REFUND" ? EnumEnterpriseWalletTransactionStatus.Refund : EnumEnterpriseWalletTransactionStatus.Fail; await repEnterpriseWalletTransaction.UpdateNowAsync(order); } } } } } } private async Task SetCode(EnterpriseWalletTransaction entity) { entity.Code = $"{DateTime.Now:yyyyMMddHHmmss}{new Random(IDGen.NextID().GetHashCode()).Next(1000, 9999)}"; var exist = await repEnterpriseWalletTransaction.AsQueryable().AsNoTracking() .AnyAsync(it => it.Code == entity.Code); if (exist) { await SetCode(entity); } } } }