using Aop.Api.Domain; using Furion.DatabaseAccessor; using Furion.DependencyInjection; using Furion.DistributedIDGenerator; using Furion.FriendlyException; using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Identity.Client; using NetTopologySuite.Index.HPRtree; using Org.BouncyCastle.Ocsp; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Text; using System.Threading.Tasks; namespace ApiTools.Core { public class ChannelPingAnPayWalletService( ChannelWalletRepository channelWalletRepository, ChannelWalletTransactionRepository channelWalletTransactionRepository, PingAnPayUtils utils ) : IChannelWalletService, ITransient { private readonly ChannelWalletRepository channelWalletRepository = channelWalletRepository; private readonly ChannelWalletTransactionRepository channelWalletTransactionRepository = channelWalletTransactionRepository; private readonly PingAnPayUtils utils = utils; /// /// 查询企业钱包余额 /// /// /// public async Task GetEnterpriseWalletBalance(ChannelWallet wallet) { if (wallet != null && wallet.Identity.IsNotNull()) { var response = await utils.CorAcctBalanceQuery(new CorAcctBalanceQueryRequest { Account = wallet.Identity, CcyCode = "RMB", }); if (response.Code.IsNotNull()) { wallet.Balance = 0; wallet.ErrorCode = response.Code; wallet.FailReason = response.Message; } else { wallet.ErrorCode = null; wallet.FailReason = null; wallet.SignStatus = EnumWalletSignStatus.Normal; wallet.Balance = response.AcctBalance.ToDecimal().Value; } } return wallet; } /// /// 转账 /// /// /// /// public async Task Transfer(ChannelWallet wallet, ChannelWalletTransaction transaction) { transaction.PingAnPay = new ChannelWalletTransactionPingAnPay(); var responseStop = await utils.StopPaymentAndSettlementAccounts(new StopPaymentAndSettlementAccountsRequest { CnsmrSeqNo = transaction.Code, AccountNo = transaction.PayerAccount, OpType = "A", CcyCode = "RMB", SeqNo = $"{DateTime.Now:yyyyMMddHHmmssfff}{new Random(IDGen.NextID().GetHashCode()).Next(100, 999)}", TradeDate = DateTime.Now.ToString("yyyyMMdd").ToInt()!.Value, TradeTime = DateTime.Now.ToString("HHmmss").ToInt()!.Value, }); if (responseStop.Code.IsNotNull()) { transaction.ErrorCode = responseStop.Code; transaction.FailReason = responseStop.Errors?.FirstOrDefault()?.ErrorMessage ?? responseStop.Message; transaction.PingAnPay.StopStt = "30"; transaction.PingAnPay.StopFailReason = transaction.FailReason; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } else { if (responseStop.StopPayFlw.IsNotNull() && responseStop.Stt == "20") { transaction.PingAnPay.FreezeNo = responseStop.StopPayFlw; } else { var responseStopDetail = await utils.InquiryAccountStopPaymentDetails(new InquiryAccountStopPaymentDetailsRequest { CnsmrSeqNo = transaction.Code, AccountNo = transaction.PayerAccount, PageNo = "1", }); if (responseStopDetail.Code.IsNotNull()) { transaction.ErrorCode = responseStopDetail.Code; transaction.FailReason = responseStopDetail.Errors?.FirstOrDefault()?.ErrorMessage ?? responseStopDetail.Message; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } else if (responseStopDetail.List.IsNotNull()) { transaction.PingAnPay.FreezeNo = responseStopDetail.List.FirstOrDefault(it => it.FreezeStatu == "0")?.StopPayFlw; } else { transaction.FailReason = "止付失败并未查询到止付编号"; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } } } if (transaction.PingAnPay.FreezeNo.IsNotNull()) { transaction.PingAnPay.ThirdVoucher = transaction.Code; await channelWalletTransactionRepository.UpdateNowAsync(transaction); var responsePayment = await utils.SingleApplicationSuspensionPayment(new SingleApplicationSuspensionPaymentRequest { CcyCode = "RMB", CnsmrSeqNo = transaction.Code, FreezeNo = transaction.PingAnPay.FreezeNo, ThirdVoucher = transaction.Code, OutAcctName = wallet.Name, OutAcctNo = wallet.Identity, InAcctBankName = transaction.ReceiveBank, InAcctName = transaction.ReceiveName, InAcctNo = transaction.ReceiveAccount, TranAmount = transaction.Amount.ToString(), UseEx = transaction.Purpose, UnionFlag = wallet.Bank == transaction.ReceiveBank ? "1" : "0", AddrFlag = "1" }); if (responsePayment.Code.IsNotNull()) { transaction.ErrorCode = responsePayment.Code; transaction.FailReason = responsePayment.Errors?.FirstOrDefault()?.ErrorMessage ?? responsePayment.Message; transaction.TransactionStatus = EnumWalletTransactionStatus.Fail; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } else { await GetTransactionDetail(wallet, transaction); if (transaction.TransactionStatus == EnumWalletTransactionStatus.Success) { await DownloadEreceiptUrl(wallet, transaction); } } } } /// /// 查询交易记录 /// /// /// /// public async Task GetTransactionDetail(ChannelWallet wallet, ChannelWalletTransaction transaction) { var response = await utils.CorSingleTransferQuery(new CorSingleTransferQueryRequest { OrigThirdVoucher = transaction.Code, }); if (response.Code.IsNotNull()) { transaction.ErrorCode = response.Code; transaction.FailReason = response.Errors?.FirstOrDefault()?.ErrorMessage ?? response.Message; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } else { response.Adapt(transaction.PingAnPay); transaction.TransDate = response.AccountDate.ToDateTime(); transaction.OrderFee = response.Fee.ToDecimal(); transaction.TransactionStatus = response.Stt == "20" ? EnumWalletTransactionStatus.Success : response.Stt == "30" ? EnumWalletTransactionStatus.Fail : EnumWalletTransactionStatus.Dealing; if (transaction.TransactionStatus == EnumWalletTransactionStatus.Fail) { transaction.ErrorCode = response.Stt; transaction.FailReason = response.BackRem; } else { transaction.ErrorCode = null; transaction.FailReason = null; } if (transaction.TransactionStatus == EnumWalletTransactionStatus.Success && transaction.TransDate == null) { transaction.TransDate = DateTime.Now; } await channelWalletTransactionRepository.UpdateNowAsync(transaction); if (transaction.TransactionStatus != EnumWalletTransactionStatus.Dealing) { var responseStop = await utils.StopPaymentAndSettlementAccounts(new StopPaymentAndSettlementAccountsRequest { CnsmrSeqNo = transaction.Code, AccountNo = transaction.PayerAccount, StopPayFlw = transaction.PingAnPay.FreezeNo, OpType = "D", CcyCode = "RMB", SeqNo = $"{DateTime.Now:yyyyMMddHHmmssfff}{new Random(IDGen.NextID().GetHashCode()).Next(100, 999)}", TradeDate = DateTime.Now.ToString("yyyyMMdd").ToInt()!.Value, TradeTime = DateTime.Now.ToString("HHmmss").ToInt()!.Value, }); if (responseStop.Code.IsNotNull()) { transaction.PingAnPay.RemoveStopStt = "30"; transaction.PingAnPay.RemoveStopFailReason = responseStop.Errors?.FirstOrDefault()?.ErrorMessage ?? responseStop.Message; } else { transaction.PingAnPay.RemoveStopStt = responseStop.Stt; transaction.PingAnPay.RemoveStopFailReason = responseStop.SttDesc; } await channelWalletTransactionRepository.UpdateNowAsync(transaction); } } } /// /// 下载电子收据 /// /// /// /// public async Task DownloadEreceiptUrl(ChannelWallet wallet, ChannelWalletTransaction transaction) { var response = await utils.SameDayHistoryReceiptDataQuery(new SameDayHistoryReceiptDataQueryRequest { OutAccNo = transaction.PayerAccount, AccountBeginDate = transaction.PingAnPay.AccountDate, AccountEndDate = transaction.PingAnPay.AccountDate, InAccNo = transaction.ReceiveAccount, HostFlow = transaction.PingAnPay.HostFlowNo }); if (response.Code.IsNotNull()) { transaction.EreceiptStatus = EnumWalletTransactionEreceiptStatus.FAIL; transaction.EreceiptErrorMessage = response.Errors?.FirstOrDefault()?.ErrorMessage ?? response.Message; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } else if (response.List.IsNull()) { transaction.EreceiptStatus = EnumWalletTransactionEreceiptStatus.FAIL; transaction.EreceiptErrorMessage = "未找到回单记录"; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } else { var responseDownload = await utils.SingleOrBatchReceiptPDFMergeDownloadNew(new SingleOrBatchReceiptPDFMergeDownloadNewRequest { OutAccNo = transaction.PayerAccount, List = response.List .Select(it => new SingleOrBatchReceiptPDFMergeDownloadNewRequestItem { RecepitType = it.ReceiptType, SeqNo = it.SeqNo, AccountDate = it.AccountDate }) .ToList() }); if (responseDownload.Code.IsNotNull()) { transaction.EreceiptStatus = EnumWalletTransactionEreceiptStatus.FAIL; transaction.EreceiptErrorMessage = responseDownload.Errors?.FirstOrDefault()?.ErrorMessage ?? responseDownload.Message; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } else { transaction.EreceiptFileId = responseDownload.DocID; transaction.EreceiptDownloadUrl = utils.DownloadFile(responseDownload.DocID, responseDownload.FileName); transaction.EreceiptDownloadOssUrl = AliyunOSSUtils.Upload( "PingAnPay", new MemoryStream(File.ReadAllBytes(transaction.EreceiptDownloadUrl)), $"电子回单-{transaction.Code}.zip") .Url; transaction.EreceiptStatus = EnumWalletTransactionEreceiptStatus.SUCCESS; await channelWalletTransactionRepository.UpdateNowAsync(transaction); } } } } }