FlexJobApi.Core/Entities/UserServer/Enterprises/EnterpriseWallet.cs
@@ -28,6 +28,16 @@ public EnumEnterpriseWalletAccess Access { get; set; } /// <summary> /// 账号 /// </summary> public string Account { get; set; } /// <summary> /// 商户Id /// </summary> public string MerchantId { get; set; } /// <summary> /// 余额 /// </summary> public decimal Balance { get; set; } FlexJobApi.Core/Enums/Common/EnumSmsTemplateCode.cs
@@ -90,6 +90,17 @@ /// 818钱包开通 /// 验证码${code},用户您好,您正在进行平台钱包开通,该验证码5分钟内有效,请勿泄露于他人。 /// </summary> BankWalletAccountOpen BankWalletAccountOpen, /// <summary> /// 电子签邀约 /// ${name}请您点击签约http://testwww.81812333.com/sg/${code} /// </summary> InviteElectronSign, /// <summary> /// 签约地址 /// ${name}请您点击签约https://testwww.81812333.com/sgu/${code} /// </summary> ElectronSignUrl, } } FlexJobApi.Core/Enums/Users/EnumEnterpriseWalletExpandindirectOrderStatus.cs
@@ -12,11 +12,15 @@ public enum EnumEnterpriseWalletExpandindirectOrderStatus { /// <summary> /// 未进件 /// </summary> Wait = 1, /// <summary> /// 审批中 /// </summary> PROCESSING = 10, /// <summary> /// 已生效 /// 已进件 /// </summary> VALID = 20, /// <summary> FlexJobApi.Core/Enums/Users/EnumEnterpriseWalletSignStatus.cs
@@ -12,6 +12,10 @@ public enum EnumEnterpriseWalletSignStatus { /// <summary> /// 未签约 /// </summary> Wait = 1, /// <summary> /// 申请中 /// </summary> Apply = 10, FlexJobApi.Core/FlexJobApi.Core.xml
@@ -2050,6 +2050,16 @@ 通道 </summary> </member> <member name="P:FlexJobApi.Core.EnterpriseWallet.Account"> <summary> 账号 </summary> </member> <member name="P:FlexJobApi.Core.EnterpriseWallet.MerchantId"> <summary> 商户Id </summary> </member> <member name="P:FlexJobApi.Core.EnterpriseWallet.Balance"> <summary> 余额 @@ -3697,6 +3707,18 @@ 验证码${code},用户您好,您正在进行平台钱包开通,该验证码5分钟内有效,请勿泄露于他人。 </summary> </member> <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.InviteElectronSign"> <summary> 电子签邀约 ${name}请您点击签约http://testwww.81812333.com/sg/${code} </summary> </member> <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.ElectronSignUrl"> <summary> 签约地址 ${name}请您点击签约https://testwww.81812333.com/sgu/${code} </summary> </member> <member name="T:FlexJobApi.Core.EnumValidationTypes"> <summary> 验证类型 @@ -4142,6 +4164,11 @@ 企业钱包代进件单状态 </summary> </member> <member name="F:FlexJobApi.Core.EnumEnterpriseWalletExpandindirectOrderStatus.Wait"> <summary> 未进件 </summary> </member> <member name="F:FlexJobApi.Core.EnumEnterpriseWalletExpandindirectOrderStatus.PROCESSING"> <summary> 审批中 @@ -4149,7 +4176,7 @@ </member> <member name="F:FlexJobApi.Core.EnumEnterpriseWalletExpandindirectOrderStatus.VALID"> <summary> 已生效 已进件 </summary> </member> <member name="F:FlexJobApi.Core.EnumEnterpriseWalletExpandindirectOrderStatus.INVALID"> @@ -4170,6 +4197,11 @@ <member name="T:FlexJobApi.Core.EnumEnterpriseWalletSignStatus"> <summary> 企业钱包签约状态 </summary> </member> <member name="F:FlexJobApi.Core.EnumEnterpriseWalletSignStatus.Wait"> <summary> 未签约 </summary> </member> <member name="F:FlexJobApi.Core.EnumEnterpriseWalletSignStatus.Apply"> @@ -8201,11 +8233,6 @@ 任务Id </summary> </member> <member name="P:FlexJobApi.Core.GetSettlementTaskUsersQuery.Keywords"> <summary> 关键字 </summary> </member> <member name="P:FlexJobApi.Core.GetSettlementTaskUsersQuery.SettlementOrderUrl"> <summary> 结算单地址 @@ -8214,6 +8241,11 @@ <member name="T:FlexJobApi.Core.GetSettlementTaskUsersQueryResult"> <summary> 查询结算任务分页列表数据 </summary> </member> <member name="P:FlexJobApi.Core.GetSettlementTaskUsersQueryResult.Data"> <summary> 结算名单 </summary> </member> <member name="P:FlexJobApi.Core.GetSettlementTaskUsersQueryResult.Errors"> @@ -9670,6 +9702,16 @@ 签署合同长链接 </summary> </member> <member name="T:FlexJobApi.Core.SendInviteElectronSignSmsCommand"> <summary> 发送邀请签约短信 </summary> </member> <member name="P:FlexJobApi.Core.SendInviteElectronSignSmsCommand.Ids"> <summary> Id </summary> </member> <member name="T:FlexJobApi.Core.StopElectronSignCommand"> <summary> 灵工解约 @@ -10633,6 +10675,16 @@ 通道 </summary> </member> <member name="P:FlexJobApi.Core.OpenEnterpriseWalletCommand.Account"> <summary> 账号 </summary> </member> <member name="P:FlexJobApi.Core.OpenEnterpriseWalletCommand.MerchantId"> <summary> 商户Id </summary> </member> <member name="T:FlexJobApi.Core.OpenEnterpriseWalletCommandResult"> <summary> 开通企业钱包 @@ -10843,6 +10895,16 @@ 通道 </summary> </member> <member name="P:FlexJobApi.Core.GetEnterpriseWalletQueryResult.Account"> <summary> 账号 </summary> </member> <member name="P:FlexJobApi.Core.GetEnterpriseWalletQueryResult.MerchantId"> <summary> 商户Id </summary> </member> <member name="P:FlexJobApi.Core.GetEnterpriseWalletQueryResult.Code"> <summary> 协议号 @@ -10871,6 +10933,11 @@ <member name="P:FlexJobApi.Core.GetEnterpriseWalletQueryResult.SignStatus"> <summary> 签约状态 </summary> </member> <member name="P:FlexJobApi.Core.GetEnterpriseWalletQueryResult.ExpandindirectOrderStatus"> <summary> 待进件状态 </summary> </member> <member name="T:FlexJobApi.Core.GetEnterpriseWalletTransactionQuery"> @@ -15208,6 +15275,21 @@ 验证码 </summary> </member> <member name="T:FlexJobApi.Core.SendSmsModel"> <summary> 发送短信 </summary> </member> <member name="P:FlexJobApi.Core.SendSmsModel.PhoneNumber"> <summary> 手机号码 </summary> </member> <member name="P:FlexJobApi.Core.SendSmsModel.TemplateCode"> <summary> 短信模板编号 </summary> </member> <member name="T:FlexJobApi.Core.SendVerifyCodeModel"> <summary> 发送验证码 FlexJobApi.Core/Jobs/CompleteTaskSettlementT1Job.cs
@@ -34,115 +34,116 @@ [UnitOfWork(false)] public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { var now = DateTime.Now; var env = App.GetConfig<string>("Environment"); var q = rep.AsQueryable() .Where(it => it.SettlementStatus == EnumTaskSettlementStatus.InProcess); var minTime = env == "Local" ? now.AddMinutes(-1) : 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) if (env != "Local") { var response = alipayUtils.FundAccountbookQuery(new AlipayFundAccountbookQueryModel 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) { 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) var response = alipayUtils.FundAccountbookQuery(new AlipayFundAccountbookQueryModel { user.SettlementStatus = EnumTaskSettlementStatus.Completed; user.SettlementTime = DateTime.Now; await repTaskInfoUser.UpdateNowAsync(user); 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 order = new EnterpriseWalletTransaction(); order.Type = EnumEnterpriseWalletTransactionType.Recharge; order.WalletId = wallet.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 var users = taskUsers.Where(it => it.TaskInfoId == task.Id).ToList(); foreach (var user in users) { OutBizNo = order.Code, TransAmount = order.Amount.ToString(), ProductCode = order.ProductCode, BizScene = order.BizScene, PayeeInfo = new Participant 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.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 { IdentityType = "ALIPAY_LOGON_ID", Identity = user.ReceiveAccount, Name = user.ReceiveName, }, PayerInfo = new Participant { IdentityType = "ACCOUNT_BOOK_ID", Identity = wallet.AccountBookId, ExtInfo = new OutBizNo = order.Code, TransAmount = order.Amount.ToString(), ProductCode = order.ProductCode, BizScene = order.BizScene, PayeeInfo = new Participant { agreement_no = wallet.AgreementNo, }.ToJson(), }, OrderTitle = order.Remark, Remark = order.Remark, BusinessParams = new 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) { 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); 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); } } } } FlexJobApi.Core/Jobs/RefreshEnterpriseWalletStatusJob.cs
@@ -1,4 +1,5 @@ using Aop.Api.Domain; using Furion; using Furion.DatabaseAccessor; using Furion.FriendlyException; using Furion.Schedule; @@ -24,92 +25,96 @@ [UnitOfWork(false)] public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { var entities = await rep.AsQueryable() var env = App.GetConfig<string>("Environment"); if (env != "Local") { var entities = await rep.AsQueryable() .Include(it => it.Enterprise) .Where(it => it.Access == EnumEnterpriseWalletAccess.Alipay && (it.SignStatus == EnumEnterpriseWalletSignStatus.Apply || it.AccountBookStatus == null)) .ToListAsync(); foreach (var entity in entities) { var update = false; if (entity.Access == EnumEnterpriseWalletAccess.Alipay) foreach (var entity in entities) { if (entity.SignStatus == EnumEnterpriseWalletSignStatus.Apply) var update = false; if (entity.Access == EnumEnterpriseWalletAccess.Alipay) { var response = alipayUtils.UserAgreementQuery(new Aop.Api.Domain.AlipayUserAgreementQueryModel if (entity.SignStatus == EnumEnterpriseWalletSignStatus.Apply) { PersonalProductCode = entity.PersonalProductCode, SignScene = entity.SignScene, ExternalAgreementNo = entity.Code, ThirdPartyType = entity.ThirdPartyType, }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); entity.AgreementNo = response.AgreementNo; entity.SignTime = response.SignTime.ToDateTime(); entity.ValidTime = response.ValidTime.ToDateTime(); entity.InvalidTime = response.InvalidTime.ToDateTime(); entity.SignStatus = response.Status == "TEMP" ? EnumEnterpriseWalletSignStatus.Apply : response.Status == "NORMAL" ? EnumEnterpriseWalletSignStatus.Normal : response.Status == "STOP" ? EnumEnterpriseWalletSignStatus.Stop : throw Oops.Oh(EnumErrorCodeType.s510, "状态异常"); entity.PricipalType = response.PricipalType; entity.AlipayLogonId = response.AlipayLogonId; entity.PrincipalId = response.PrincipalId; entity.PrincipalOpenId = response.PrincipalOpenId; entity.ZmOpenId = response.ZmOpenId; entity.CreditAuthMode = response.CreditAuthMode; update = true; } if (entity.SignStatus == EnumEnterpriseWalletSignStatus.Normal && entity.AccountBookStatus != EnumEnterpriseWalletAccountBookStatus.Normal) { var response = alipayUtils.FundAccountbookCreate(new Aop.Api.Domain.AlipayFundAccountbookCreateModel { MerchantUserId = entity.Code, MerchantUserType = "BUSINESS_ORGANIZATION", SceneCode = "SATF_FUND_BOOK", ExtInfo = new var response = alipayUtils.UserAgreementQuery(new Aop.Api.Domain.AlipayUserAgreementQueryModel { agreement_no = entity.AgreementNo, cert_no = entity.Enterprise.SocietyCreditCode }.ToJson() }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); entity.AccountBookId = response.AccountBookId; entity.BankAccName = response.ExtCardInfo.BankAccName; entity.CardBank = response.ExtCardInfo.CardBank; entity.CardBranch = response.ExtCardInfo.CardBranch; entity.CardDeposit = response.ExtCardInfo.CardDeposit; entity.CardLocation = response.ExtCardInfo.CardLocation; entity.CardNo = response.ExtCardInfo.CardNo; entity.AccountBookStatus = response.ExtCardInfo.Status == "A" ? EnumEnterpriseWalletAccountBookStatus.Normal : EnumEnterpriseWalletAccountBookStatus.Exception; update = true; } PersonalProductCode = entity.PersonalProductCode, SignScene = entity.SignScene, ExternalAgreementNo = entity.Code, ThirdPartyType = entity.ThirdPartyType, }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); entity.AgreementNo = response.AgreementNo; entity.SignTime = response.SignTime.ToDateTime(); entity.ValidTime = response.ValidTime.ToDateTime(); entity.InvalidTime = response.InvalidTime.ToDateTime(); entity.SignStatus = response.Status == "TEMP" ? EnumEnterpriseWalletSignStatus.Apply : response.Status == "NORMAL" ? EnumEnterpriseWalletSignStatus.Normal : response.Status == "STOP" ? EnumEnterpriseWalletSignStatus.Stop : throw Oops.Oh(EnumErrorCodeType.s510, "状态异常"); entity.PricipalType = response.PricipalType; entity.AlipayLogonId = response.AlipayLogonId; entity.PrincipalId = response.PrincipalId; entity.PrincipalOpenId = response.PrincipalOpenId; entity.ZmOpenId = response.ZmOpenId; entity.CreditAuthMode = response.CreditAuthMode; update = true; } if (entity.AccountBookStatus == EnumEnterpriseWalletAccountBookStatus.Normal) { var response = alipayUtils.FundAccountbookQuery(new AlipayFundAccountbookQueryModel if (entity.SignStatus == EnumEnterpriseWalletSignStatus.Normal && entity.AccountBookStatus != EnumEnterpriseWalletAccountBookStatus.Normal) { AccountBookId = entity.AccountBookId, SceneCode = "SATF_FUND_BOOK", MerchantUserId = entity.Code, }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); entity.Balance = response.AvailableAmount.ToDecimal() ?? 0; update = true; } } var response = alipayUtils.FundAccountbookCreate(new Aop.Api.Domain.AlipayFundAccountbookCreateModel { MerchantUserId = entity.Code, MerchantUserType = "BUSINESS_ORGANIZATION", SceneCode = "SATF_FUND_BOOK", ExtInfo = new { agreement_no = entity.AgreementNo, cert_no = entity.Enterprise.SocietyCreditCode }.ToJson() }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); entity.AccountBookId = response.AccountBookId; entity.BankAccName = response.ExtCardInfo.BankAccName; entity.CardBank = response.ExtCardInfo.CardBank; entity.CardBranch = response.ExtCardInfo.CardBranch; entity.CardDeposit = response.ExtCardInfo.CardDeposit; entity.CardLocation = response.ExtCardInfo.CardLocation; entity.CardNo = response.ExtCardInfo.CardNo; entity.AccountBookStatus = response.ExtCardInfo.Status == "A" ? EnumEnterpriseWalletAccountBookStatus.Normal : EnumEnterpriseWalletAccountBookStatus.Exception; update = true; } if (update) { await rep.UpdateAsync(entity); if (entity.AccountBookStatus == EnumEnterpriseWalletAccountBookStatus.Normal) { var response = alipayUtils.FundAccountbookQuery(new AlipayFundAccountbookQueryModel { AccountBookId = entity.AccountBookId, SceneCode = "SATF_FUND_BOOK", MerchantUserId = entity.Code, }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); entity.Balance = response.AvailableAmount.ToDecimal() ?? 0; update = true; } } if (update) { await rep.UpdateAsync(entity); } } } } FlexJobApi.Core/Jobs/RefreshEnterpriseWalletTransactionStatusJob.cs
@@ -1,4 +1,5 @@ using Aop.Api.Domain; using Furion; using Furion.DatabaseAccessor; using Furion.FriendlyException; using Furion.Schedule; @@ -25,70 +26,74 @@ public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { var entities = await rep.AsQueryable() var env = App.GetConfig<string>("Environment"); if (env != "Local") { var entities = await rep.AsQueryable() .Where(it => it.TransactionStatus == EnumEnterpriseWalletTransactionStatus.WaitPay || it.TransactionStatus == EnumEnterpriseWalletTransactionStatus.Dealing) .ToListAsync(); if (entities.IsNotNull()) { foreach (var entity in entities) if (entities.IsNotNull()) { var response = alipayUtils.FundTransCommonQuery(new Aop.Api.Domain.AlipayFundTransCommonQueryModel foreach (var entity in entities) { ProductCode = entity.ProductCode, BizScene = entity.BizScene, OutBizNo = entity.Code }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); 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" ? EnumEnterpriseWalletTransactionStatus.Success : response.Status == "DEALING" ? EnumEnterpriseWalletTransactionStatus.Dealing : response.Status == "REFUND" ? EnumEnterpriseWalletTransactionStatus.Refund : response.Status == "FAIL" ? EnumEnterpriseWalletTransactionStatus.Fail : throw Oops.Oh(EnumErrorCodeType.s510, $"未识别的状态:{response.Status}"); await rep.UpdateAsync(entity); } var walletIds = entities .Where(it => it.TransactionStatus == EnumEnterpriseWalletTransactionStatus.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 var response = alipayUtils.FundTransCommonQuery(new Aop.Api.Domain.AlipayFundTransCommonQueryModel { AccountBookId = wallet.AccountBookId, SceneCode = "SATF_FUND_BOOK", MerchantUserId = wallet.Code, ProductCode = entity.ProductCode, BizScene = entity.BizScene, OutBizNo = entity.Code }); if (response.IsError) throw Oops.Oh(EnumErrorCodeType.s510, response.SubMsg ?? response.Msg); wallet.Balance = response.AvailableAmount.ToDecimal() ?? 0; await repEnterpriseWallet.UpdateAsync(wallet); 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" ? EnumEnterpriseWalletTransactionStatus.Success : response.Status == "DEALING" ? EnumEnterpriseWalletTransactionStatus.Dealing : response.Status == "REFUND" ? EnumEnterpriseWalletTransactionStatus.Refund : response.Status == "FAIL" ? EnumEnterpriseWalletTransactionStatus.Fail : throw Oops.Oh(EnumErrorCodeType.s510, $"未识别的状态:{response.Status}"); await rep.UpdateAsync(entity); } var walletIds = entities .Where(it => it.TransactionStatus == EnumEnterpriseWalletTransactionStatus.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); } } } } FlexJobApi.Core/Models/FlexJobServer/TaskUsers/Queries/GetSettlementTaskUsersQuery.cs
@@ -12,17 +12,12 @@ /// 查询结算名单分页列表数据 /// </summary> [Resource([EnumResourceController.FlexJobServerTaskUser])] public class GetSettlementTaskUsersQuery : PagedListQuery<GetSettlementTaskUsersQueryResult, GetSettlementTaskUsersQueryResultItem> public class GetSettlementTaskUsersQuery : IRequest<GetSettlementTaskUsersQueryResult> { /// <summary> /// 任务Id /// </summary> public Guid TaskInfoId { get; set; } /// <summary> /// 关键字 /// </summary> public string Keywords { get; set; } /// <summary> /// 结算单地址 @@ -33,9 +28,13 @@ /// <summary> /// 查询结算任务分页列表数据 /// </summary> public class GetSettlementTaskUsersQueryResult : PagedListQueryResult<GetSettlementTaskUsersQueryResultItem> public class GetSettlementTaskUsersQueryResult { /// <summary> /// 结算名单 /// </summary> public List<GetSettlementTaskUsersQueryResultItem> Data { get; set; } /// <summary> /// 错误信息 /// </summary> public List<GetSettlementTaskUsersQueryResultError> Errors { get; set; } FlexJobApi.Core/Models/UserServer/EnterpriseEmployees/Commands/SendInviteElectronSignSmsCommand.cs
New file @@ -0,0 +1,26 @@ using MediatR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core { /// <summary> /// 发送邀请签约短信 /// </summary> [Resource([EnumResourceController.UserServerEnterpriseEmployee])] public class SendInviteElectronSignSmsCommand : IRequest<int> { public SendInviteElectronSignSmsCommand() { Ids = []; } /// <summary> /// Id /// </summary> public List<Guid> Ids { get; set; } } } FlexJobApi.Core/Models/UserServer/EnterpriseWallets/Commands/OpenEnterpriseWalletCommand.cs
@@ -22,6 +22,15 @@ /// </summary> public EnumEnterpriseWalletAccess Access { get; set; } /// <summary> /// 账号 /// </summary> public string Account { get; set; } /// <summary> /// 商户Id /// </summary> public string MerchantId { get; set; } } /// <summary> FlexJobApi.Core/Models/UserServer/EnterpriseWallets/Queries/GetEnterpriseWalletQuery.cs
@@ -34,12 +34,22 @@ /// <summary> /// 钱包Id /// </summary> public Guid Id { get; set; } public Guid? Id { get; set; } /// <summary> /// 通道 /// </summary> public EnumEnterpriseWalletAccess Access { get; set; } /// <summary> /// 账号 /// </summary> public string Account { get; set; } /// <summary> /// 商户Id /// </summary> public string MerchantId { get; set; } /// <summary> /// 协议号 @@ -70,5 +80,10 @@ /// 签约状态 /// </summary> public EnumEnterpriseWalletSignStatus SignStatus { get; set; } /// <summary> /// 待进件状态 /// </summary> public EnumEnterpriseWalletExpandindirectOrderStatus ExpandindirectOrderStatus { get; set; } } } FlexJobApi.Core/Utils/SmsUtils/SendSmsModel.cs
New file @@ -0,0 +1,28 @@ using Furion.DataValidation; using MediatR; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core { /// <summary> /// 发送短信 /// </summary> public class SendSmsModel { /// <summary> /// 手机号码 /// </summary> [Required, DataValidation(ValidationTypes.PhoneNumber)] public string PhoneNumber { get; set; } /// <summary> /// 短信模板编号 /// </summary> public EnumSmsTemplateCode TemplateCode { get; set; } } } FlexJobApi.Core/Utils/SmsUtils/SmsUtils.cs
@@ -36,6 +36,17 @@ this.aliyunSmsUtils = aliyunSmsUtils; } public async Task<Guid> Send(SendSmsModel model, object templateParam, CancellationToken cancellationToken = default) { var entity = new SmsLog(); model.Adapt(entity); entity.Expiry = DateTime.Now.AddMinutes(10); entity.TemplateParam = templateParam.ToJson(); await aliyunSmsUtils.SendAsync(model.PhoneNumber, model.TemplateCode, entity.TemplateParam, cancellationToken); await rep.InsertAsync(entity); return entity.Id; } public async Task<Guid> SendVerifyCode(SendVerifyCodeModel model, CancellationToken cancellationToken = default) { var code = new Random().Next(100000, 999999).ToString(); FlexJobApi.FlexJobServer.Application/TaskUsers/Queries/TaskUserQueryHandler.cs
@@ -168,9 +168,10 @@ public async Task<GetSettlementTaskUsersQueryResult> Handle(GetSettlementTaskUsersQuery request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var list = new GetSettlementTaskUsersQueryResult(); var q = rep.AsQueryable().AsNoTracking() .Where(it => it.TaskInfoId == request.TaskInfoId); var s = q list.Data = q .Select(it => new GetSettlementTaskUsersQueryResultItem { Id = it.Id, @@ -184,8 +185,8 @@ SettlementAmount = it.SettlementAmount, ActualSettlementAmount = it.ActualSettlementAmount, SettlementTime = it.SettlementTime }); var list = await request.PageModel.GetPagedListAsync<GetSettlementTaskUsersQueryResult, GetSettlementTaskUsersQueryResultItem>(s, cancellationToken); }) .ToList(); var successList = new List<GetSettlementTaskUsersQueryResultExcelRow>(); if (request.SettlementOrderUrl.IsNotNull()) @@ -270,14 +271,9 @@ } } var pagedList = await list.Data list.Data = list.Data .Where(it => successList.Any(s => s.Identity == it.Identity)) .AsQueryable() .ToPagedListAsync(request.PageModel.Page, request.PageModel.Rows, cancellationToken); list.PageModel = request.PageModel.Adapt<PagedListQueryResultPageModel>(); list.PageModel.TotalCount = pagedList.TotalCount; list.PageModel.TotalPage = pagedList.TotalPages; list.Data = pagedList.Items.ToList(); .ToList(); return list; } FlexJobApi.UserServer.Application/ElectronSign/Commands/PersonalUserRealCommandHandler.cs
@@ -191,7 +191,7 @@ faceRealUrl: result.Result.FaceUrl); await repUser.UpdateAsync(user); return result.Result.FaceUrl; return result.Result.FaceUrl.Replace("https://h5-v2.kych5.com", "https://wx05.ssqian.com.cn"); } /// <summary> FlexJobApi.UserServer.Application/EnterpriseEmployees/Commands/EnterpriseEmployeesCommandHandler.cs
@@ -30,6 +30,7 @@ /// 灵工命令处理器 /// </summary> public class EnterpriseEmployeesCommandHandler( SmsUtils smsUtils, IMediator mediator, IRepository<EnterpriseEmployee> rep, IRepository<User> repUser, @@ -45,8 +46,10 @@ IRequestHandler<InviteElectronSignCommand, int>, IRequestHandler<PersonalUserElectronSignCommand, PersonalUserElectronSignCommandResult>, IRequestHandler<EnterpriseUserElectronSignCommand, EnterpriseUserElectronSignCommandResult>, IRequestHandler<StopElectronSignCommand, int> IRequestHandler<StopElectronSignCommand, int>, IRequestHandler<SendInviteElectronSignSmsCommand, int> { private readonly SmsUtils smsUtils = smsUtils; private readonly IMediator mediator = mediator; private readonly IRepository<EnterpriseEmployee> rep = rep; private readonly IRepository<User> repUser = repUser; @@ -266,6 +269,39 @@ } /// <summary> /// 发送邀请签约短信 /// </summary> /// <param name="request"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task<int> Handle(SendInviteElectronSignSmsCommand request, CancellationToken cancellationToken) { var logier = JwtUtils.GetCurrentLogier(); var entities = await rep.AsQueryable() .Include(it => it.Enterprise) .Include(it => it.ContractTemplate) .Where(it => it.EnterpriseId == logier.EnterpriseId && request.Ids.Contains(it.Id) && it.UserSignContractStatus == EnumTaskUserSignContractStatus.Wait) .ToListAsync(); foreach (var entity in entities) { await smsUtils.Send(new SendSmsModel { PhoneNumber = entity.ContactPhoneNumber, TemplateCode = EnumSmsTemplateCode.InviteElectronSign, }, new { name = entity.Enterprise.EnterpriseName, code = entity.ContractTemplate.Code }); } return entities.Count; } /// <summary> /// 个人用户签约 /// </summary> /// <param name="request"></param> @@ -332,7 +368,11 @@ { throw Oops.Oh(EnumErrorCodeType.s510, result?.Message ?? "签约失败"); } return result.Result.Adapt<PersonalUserElectronSignCommandResult>(); var model = result.Result.Adapt<PersonalUserElectronSignCommandResult>(); model.SignContractLongUrl = model.SignContractLongUrl .Replace("https://openapi.bestsign.info:443", "https://wx115.bestsign.info") .Replace("https://openapi.bestsign.cn:443", "https://wx115.bestsign.cn"); return model; } /// <summary> @@ -383,7 +423,11 @@ { throw Oops.Oh(EnumErrorCodeType.s510, result?.Message ?? "签约失败"); } return result.Result.Adapt<EnterpriseUserElectronSignCommandResult>(); var model = result.Result.Adapt<EnterpriseUserElectronSignCommandResult>(); model.SignContractLongUrl = model.SignContractLongUrl .Replace("https://openapi.bestsign.info:443", "https://wx115.bestsign.info") .Replace("https://openapi.bestsign.cn:443", "https://wx115.bestsign.cn"); return model; } /// <summary> @@ -433,5 +477,6 @@ return entities.Count; } } } FlexJobApi.UserServer.Application/EnterpriseWallets/Commands/EnterpriseWalletCommandHandler.cs
@@ -59,6 +59,8 @@ entity = new EnterpriseWallet(); entity.EnterpriseId = request.EnterpriseId!.Value; entity.Access = EnumEnterpriseWalletAccess.Alipay; entity.Account = request.Account; entity.MerchantId = request.MerchantId; entity.PersonalProductCode = "FUND_SAFT_SIGN_WITHHOLDING_P"; entity.SignScene = "INDUSTRY|SATF_ACC"; entity.ThirdPartyType = "PARTNER"; @@ -70,6 +72,8 @@ else { if (entity.SignStatus == EnumEnterpriseWalletSignStatus.Normal) throw Oops.Oh(EnumErrorCodeType.s510, "已签约"); entity.Account = request.Account; entity.MerchantId = request.MerchantId; entity.SignStatus = EnumEnterpriseWalletSignStatus.Apply; await rep.UpdateAsync(entity); } FlexJobApi.UserServer.Application/EnterpriseWallets/Queries/EnterpriseWalletQueryHandler.cs
@@ -21,6 +21,7 @@ public class EnterpriseWalletQueryHandler( IRepository<EnterpriseWallet> rep, IRepository<EnterpriseWalletTransaction> repEnterpriseWalletTransaction, IRepository<EnterpriseWalletExpandindirectOrder> repEnterpriseWalletExpandindirectOrder, IRepository<Enterprise> repEnterprise, AlipayUtils alipayUtils ) : @@ -29,6 +30,7 @@ { private readonly IRepository<EnterpriseWallet> rep = rep; private readonly IRepository<EnterpriseWalletTransaction> repEnterpriseWalletTransaction = repEnterpriseWalletTransaction; private readonly IRepository<EnterpriseWalletExpandindirectOrder> repEnterpriseWalletExpandindirectOrder = repEnterpriseWalletExpandindirectOrder; private readonly IRepository<Enterprise> repEnterprise = repEnterprise; private readonly AlipayUtils alipayUtils = alipayUtils; @@ -53,7 +55,15 @@ var entity = await rep.AsQueryable() .Where(it => it.EnterpriseId == request.EnterpriseId && it.Access == request.Access) .FirstOrDefaultAsync(); if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "企业钱包"); if (entity == null) { return new GetEnterpriseWalletQueryResult { Access = request.Access, SignStatus = EnumEnterpriseWalletSignStatus.Wait, ExpandindirectOrderStatus = EnumEnterpriseWalletExpandindirectOrderStatus.Wait }; } var update = false; if (entity.Access == EnumEnterpriseWalletAccess.Alipay) { @@ -134,6 +144,19 @@ } var model = entity.Adapt<GetEnterpriseWalletQueryResult>(); var expandindirectOrder = await repEnterpriseWalletExpandindirectOrder.AsQueryable().AsNoTracking() .OrderByDescending(it => it.CreatedTime) .Where(it => it.WalletId == model.Id) .Select(it => new { it.OrderStatus }) .FirstOrDefaultAsync(); model.ExpandindirectOrderStatus = expandindirectOrder == null ? EnumEnterpriseWalletExpandindirectOrderStatus.Wait : expandindirectOrder.OrderStatus; return model; } FlexJobApi.UserServer.Application/FlexJobApi.UserServer.Application.xml
@@ -374,7 +374,7 @@ 灵工命令处理器 </summary> </member> <member name="M:FlexJobApi.UserServer.Application.EnterpriseEmployeesCommandHandler.#ctor(MediatR.IMediator,Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseEmployee},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.User},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Enterprise},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseEmployeeContract},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.ElectronSignSetting},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.ContractTemplate},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseCost},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.TaskInfoUser})"> <member name="M:FlexJobApi.UserServer.Application.EnterpriseEmployeesCommandHandler.#ctor(FlexJobApi.Core.SmsUtils,MediatR.IMediator,Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseEmployee},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.User},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Enterprise},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseEmployeeContract},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.ElectronSignSetting},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.ContractTemplate},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseCost},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.TaskInfoUser})"> <summary> 灵工命令处理器 </summary> @@ -398,6 +398,14 @@ <member name="M:FlexJobApi.UserServer.Application.EnterpriseEmployeesCommandHandler.Handle(FlexJobApi.Core.InviteElectronSignCommand,System.Threading.CancellationToken)"> <summary> 邀请灵工签约 </summary> <param name="request"></param> <param name="cancellationToken"></param> <returns></returns> </member> <member name="M:FlexJobApi.UserServer.Application.EnterpriseEmployeesCommandHandler.Handle(FlexJobApi.Core.SendInviteElectronSignSmsCommand,System.Threading.CancellationToken)"> <summary> 发送邀请签约短信 </summary> <param name="request"></param> <param name="cancellationToken"></param> @@ -699,7 +707,7 @@ 企业钱包查询处理器 </summary> </member> <member name="M:FlexJobApi.UserServer.Application.EnterpriseWalletQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseWallet},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseWalletTransaction},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Enterprise},FlexJobApi.Core.AlipayUtils)"> <member name="M:FlexJobApi.UserServer.Application.EnterpriseWalletQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseWallet},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseWalletTransaction},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.EnterpriseWalletExpandindirectOrder},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Enterprise},FlexJobApi.Core.AlipayUtils)"> <summary> 企业钱包查询处理器 </summary> FlexJobApi.Web.Entry/appsettings.json
@@ -117,7 +117,10 @@ "UserElectronSign": "SMS_476485061", //818钱包开通 验证码${code},用户您好,您正在进行平台钱包开通,该验证码5分钟内有效,请勿泄露于他人。 "BankWalletAccountOpen": "SMS_473860301" "BankWalletAccountOpen": "SMS_473860301", "InviteElectronSign": "SMS_493755029", "ElectronSignUrl": "SMS_493715033" } } },