From fedc3ae6cde6e94eac723d91488ca8e8ab0e5cf1 Mon Sep 17 00:00:00 2001 From: zhengyuxuan <zhengyuxuan1995> Date: 星期二, 25 三月 2025 14:44:50 +0800 Subject: [PATCH] fix:退款订单号bug修复 --- LifePayment/LifePayment.Application/LifePay/LifePayService.cs | 1461 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 1,381 insertions(+), 80 deletions(-) diff --git a/LifePayment/LifePayment.Application/LifePay/LifePayService.cs b/LifePayment/LifePayment.Application/LifePay/LifePayService.cs index 8f950fe..a142921 100644 --- a/LifePayment/LifePayment.Application/LifePay/LifePayService.cs +++ b/LifePayment/LifePayment.Application/LifePay/LifePayService.cs @@ -1,31 +1,32 @@ -锘縰sing DynamicQuery.Net.Dto.Input; -using LifePayment.Application.Contracts; +锘縰sing LifePayment.Application.Contracts; using LifePayment.Domain; +using LifePayment.Domain.LifePay; using LifePayment.Domain.Models; using LifePayment.Domain.Shared; -using MailKit.Search; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Nest; using Newtonsoft.Json; -using NPOI.OpenXmlFormats.Dml.Chart; -using NPOI.SS.Formula.Functions; -using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; -using System.Security.Cryptography; +using System.Linq.Dynamic.Core; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application.Services; -using Volo.Abp.Domain.Entities; +using Volo.Abp.Data; using Volo.Abp.Domain.Repositories; using Volo.Abp.EventBus.Distributed; +using Z.EntityFramework.Plus; using ZeroD.Util; -using ZeroD.Util.Fadd; +using Alipay.EasySDK.Payment.Common.Models; using static LifePayment.Domain.Shared.LifePaymentConstant; -using static IdentityServer4.Models.IdentityResources; +using ZeroD.Util.Fadd; +using Nest; +using Volo.Abp.Domain.Entities; +using Volo.Abp.ObjectMapping; +using NPOI.SS.Formula.Functions; +using StackExchange.Redis; namespace LifePayment.Application; @@ -35,10 +36,18 @@ private readonly ILogger<LifePayService> _logger; private readonly IRepository<LifePayRate, Guid> _lifePayRateRepository; + private readonly IRepository<LifePayPremium, Guid> _lifePayPremiumRepository; private readonly IRepository<LifePayOrder, Guid> _lifePayOrderRepository; private readonly IRepository<LifePayUser, Guid> _lifePayUserRepository; - + private readonly IRepository<LifePayIntroInfo, Guid> _lifePayIntroInfoRepository; + private readonly IRepository<DallyStatistics, Guid> _dallyStatisticsRepository; + private readonly IRepository<LifePayChannles, Guid> _lifePayChannlesRep; + private readonly IRepository<LifePayAccount, Guid> _lifePayAccount; + private readonly IRepository<OperateHistory, Guid> _operateHistory; + private readonly IDataFilter dataFilter; + private readonly IChannelFilter _channelFilter; private readonly IAliPayApi _aliPayApi; + private readonly IAlipayInterfaceManager _alipayInterfaceManager; private readonly IWxPayApi _wxPayApi; private readonly WxPayOption _wxPayOptions; @@ -50,22 +59,39 @@ IRepository<LifePayRate, Guid> lifePayRateRepository, IRepository<LifePayOrder, Guid> lifePayOrderRepository, IRepository<LifePayUser, Guid> lifePayUserRepository, + IRepository<LifePayPremium, Guid> lifePayPremiumRepository, + IRepository<LifePayIntroInfo, Guid> lifePayIntroInfoRepository, + IRepository<OperateHistory, Guid> operateHistory, IAliPayApi aliPayApi, + IAlipayInterfaceManager aliPayInterfaceManager, IWxPayApi wxPayApi, - IOptions<WxPayOption> wxPayOptions) + IOptions<WxPayOption> wxPayOptions, + IRepository<LifePayChannles, Guid> lifePayChannlesRep, + IRepository<LifePayAccount, Guid> lifePayAccount, + IDataFilter dataFilter, + IChannelFilter channelFilter) { _logger = logger; _aCOOLYManager = aCOOLYManager; _lifePayRateRepository = lifePayRateRepository; _lifePayOrderRepository = lifePayOrderRepository; _lifePayUserRepository = lifePayUserRepository; + _lifePayPremiumRepository = lifePayPremiumRepository; + _lifePayIntroInfoRepository = lifePayIntroInfoRepository; _aliPayApi = aliPayApi; + _alipayInterfaceManager = aliPayInterfaceManager; _wxPayApi = wxPayApi; _wxPayOptions = wxPayOptions.Value; _distributedEventBus = distributedEventBus; + _lifePayChannlesRep = lifePayChannlesRep; + _lifePayAccount = lifePayAccount; + this.dataFilter = dataFilter; + _channelFilter = channelFilter; + _operateHistory = operateHistory; } #region 鏌ヨ + /// <summary> /// 鑾峰彇鐢佃垂闈㈠�� @@ -97,12 +123,62 @@ } /// <summary> + /// 鑾峰彇璇濊垂闈㈠�� + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<GasParValueResponse> GetGasParValue() + { + return await _aCOOLYManager.GasParValue(new GasParValueRequestInput()); + } + + /// <summary> + /// 鑾峰彇鐕冩皵鏀寔鍟嗘埛 + /// </summary> + /// <returns></returns> + public async Task<GasOrgTypeValueResponse> GetGasOrgType() + { + return await _aCOOLYManager.GasOrgType(new GasOrgTypeRequestInput()); + } + + /// <summary> /// 鑾峰彇鎶樻墸 /// </summary> /// <returns></returns> public async Task<List<LifePayRateListOutput>> GetRate() { - return await _lifePayRateRepository.Select(x => new LifePayRateListOutput() { Rate = x.Rate, RateType = x.RateType }) + return await _lifePayRateRepository.Where(x => x.IsDeleted == false).Select(x => new LifePayRateListOutput() { Id = x.Id, Rate = x.Rate, RateType = x.RateType }) + .ToListAsync(); + } + + /// <summary> + /// 鑾峰彇娓犻亾鎶樻墸 + /// </summary> + /// <returns></returns> + public async Task<ChannelRateOutput> GetChannelRate(ChannelsBaseInput input) + { + return _lifePayChannlesRep.Where(x => x.IsDeleted == false && x.ChannlesNum == input.CheckChannelId).Select(x => new ChannelRateOutput() { ChannlesRate = x.ChannlesRate }) + .FirstOrDefault(); + } + + /// <summary> + /// 鑾峰彇鎵嬬画璐硅垂鐜� + /// </summary> + /// <returns></returns> + public async Task<List<LifePayPremiumListOutput>> GetPremium() + { + return await _lifePayPremiumRepository.Where(x => x.IsDeleted == false).Select(x => new LifePayPremiumListOutput() { Id = x.Id, Rate = x.Rate, PremiumType = x.PremiumType }) + .ToListAsync(); + } + + /// <summary> + /// 椤荤煡閰嶇疆 + /// </summary> + /// <returns></returns> + public async Task<List<LifePayIntroInfoOutput>> GetIntroInfo(LifePayOrderTypeEnum lifePayType) + { + return await _lifePayIntroInfoRepository.Where(x => x.IsDeleted == false && x.LifePayType == lifePayType).OrderBy(x => x.Sequence) + .Select(x => new LifePayIntroInfoOutput() { Type = x.Type, ContentSummary = x.ContentSummary, Content = x.Content, LifePayType = x.LifePayType, Path = x.Path, Sequence = x.Sequence }) .ToListAsync(); } @@ -111,17 +187,54 @@ /// </summary> /// <param name="input"></param> /// <returns></returns> - public async Task<PageOutput<UserListOutput>> GetUserPage(PageInput input) + public async Task<PageOutput<UserListOutput>> GetUserPage(QueryUserPageInput input) { - return await _lifePayUserRepository.Select(x => + return await _channelFilter.GetChannelLifePayUserFilter(_lifePayUserRepository).Where(x => x.IsDeleted == false) + .WhereIf(!string.IsNullOrEmpty(input.QueryCondition), x => x.PhoneNumber.Contains(input.QueryCondition) || x.Name.Contains(input.QueryCondition)) + .WhereIf(input.CreationTimeBegin.HasValue, x => x.CreationTime >= input.CreationTimeBegin) + .WhereIf(input.CreationTimeEnd.HasValue, x => x.CreationTime <= input.CreationTimeEnd) + .Select(x => new UserListOutput() { Id = x.Id, + CreationChannle = string.IsNullOrEmpty(x.CreationChannleNum) ? "" : _lifePayChannlesRep.Where(c => c.ChannlesNum == x.CreationChannleNum).FirstOrDefault().ChannlesName, + LastLoginChannle = string.IsNullOrEmpty(x.LastLoginChannleNum) ? "" : _lifePayChannlesRep.Where(c => c.ChannlesNum == x.LastLoginChannleNum).FirstOrDefault().ChannlesName, PhoneNumber = x.PhoneNumber, + Name = string.IsNullOrEmpty(x.Name) ? "" : x.Name, CreationTime = x.CreationTime, LastLoginTime = x.LastLoginTime }) .GetPageResult(input.PageModel); + } + + /// <summary> + /// 鑾峰彇鐢ㄦ埛鎴峰彿鍒嗛〉鏁版嵁 + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<PageOutput<UserAccountOutput>> GetAccountPage(QueryUserAccountListInput input) + { + using (dataFilter.Disable<ISoftDelete>()) + { + return await _lifePayAccount.Where(x => x.UserId == input.UserId) + .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayType == input.LifePayOrderType) + .OrderByDescending(x => x.CreationTime) + .Select(x => + new UserAccountOutput + { + Id = x.Id, + LifePayType = x.LifePayType, + Content = x.Content, + CreationTime = x.CreationTime, + Remark = x.Remark, + Operators = x.Operators, + Province = x.Province, + City = x.City, + ExtraProperties = x.ExtraProperties, + IsDeleted = x.IsDeleted + }) + .GetPageResult(input.PageModel); + } } /// <summary> @@ -131,36 +244,252 @@ /// <returns></returns> public async Task<PageOutput<LifePayOrderListOutput>> GetLifePayOrderPage(QueryLifePayOrderListInput input) { - return await _lifePayOrderRepository.Where(x => x.PayStatus != LifePayStatusEnum.鏈敮浠�) - .WhereIf(input.BeginFinishTime.HasValue, x => x.FinishTime >= input.BeginFinishTime) + var channles = await _lifePayChannlesRep.Where(x => x.ChannlesName.Contains(input.KeyWords)).Select(x => x.ChannlesNum).ToListAsync(); + var result = await (from a in _channelFilter.GetChannelLifePayOrderFilter(_lifePayOrderRepository) + .WhereIf(input.BeginFinishTime.HasValue, x => x.FinishTime >= input.BeginFinishTime) .WhereIf(input.EndFinishTime.HasValue, x => x.FinishTime <= input.EndFinishTime) .WhereIf(input.BeginPayTime.HasValue, x => x.PayTime >= input.BeginPayTime) + .WhereIf(input.LifePayType.HasValue, x => x.LifePayType == input.LifePayType) .WhereIf(input.EndPayTime.HasValue, x => x.PayTime <= input.EndPayTime) .WhereIf(input.LifePayOrderStatus.HasValue, x => x.LifePayOrderStatus == input.LifePayOrderStatus.Value) .WhereIf(input.PayStatus.HasValue, x => x.PayStatus == input.PayStatus.Value) + .WhereIf(input.ACOOLYStatus.HasValue, x => x.ACOOLYStatus == input.ACOOLYStatus.Value) .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayOrderType == input.LifePayOrderType.Value) .WhereIf(input.UserId.HasValue, x => x.UserId == input.UserId.Value) - .Select(x => - new LifePayOrderListOutput - { - DiscountAmount = x.DiscountAmount, - FinishTime = x.FinishTime, - Id = x.Id, - LifePayOrderStatus = x.LifePayOrderStatus, - LifePayOrderType = x.LifePayOrderType, - LifePayType = x.LifePayType, - OrderNo = x.OrderNo, - PayAmount = x.PayAmount, - PhoneNumber = x.PhoneNumber, - RechargeAmount = x.RechargeAmount, - UserId = x.UserId, - OutOrderNo = x.OutOrderNo, - PayStatus = x.PayStatus, - PayTime = x.PayTime, - RefundCredentialsImgUrl = x.RefundCredentialsImgUrl, - CreationTime = x.CreationTime - }) - .GetPageResult(input.PageModel); + .WhereIf(input.KeyWords.IsNotNullOrEmpty(), x => x.OrderNo.Contains(input.KeyWords) || x.OutOrderNo.Contains(input.KeyWords) || x.ACOOLYOrderNo.Contains(input.KeyWords) || channles.Contains(x.ChannelId)) + join b in _lifePayChannlesRep on a.ChannelId equals b.ChannlesNum into temp + from b in temp.DefaultIfEmpty() + select new LifePayOrderListOutput + { + DiscountAmount = a.DiscountAmount, + FinishTime = a.FinishTime, + Id = a.Id, + LifePayOrderStatus = a.LifePayOrderStatus, + LifePayOrderType = a.LifePayOrderType, + LifePayType = a.LifePayType, + OrderNo = a.OrderNo, + PayAmount = a.PayAmount, + PhoneNumber = a.PhoneNumber, + RechargeAmount = a.RechargeAmount, + UserId = a.UserId, + OutOrderNo = a.OutOrderNo, + PayStatus = a.PayStatus, + PayTime = a.PayTime, + ACOOLYOrderNo = a.ACOOLYOrderNo, + RefundCredentialsImgUrl = a.RefundCredentialsImgUrl.GetOssPath(), + RefundPrice = a.RefundPrice, + CreationTime = a.CreationTime, + RefundCheckRemark = a.RefundCheckRemark, + RefundApplyRemark = a.RefundApplyRemark, + RefundTime = a.RefundTime, + ChannelName = b.ChannlesName, + ActualRechargeAmount = a.RechargeAmount, + PlatformDeductionAmount = a.PlatformDeductionAmount, + ACOOLYStatus = a.ACOOLYStatus, + LifePayRefundStatus = a.LifePayRefundStatus, + }).GetPageResult(input.PageModel); + + return result; + } + + /// <summary> + /// 閫�娆捐鍗曞垎椤� + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<PageOutput<LifePayOrderListOutput>> GetLifePayRefundOrderPage(QueryLifePayRefundOrderListInput input) + { + + var result = await (from a in _channelFilter.GetChannelLifePayOrderFilter(_lifePayOrderRepository) + .Where(x => x.LifePayOrderStatus == LifePayOrderStatusEnum.寰呴��娆� || x.LifePayOrderStatus == LifePayOrderStatusEnum.宸查��娆� || x.LifePayOrderStatus == LifePayOrderStatusEnum.閫�娆句腑 + || (x.LifePayRefundStatus > LifePayRefundStatusEnum.鏃犻渶閫�娆� && x.LifePayRefundStatus != LifePayRefundStatusEnum.閫�娆鹃┏鍥�)) + .WhereIf(input.BeginRefundTime.HasValue, x => x.RefundTime >= input.BeginRefundTime) + .WhereIf(input.EndRefundTime.HasValue, x => x.RefundTime <= input.EndRefundTime) + .WhereIf(input.BeginRefundApplyTime.HasValue, x => x.RefundApplyTime >= input.BeginRefundApplyTime) + .WhereIf(input.LifePayType.HasValue, x => x.LifePayType == input.LifePayType) + .WhereIf(input.EndRefundApplyTime.HasValue, x => x.RefundApplyTime <= input.EndRefundApplyTime) + .WhereIf(input.LifePayRefundStatus.HasValue, x => x.LifePayRefundStatus == input.LifePayRefundStatus.Value) + .WhereIf(input.ACOOLYStatus.HasValue, x => x.ACOOLYStatus == input.ACOOLYStatus.Value) + .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayOrderType == input.LifePayOrderType.Value) + .WhereIf(input.UserId.HasValue, x => x.UserId == input.UserId.Value) + .WhereIf(input.KeyWords.IsNotNullOrEmpty(), x => x.PhoneNumber.Contains(input.KeyWords) || x.OrderNo.Contains(input.KeyWords) || x.OutOrderNo.Contains(input.KeyWords) || x.ACOOLYOrderNo.Contains(input.KeyWords)) + join b in _lifePayChannlesRep on a.ChannelId equals b.ChannlesNum into temp + from b in temp.DefaultIfEmpty() + select new LifePayOrderListOutput + { + DiscountAmount = a.DiscountAmount, + FinishTime = a.FinishTime, + Id = a.Id, + LifePayOrderStatus = a.LifePayOrderStatus, + LifePayOrderType = a.LifePayOrderType, + LifePayType = a.LifePayType, + OrderNo = a.OrderNo, + PayAmount = a.PayAmount, + PhoneNumber = a.PhoneNumber, + RechargeAmount = a.RechargeAmount, + UserId = a.UserId, + OutOrderNo = a.OutOrderNo, + PayStatus = a.PayStatus, + PayTime = a.PayTime, + ACOOLYOrderNo = a.ACOOLYOrderNo, + RefundCredentialsImgUrl = a.RefundCredentialsImgUrl.GetOssPath(), + CreationTime = a.CreationTime, + RefundCheckRemark = a.RefundCheckRemark, + RefundApplyRemark = a.RefundApplyRemark, + RefundApplyTime = a.RefundApplyTime, + RefundOrderNo = a.RefundOrderNo, + RefundTime = a.RefundTime, + RefundPrice = a.RefundPrice, + ChannelName = b.ChannlesName, + ActualRechargeAmount = a.RechargeAmount, + PlatformDeductionAmount = a.PlatformDeductionAmount, + ACOOLYStatus = a.ACOOLYStatus, + LifePayRefundStatus = a.LifePayRefundStatus, + }).GetPageResult(input.PageModel); + + return result; + } + + /// <summary> + /// 閫�娆捐鍗曞垎椤� + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<List<LifePayRefundOrderListTemplate>> GetLifePayRefudOrderPageExport(QueryLifePayRefundOrderListInput input) + { + var result = await (await GetLifePayRefundOrderListFilter(input)).Select(x => new LifePayRefundOrderListTemplate + { + FinishTime = x.RefundTime, + RefundPrice = x.RefundPrice, + LifePayOrderType = x.LifePayOrderType, + LifePayType = x.LifePayType, + PayAmount = x.PayAmount, + PhoneNumber = x.PhoneNumber, + RefundOrderNo = x.RefundOrderNo, + RefundApplyTime = x.RefundApplyTime, + ChannelName = x.ChannelName, + CreationTime = x.CreationTime, + ACOOLYStatus = x.ACOOLYStatus, + RefundApplyRemark = x.RefundApplyRemark, + RechargeAmount = x.RechargeAmount, + ActualReceivedAmount = x.ActualReceivedAmount.ToString("F2"), + LifePayRefundStatus = x.LifePayRefundStatus, + + }).OrderByDescending(r => r.CreationTime).ToListAsync(); + var i = 0; + result.ForEach(s => + { + s.SerialNumber = ++i; + s.ACOOLYStatusStr = s.ACOOLYStatus.GetDescription(); + s.LifePayOrderTypeStr = s.LifePayOrderType.GetDescription(); + s.RechargeAmountStr = s.RechargeAmount.ToString("F2"); + s.ActualReceivedAmount = s.ActualReceivedAmount; + s.LifePayRefundStatusStr = s.LifePayRefundStatus.GetDescription(); + s.PayAmountStr = s.PayAmount.ToString("F2"); + s.LifePayTypeStr = s.LifePayType.GetDescription(); + s.FinishTimeStr = !s.FinishTime.HasValue ? string.Empty : s.FinishTime.Value.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmm); + s.RefundApplyTimeStr = !s.RefundApplyTime.HasValue? string.Empty:s.RefundApplyTime.Value.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmm); + }); + return result; + } + + + public async Task<LifePayOrderOutput> GetLifePayOrderDetail(string orderNo) + { + var order = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo).FirstOrDefaultAsync(); + var channle = await _lifePayChannlesRep.FirstOrDefaultAsync(r => r.ChannlesNum == order.ChannelId); + CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "璁㈠崟涓嶅瓨鍦�"); + var user = await _lifePayUserRepository.FirstOrDefaultAsync(x => x.Id == order.UserId); + var channlesRakePrice = (order.PayAmount - (order.PlatformDeductionAmount == null ? 0 : order.PlatformDeductionAmount)) * channle.ChannlesRakeRate / 100; + var orderpirce = await GetOrderPrice(order.RechargeAmount, order.PayAmount,order.PlatformRate, order.ChannleRate, order.ChannlesRakeRate,order.PremiumRate); + + + var result = new LifePayOrderOutput() + { + UserName = user.Name, + UserPhoneNumber = user.PhoneNumber, + DiscountAmount = order.DiscountAmount, + FinishTime = order.FinishTime, + Id = order.Id, + OutOrderNo = order.OutOrderNo, + LifePayChannle = channle.ChannlesName, + Status = order.LifePayOrderStatus, + LifePayOrderType = order.LifePayOrderType, + LifePayType = order.LifePayType, + OrderNo = order.OrderNo, + PayAmount = order.PayAmount, + RechargeAmount = order.RechargeAmount, + PayStatus = order.PayStatus, + PayTime = order.PayTime, + OrderParamDetailJsonStr = order.OrderParamDetailJsonStr, + RefundCredentialsImgUrl = order.RefundCredentialsImgUrl.GetOssPath(), + CreationTime = order.CreationTime, + RefundCheckRemark = order.RefundCheckRemark, + RefundApplyRemark = order.RefundApplyRemark, + RefundTime = order.RefundTime, + ACOOLYOrderNo = order.ACOOLYOrderNo, + LifePayRefundStatus = order.LifePayRefundStatus, + ActualRechargeAmount = order.RechargeAmount, + RefundPrice = order.RefundPrice, + PlatformRate = order.PlatformRate, + PlatformPrice = order.PlatformDeductionAmount, + ElecBillUrl = order.ElecBillUrl.GetOssPath(), + RefundElecBillUrl = order.RefundElecBillUrl.GetOssPath(), + ChannleRate = order.ChannleRate, + ChannlesRakeRate = order.ChannlesRakeRate, + ChannlesRakePrice = orderpirce.ChannlesRakePrice, + PremiumRate = order.PremiumRate, + PremiumPrice = orderpirce.PremiumPrice, + Profit = orderpirce.Profit + }; + + return result; + } + + public async Task<LifePayRefundOrderOutput> GetLifePayRefundOrderDetail(string orderNo) + { + var order = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo).FirstOrDefaultAsync(); + var platformRate = await _lifePayRateRepository.FirstOrDefaultAsync(r => r.RateType == LifePayRateTypeEnum.渚涘簲鍟嗘姌鎵d环); + var channle = await _lifePayChannlesRep.FirstOrDefaultAsync(r => r.ChannlesNum == order.ChannelId); + var premium = await _lifePayPremiumRepository.Where(x => x.IsDeleted == false && x.PremiumType == order.LifePayType).FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "璁㈠崟涓嶅瓨鍦�"); + var user = await _lifePayUserRepository.FirstOrDefaultAsync(x => x.Id == order.UserId); + + var channlesRakePrice = (order.PayAmount - (order.PlatformDeductionAmount == null ? 0 : order.PlatformDeductionAmount)) * channle.ChannlesRakeRate / 100; + var result = new LifePayRefundOrderOutput() + { + UserName = user.Name, + UserPhoneNumber = user.PhoneNumber, + DiscountAmount = order.DiscountAmount, + FinishTime = order.FinishTime, + Id = order.Id, + OutOrderNo = order.OutOrderNo, + LifePayChannle = channle.ChannlesName, + Status = order.LifePayOrderStatus, + LifePayOrderType = order.LifePayOrderType, + LifePayType = order.LifePayType, + OrderNo = order.OrderNo, + PayAmount = order.PayAmount, + RechargeAmount = order.RechargeAmount, + PayStatus = order.PayStatus, + PayTime = order.PayTime, + RefundCredentialsImgUrl = order.RefundCredentialsImgUrl.GetOssPath(), + CreationTime = order.CreationTime, + RefundCheckRemark = order.RefundCheckRemark, + RefundApplyRemark = order.RefundApplyRemark, + RefundApplyTime = order.RefundApplyTime, + RefundTime = order.RefundTime, + RefundOrderNo = order.RefundOrderNo, + ACOOLYOrderNo = order.ACOOLYOrderNo, + LifePayRefundStatus = order.LifePayRefundStatus, + ActualRechargeAmount = order.ActualRechargeAmount, + ActualReceivedAmount = order.ActualReceivedAmount, + RefundPrice = order.RefundPrice, + ElecBillUrl = order.ElecBillUrl.GetOssPath(), + RefundElecBillUrl = order.RefundElecBillUrl.GetOssPath(), + }; + + return result; } /// <summary> @@ -175,7 +504,7 @@ return new PageOutput<UserLifePayOrderOutput>(); } - return await _lifePayOrderRepository.Where(x => x.PayStatus != LifePayStatusEnum.鏈敮浠�) + return await _channelFilter.GetChannelLifePayOrderFilter(_lifePayOrderRepository).Where(x => x.PayStatus != LifePayStatusEnum.鏈敮浠�) .WhereIf(input.BeginFinishTime.HasValue, x => x.FinishTime >= input.BeginFinishTime) .WhereIf(input.EndFinishTime.HasValue, x => x.FinishTime <= input.EndFinishTime) .WhereIf(input.BeginPayTime.HasValue, x => x.PayTime >= input.BeginPayTime) @@ -199,11 +528,51 @@ PayStatus = x.PayStatus, PayTime = x.PayTime, OrderParamDetailJsonStr = x.OrderParamDetailJsonStr, + RefundCredentialsImgUrl = x.RefundCredentialsImgUrl.GetOssPath(), CreationTime = x.CreationTime, - RefundTime = x.RefundTime + RefundCheckRemark = x.RefundCheckRemark, + RefundApplyRemark = x.RefundApplyRemark, + RefundApplyTime = x.RefundApplyTime, + RefundTime = x.RefundTime, + ACOOLYOrderNo = x.ACOOLYOrderNo, + LifePayRefundStatus = x.LifePayRefundStatus, + ACOOLYStatus = x.ACOOLYStatus, }) .GetPageResult(input.PageModel); } + + public async Task<UserLifePayOrderOutput> GetUserLifePayOrderDetail(string orderNo) + { + var result = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo) + .Select(x => + new UserLifePayOrderOutput + { + DiscountAmount = x.DiscountAmount, + FinishTime = x.FinishTime, + Id = x.Id, + LifePayOrderStatus = x.LifePayOrderStatus, + LifePayOrderType = x.LifePayOrderType, + LifePayType = x.LifePayType, + OrderNo = x.OrderNo, + PayAmount = x.PayAmount, + RechargeAmount = x.RechargeAmount, + PayStatus = x.PayStatus, + PayTime = x.PayTime, + OrderParamDetailJsonStr = x.OrderParamDetailJsonStr, + RefundCredentialsImgUrl = x.RefundCredentialsImgUrl.GetOssPath(), + CreationTime = x.CreationTime, + RefundCheckRemark = x.RefundCheckRemark, + RefundApplyRemark = x.RefundApplyRemark, + RefundTime = x.RefundTime, + ACOOLYOrderNo = x.ACOOLYOrderNo, + }) + .FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(result == null, "璁㈠崟涓嶅瓨鍦�"); + + return result; + } + + /// <summary> /// 鏍规嵁璁㈠崟鍙疯幏鍙栨敮浠樼姸鎬� @@ -217,6 +586,233 @@ .FirstOrDefaultAsync(); } + public async Task<PageOutput<CreateEditPayChannelsInput>> GetLifePayChannlesPage(PageInput input) + { + return await GetLifePayChannlesListFilter().GetPageResult(input.PageModel); + } + + public async Task<List<CreateEditPayChannelsInput>> GetLifePayChannlesAllList() + { + return await GetLifePayChannlesListFilter().Where(x => x.Status == LifePayChannelsStatsEnum.鍚敤).ToListAsync(); + } + + public async Task<CreateEditPayChannelsInput> GetLifePayChannlesDto(Guid id) + { + return await _lifePayChannlesRep.Where(x => x.Id == id).Select(x => + new CreateEditPayChannelsInput + { + Id = x.Id, + ChannlesRate = x.ChannlesRate, + ChannlesRakeRate = x.ChannlesRakeRate, + ChannlesName = x.ChannlesName, + ChannlesNum = x.ChannlesNum, + Status = x.Status, + SwitchType = x.SwitchType, + ChannlesType = x.ChannlesType, + }).FirstOrDefaultAsync(); + } + + public async Task<CreateEditPayChannelsInput> GetLifePayChannlesDtoByNum(string channlesNum) + { + var result = await _lifePayChannlesRep.Where(x => x.ChannlesNum == channlesNum && x.Status == LifePayChannelsStatsEnum.鍚敤).Select(x => + new CreateEditPayChannelsInput + { + Id = x.Id, + ChannlesRate = x.ChannlesRate, + ChannlesRakeRate = x.ChannlesRakeRate, + ChannlesName = x.ChannlesName, + ChannlesNum = x.ChannlesNum, + Status = x.Status, + SwitchType = x.SwitchType, + ChannlesType = x.ChannlesType, + }).FirstOrDefaultAsync(); + return result; + } + + public async Task<UserLifePayOrderRefundOutput> GetUserLifePayOrderRefund(Guid id) + { + var order = await _channelFilter.GetChannelLifePayOrderFilter(_lifePayOrderRepository).Where(x => x.Id == id).Select(x => + new UserLifePayOrderRefundOutput + { + Id = x.Id, + OrderNo = x.OrderNo, + RefundCheckRemark = x.RefundCheckRemark, + RefundApplyRemark = x.RefundApplyRemark, + LifePayOrderStatus = x.LifePayOrderStatus, + }).FirstOrDefaultAsync(); + + CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "鏈壘鍒拌鍗曚俊鎭�"); + + return order; + } + + public async Task<PageOutput<UserAccountOutput>> GetUserAccountList(QueryUserAccountListInput input) + { + if (!input.UserId.HasValue) + { + return new PageOutput<UserAccountOutput>(); + } + + var result = await _lifePayAccount.Where(x => x.UserId == input.UserId && x.IsDeleted == false) + .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayType == input.LifePayOrderType) + .OrderByDescending(x => x.CreationTime) + .Select(x => + new UserAccountOutput + { + Id = x.Id, + LifePayType = x.LifePayType, + Content = x.Content, + CreationTime = x.CreationTime, + Remark = x.Remark, + Operators = x.Operators, + Province = x.Province, + City = x.City, + ExtraProperties = x.ExtraProperties, + }) + .GetPageResult(input.PageModel); + return result; + } + + public async Task<List<UserAccountOutput>> GetUserAccountAllList(QueryUserAccountAllListInput input) + { + if (!input.UserId.HasValue) + { + return new List<UserAccountOutput>(); + } + + var result = await _lifePayAccount.Where(x => x.UserId == input.UserId && x.IsDeleted == false) + .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayType == input.LifePayOrderType) + .OrderByDescending(x => x.CreationTime) + .Select(x => + new UserAccountOutput + { + Id = x.Id, + LifePayType = x.LifePayType, + Content = x.Content, + CreationTime = x.CreationTime, + Remark = x.Remark, + Operators = x.Operators, + Province = x.Province, + City = x.City, + ExtraProperties = x.ExtraProperties, + }).ToListAsync(); + return result; + } + + public async Task<UserAccountOutput> GetUserAccountDetail(Guid id) + { + var result = await _lifePayAccount.Where(x => x.Id == id) + .OrderByDescending(x => x.CreationTime) + .Select(x => + new UserAccountOutput + { + Id = x.Id, + LifePayType = x.LifePayType, + Content = x.Content, + CreationTime = x.CreationTime, + Remark = x.Remark, + Operators = x.Operators, + Province = x.Province, + City = x.City, + ExtraProperties = x.ExtraProperties, + }).FirstOrDefaultAsync(); + + CheckExtensions.IfTrueThrowUserFriendlyException(result == null, "鏈壘鍒版埛鍙蜂俊鎭�"); + return result; + } + + public async Task<List<LifePayOrderListTemplate>> GetLifePayOrderPageExport(QueryLifePayOrderListInput input) + { + var result = await (await GetLifePayOrderListFilter(input)).Select(x => new LifePayOrderListTemplate + { + DiscountAmount = x.DiscountAmount, + FinishTime = x.FinishTime, + //LifePayOrderStatus = x.LifePayOrderStatus, + LifePayOrderType = x.LifePayOrderType, + LifePayType = x.LifePayType, + OrderNo = x.OrderNo, + PayAmount = x.PayAmount, + ActualRechargeAmount = x.ActualRechargeAmount.HasValue?x.ActualRechargeAmount.Value:0, + PhoneNumber = x.PhoneNumber, + RechargeAmount = x.RechargeAmount, + OutOrderNo = x.OutOrderNo, + PayStatus = x.PayStatus, + PayTime = x.PayTime, + ACOOLYOrderNo = x.ACOOLYOrderNo, + CreationTime = x.CreationTime, + LifePayRefundStatus = x.LifePayRefundStatus, + ACOOLYStatus = x.ACOOLYStatus, + //RefundApplyRemark = x.RefundApplyRemark, + ChannelName = x.ChannelName, + PlatformPrice = x.PlatformDeductionAmount.HasValue ? x.PlatformDeductionAmount.Value : 0.00m + }).OrderByDescending(r => r.CreationTime).ToListAsync(); + var i = 0; + result.ForEach(s => + { + s.SerialNumber = ++i; + s.LifePayOrderTypeStr = s.LifePayOrderType.GetDescription(); + s.CreationTimeStr = s.CreationTime.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmmss); + s.RechargeAmountStr = s.RechargeAmount.ToString("F2"); + s.PayAmountStr = s.PayAmount.ToString("F2"); + s.PayTimeStr = !s.PayTime.HasValue ? string.Empty : s.PayTime.Value.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmmss); + s.LifePayTypeStr = s.LifePayType.GetDescription(); + s.PayStatusStr = s.PayStatus.GetDescription(); + s.ActualRechargeAmountStr = s.ActualRechargeAmount.ToString("F2"); + s.LifePayRefundStatusStr = s.LifePayRefundStatus.GetDescription(); + s.ACOOLYStatusStr = s.ACOOLYStatus.GetDescription(); + //s.LifePayOrderStatusStr = s.LifePayOrderStatus.GetDescription(); + s.FinishTimeStr = !s.FinishTime.HasValue ? string.Empty : s.FinishTime.Value.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmmss); + }); + return result; + } + public async Task<string> GetBillErceiptExport(string orderNo) + { + try + { + var order = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo).FirstOrDefaultAsync(); + + CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "鏈壘鍒拌鍗曚俊鎭�"); + if (order.LifePayType == LifePayTypeEnum.AliPay) + { + var elecInfoInput = new DataBillErceiptApplyInput + { + Type = "FUND_DETAIL", + Key = order.OutOrderNo + }; + + var elecInfoOutput = await _alipayInterfaceManager.DataBillErceiptApply(elecInfoInput); + if (elecInfoOutput != null) + { + var elecFileInput = new DataBillEreceiptQueryInput + { + FileId = elecInfoOutput.FileId, + }; + var elecFileOutput = await _alipayInterfaceManager.DataBillEreceiptQuery(elecFileInput); + if (!string.IsNullOrEmpty(elecFileOutput.DownloadUrl)) + { + return elecFileOutput.DownloadUrl; + } + return ""; + } + return ""; + } + else + { + WxPayTradeBillApplyRequest req = new WxPayTradeBillApplyRequest + { + OutBillNo = order.OutOrderNo, + }; + + var res = await _wxPayApi.WxPayTradeBillApply(req); + return ""; + } + } + catch (Exception ex) + { + _logger.LogError("鑾峰彇璁㈠崟鍙蜂负{0}鐢靛瓙鍥炲崟鍑虹幇閿欒锛歿1}", orderNo, ex.Message); + return ""; + } + } #endregion #region 鎿嶄綔 @@ -228,18 +824,29 @@ /// <returns></returns> public async Task<CreateLifePayOrderOutput> CreateLifePayPhoneOrder(CreateLifePayOrderInput<LifePhoneData> input) { + CheckExtensions.IfTrueThrowUserFriendlyException(input.ProductData.IspCode == "dianxin" && string.IsNullOrEmpty(input.ProductData.Name), "鐢典俊鎵嬫満鍙峰繀濉満涓诲悕"); + + var user = await _lifePayUserRepository.FirstOrDefaultAsync(x => x.Id == input.UserId); CheckExtensions.IfTrueThrowUserFriendlyException(user == null, "鐢ㄦ埛涓嶅瓨鍦紝璇峰厛鐧诲綍鍐嶆搷浣�"); + + var channle = await GetLifePayChannlesDtoByNum(input.ChannelId); + CheckExtensions.IfTrueThrowUserFriendlyException(channle == null, "娓犻亾涓嶅瓨鍦�"); var rate = await GetRate(); CheckExtensions.IfTrueThrowUserFriendlyException(rate.IsNullOrEmpty(), "鏈厤缃姌鎵�"); + //var rate = await GetLifePayRate(); + var amount = CalculateAmount(input.ProductData.ParValue, rate.FirstOrDefault(x => x.RateType == LifePayRateTypeEnum.榛樿璇濊垂鎶樻墸).Rate); + + var platformRate = await _lifePayRateRepository.FirstOrDefaultAsync(r => r.RateType == LifePayRateTypeEnum.渚涘簲鍟嗘姌鎵d环); + var orderInput = new CreateLifePayOrderInput { - OrderNo = CreateOrderNo(), - LifePayOrderStatus = LifePayOrderStatusEnum.寰呯‘璁�, + OrderNo = channle.ChannlesNum + CreateOrderNo(), + LifePayOrderStatus = LifePayOrderStatusEnum.鍏呭�间腑, LifePayOrderType = LifePayOrderTypeEnum.璇濊垂璁㈠崟, //LifePayType = input.LifePayType, OrderParamDetailJsonStr = JsonConvert.SerializeObject(input.ProductData), @@ -249,6 +856,12 @@ PayAmount = amount.PayAmont, DiscountAmount = amount.DiscountAmount, RechargeAmount = amount.RechargeAmount, + ChannelId = channle.ChannlesNum, + PlatformRate = platformRate.Rate, + PlatformDeductionAmount = amount.RechargeAmount * platformRate.Rate /100, + ChannleRate = channle.ChannlesRate, + ChannlesRakeRate = channle.ChannlesRakeRate, + //ChannlesRakePrice = amount.RechargeAmount * (channle.ChannlesRate - platformRate.Rate) / 100 * channle.ChannlesRakeRate / 100 }; await CreateLifePayOrder(orderInput); @@ -270,15 +883,21 @@ var user = await _lifePayUserRepository.FirstOrDefaultAsync(x => x.Id == input.UserId); CheckExtensions.IfTrueThrowUserFriendlyException(user == null, "鐢ㄦ埛涓嶅瓨鍦紝璇峰厛鐧诲綍鍐嶆搷浣�"); + var channle = await GetLifePayChannlesDtoByNum(input.ChannelId); + CheckExtensions.IfTrueThrowUserFriendlyException(channle == null, "娓犻亾涓嶅瓨鍦�"); + CheckExtensions.IfTrueThrowUserFriendlyException(channle.Status == LifePayChannelsStatsEnum.绂佺敤, "娓犻亾宸茶绂佺敤"); + var rate = await GetRate(); CheckExtensions.IfTrueThrowUserFriendlyException(rate.IsNullOrEmpty(), "鏈厤缃姌鎵�"); var amount = CalculateAmount(input.ProductData.ParValue, rate.FirstOrDefault(x => x.RateType == LifePayRateTypeEnum.榛樿鐢佃垂鎶樻墸).Rate); + var platformRate = await _lifePayRateRepository.FirstOrDefaultAsync(r => r.RateType == LifePayRateTypeEnum.渚涘簲鍟嗘姌鎵d环); + var orderInput = new CreateLifePayOrderInput { - OrderNo = CreateOrderNo(), - LifePayOrderStatus = LifePayOrderStatusEnum.寰呯‘璁�, + OrderNo = channle.ChannlesNum + CreateOrderNo(), + LifePayOrderStatus = LifePayOrderStatusEnum.鍏呭�间腑, LifePayOrderType = LifePayOrderTypeEnum.鐢佃垂璁㈠崟, // LifePayType = input.LifePayType, OrderParamDetailJsonStr = JsonConvert.SerializeObject(input.ProductData), @@ -288,6 +907,56 @@ PayAmount = amount.PayAmont, DiscountAmount = amount.DiscountAmount, RechargeAmount = amount.RechargeAmount, + ChannelId = channle.ChannlesNum, + PlatformRate = platformRate.Rate, + ChannleRate = channle.ChannlesRate, + ChannlesRakeRate = channle.ChannlesRakeRate, + }; + + await CreateLifePayOrder(orderInput); + + var result = new CreateLifePayOrderOutput() + { + OrderNo = orderInput.OrderNo, + }; + return result; + } + + /// <summary> + /// 鍒涘缓鐢熸椿缂磋垂鐕冩皵璁㈠崟 + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<CreateLifePayOrderOutput> CreateLifePayGasOrder(CreateLifePayOrderInput<LifeGasData> input) + { + var user = await _lifePayUserRepository.FirstOrDefaultAsync(x => x.Id == input.UserId); + CheckExtensions.IfTrueThrowUserFriendlyException(user == null, "鐢ㄦ埛涓嶅瓨鍦紝璇峰厛鐧诲綍鍐嶆搷浣�"); + + var channle = await GetLifePayChannlesDtoByNum(input.ChannelId); + CheckExtensions.IfTrueThrowUserFriendlyException(channle == null, "娓犻亾涓嶅瓨鍦�"); + CheckExtensions.IfTrueThrowUserFriendlyException(channle.Status == LifePayChannelsStatsEnum.绂佺敤, "娓犻亾宸茶绂佺敤"); + + var rate = await GetRate(); + CheckExtensions.IfTrueThrowUserFriendlyException(rate.IsNullOrEmpty(), "鏈厤缃姌鎵�"); + + var amount = CalculateAmount(input.ProductData.ParValue, rate.FirstOrDefault(x => x.RateType == LifePayRateTypeEnum.榛樿鐕冩皵鎶樻墸).Rate); + + var platformRate = await _lifePayRateRepository.FirstOrDefaultAsync(r => r.RateType == LifePayRateTypeEnum.渚涘簲鍟嗘姌鎵d环); + + var orderInput = new CreateLifePayOrderInput + { + OrderNo = channle.ChannlesNum + CreateOrderNo(), + LifePayOrderStatus = LifePayOrderStatusEnum.鍏呭�间腑, + LifePayOrderType = LifePayOrderTypeEnum.鐕冩皵璁㈠崟, + // LifePayType = input.LifePayType, + OrderParamDetailJsonStr = JsonConvert.SerializeObject(input.ProductData), + UserId = user.Id, + PayStatus = LifePayStatusEnum.鏈敮浠�, + PhoneNumber = user.PhoneNumber, + PayAmount = amount.PayAmont, + DiscountAmount = amount.DiscountAmount, + RechargeAmount = amount.RechargeAmount, + ChannelId = channle.ChannlesNum }; await CreateLifePayOrder(orderInput); @@ -312,7 +981,8 @@ CheckExtensions.IfTrueThrowUserFriendlyException(order.LifePayType.HasValue, "褰撳墠璁㈠崟宸查�夋嫨鏀粯绫诲瀷"); order.LifePayType = input.LifePayType; - + var premium = await _lifePayPremiumRepository.Where(x => x.IsDeleted == false && x.PremiumType == order.LifePayType).FirstOrDefaultAsync(); + order.PremiumRate = premium == null ? 0 : premium.Rate; await _lifePayOrderRepository.UpdateAsync(order); var desc = "鐢熸椿缂磋垂-"; @@ -323,6 +993,9 @@ break; case LifePayOrderTypeEnum.鐢佃垂璁㈠崟: desc += "鐢佃垂"; + break; + case LifePayOrderTypeEnum.鐕冩皵璁㈠崟: + desc += "鐕冩皵"; break; default: break; @@ -363,6 +1036,9 @@ case LifePayOrderTypeEnum.鐢佃垂璁㈠崟: desc += "鐢佃垂"; break; + case LifePayOrderTypeEnum.鐕冩皵璁㈠崟: + desc += "鐕冩皵"; + break; default: break; } @@ -373,12 +1049,10 @@ // var result = await PayTransactionsJsAPI(input.OpenId, input.Attach, order.PayAmount, input.OrderNo, desc); - var result = await PayTransactionsJsAPI(input.OpenId, input.Attach, order.PayAmount, input.OrderNo, desc); + var result = await PayTransactionsJsAPI(input.OpenId, input.PayAppId, input.Attach, order.PayAmount, input.OrderNo, desc); return result; //var payUrl = await GetPayQRCode(order.LifePayType.Value, order.OrderNo, desc, 0.01m, ip, input.H5Type); //var payUrl = await GetPayQRCode(order.LifePayType.Value, order.OrderNo, desc, order.PayAmount, ip, input.H5Type); - - } @@ -454,14 +1128,46 @@ return (result.Code, requestInput.RequestNo, result.ElectricChargeOrder.BusiOrderNo); } - public async Task<ModelPaymentMiniPay> PayTransactionsJsAPI(string openid, string order_guid, decimal amount, string outTradeNo, string description) + /// <summary> + /// 鍒涘缓ACOOLY鐕冩皵璁㈠崟 + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<(string Code, string RequestNo, string ACOOLYOrderNo)> CreateACOOLYGasOrder(LifeGasData input, string orderNo) { - string time_expire = DateTime.Now.AddMinutes(5).ToString("yyyy-MM-ddTHH:mm:ss") + "+08:00";//璁㈠崟澶辨晥鏃堕棿 + var requestInput = new ConfirmGasOrderRequestInput() + { + GasOrgType = input.GasOrgType, + ParValue = input.ParValue, + GasAccount = input.GasAccount, + OutOrderNo = orderNo, + AreaName = input.Province + "-" + input.City + }; + var result = await _aCOOLYManager.ConfirmGasOrder(requestInput); +#if DEBUG + + _logger.LogInformation($"CreateACOOLYGasOrder:{JsonConvert.SerializeObject(result)}"); + +#endif + + CheckExtensions.IfTrueThrowUserFriendlyException(!result.Success || (result.Code != ACOOLYConstant.Code.SUCCESS && result.Code != ACOOLYConstant.Code.PROCESSING), + "璋冪敤ACOOLY鎺ュ彛ConfirmElectricOrder杩斿洖閿欒:" + JsonConvert.SerializeObject(result)); + + return (result.Code, requestInput.RequestNo, result.GasChargeOrder.BusiOrderNo); + } + + public async Task<ModelPaymentMiniPay> PayTransactionsJsAPI(string openid, string appId, string order_guid, decimal amount, string outTradeNo, string description) + { + string time_expire = DateTime.Now.AddMinutes(5).ToString("yyyy-MM-ddTHH:mm:ss") + "+08:00"; /// 璁㈠崟澶辨晥鏃堕棿 + if (string.IsNullOrEmpty(appId)) + { + appId = _wxPayOptions.AppID; + } + ModelMiniPayRequest req = new ModelMiniPayRequest { - TimeExpire = time_expire, - Appid = _wxPayOptions.AppID, + Appid = appId, Mchid = _wxPayOptions.Mchid, Attach = order_guid, Description = description, @@ -477,16 +1183,18 @@ OpenId = openid } }; + Logger.LogError("璋冪敤璇锋眰锛�" + req.ToJson()); var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); string nonce = Guid.NewGuid().ToString(); var res = await _wxPayApi.PayTransactionsJsAPI(req); + Logger.LogError("璋冪敤缁撴灉锛�" + res.ToJson()); string package = "prepay_id=" + res.PrepayId; ModelPaymentMiniPay info = new ModelPaymentMiniPay(); if (res != null) { - string paytext = BuildSignByPay(_wxPayOptions.AppID, timestamp, nonce, package); + string paytext = BuildSignByPay(appId, timestamp, nonce, package); string paysign = _wxPayApi.GeneratePaySignByKey(paytext); info.Timestamp = timestamp.ToString(); @@ -543,11 +1251,15 @@ case LifePayOrderTypeEnum.鐢佃垂璁㈠崟: result = await CreateACOOLYElectricOrder(JsonConvert.DeserializeObject<LifeElectricData>(order.OrderParamDetailJsonStr), order.OrderNo); break; + case LifePayOrderTypeEnum.鐕冩皵璁㈠崟: + result = await CreateACOOLYGasOrder(JsonConvert.DeserializeObject<LifeGasData>(order.OrderParamDetailJsonStr), order.OrderNo); + break; default: break; } - order.LifePayOrderStatus = LifePayOrderStatusEnum.寰呯‘璁�; + order.LifePayRefundStatus = LifePayRefundStatusEnum.鏃犻渶閫�娆�; + order.LifePayOrderStatus = LifePayOrderStatusEnum.鍏呭�间腑; //SetOrderStatus(order, result.Code); order.OutRequestNo = result.RequestNo.IsNullOrEmpty() ? null : result.RequestNo; order.ACOOLYOrderNo = result.ACOOLYOrderNo.IsNullOrEmpty() ? null : result.ACOOLYOrderNo; @@ -555,11 +1267,29 @@ catch (Exception ex) { _logger.LogError(ex, "澶勭悊鐢熸椿缂磋垂鏀粯鎴愬姛鍥炶皟鏃跺紓甯�"); - order.LifePayOrderStatus = LifePayOrderStatusEnum.宸插け璐�; - order.PayStatus = LifePayStatusEnum.寰呴��娆�; + order.LifePayOrderStatus = LifePayOrderStatusEnum.寰呴��娆�; + order.LifePayRefundStatus = LifePayRefundStatusEnum.寰呴��娆�; } _logger.LogError("鐢熸椿缂磋垂璁㈠崟鐘舵�侊細" + order.LifePayOrderStatus.ToString()); await _lifePayOrderRepository.UpdateAsync(order); + } + + public async Task WxPayDomesticRefundsHandler(string orderNo, LifePayRefundStatusEnum refundStatus) + { + var order = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo).FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "璁㈠崟涓嶅瓨鍦�"); + order.LifePayRefundStatus = refundStatus; + switch (refundStatus) + { + case LifePayRefundStatusEnum.宸查��娆�: + order.LifePayOrderStatus = LifePayOrderStatusEnum.宸查��娆�; + order.ACOOLYStatus = ACOOLYStatusEnum.宸查��娆�; + break; + case LifePayRefundStatusEnum.閫�娆句腑: + order.LifePayOrderStatus = LifePayOrderStatusEnum.閫�娆句腑; + break; + default:break; + } } /// <summary> @@ -568,32 +1298,35 @@ /// <param name="orderNo"></param> /// <param name="outOrderNo"></param> /// <returns></returns> - public async Task ACOOLYOrderNotifyHandler(string orderNo, string acoolyOrderNo, LifePayOrderStatusEnum status) + public async Task ACOOLYOrderNotifyHandler(string orderNo, string acoolyOrderNo, LifePayOrderStatusEnum status, ACOOLYStatusEnum acoolyStatus, decimal payAmount,string refundApplyRemark) { var order = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo).FirstOrDefaultAsync(); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "璁㈠崟涓嶅瓨鍦�"); - if (order.LifePayOrderStatus == LifePayOrderStatusEnum.宸插畬鎴�) - { - return; - } + //if (order.LifePayOrderStatus == LifePayOrderStatusEnum.宸插畬鎴�) + //{ + // return; + //} - order.LifePayOrderStatus = status; + order.PlatformDeductionAmount = payAmount; if (acoolyOrderNo.IsNotNullOrEmpty()) { order.ACOOLYOrderNo = acoolyOrderNo; } - if (order.LifePayOrderStatus == LifePayOrderStatusEnum.宸插畬鎴�) + if (status == LifePayOrderStatusEnum.寰呴��娆�) { - order.FinishTime = DateTime.Now; + order.LifePayRefundStatus = LifePayRefundStatusEnum.寰呴��娆�; } - if (order.LifePayOrderStatus == LifePayOrderStatusEnum.宸插け璐� && order.PayStatus != LifePayStatusEnum.宸查��娆�) + if (refundApplyRemark.IsNotNullOrEmpty()) { - order.PayStatus = LifePayStatusEnum.寰呴��娆�; + order.RefundApplyRemark = refundApplyRemark; } + order.LifePayOrderStatus = status; + order.ACOOLYStatus = acoolyStatus; + order.FinishTime = DateTime.Now; await _lifePayOrderRepository.UpdateAsync(order); } @@ -608,30 +1341,415 @@ var order = await _lifePayOrderRepository.FirstOrDefaultAsync(x => x.Id == input.Id); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "璁㈠崟涓嶅瓨鍦�"); - if (order.PayStatus == LifePayStatusEnum.宸查��娆�) + if (order.LifePayRefundStatus == LifePayRefundStatusEnum.宸查��娆�) { return; } - if (order.LifePayOrderStatus != LifePayOrderStatusEnum.宸插け璐� && order.PayStatus != LifePayStatusEnum.寰呴��娆�) + if (input.RefundPrice > order.PayAmount) + { + throw new UserFriendlyException("閫�娆剧殑閲戦涓嶈兘澶т簬瀹炰粯閲戦"); + } + + if (input.LifePayRefundType == LifePayRefundTypeEnum.鍏ㄩ閫�娆�) + { + input.RefundPrice = order.PayAmount; + } + + if (order.LifePayOrderStatus != LifePayOrderStatusEnum.寰呴��娆� || order.PayStatus != LifePayStatusEnum.宸叉敮浠� || order.LifePayRefundStatus != LifePayRefundStatusEnum.寰呴��娆�) { throw new UserFriendlyException("褰撳墠璁㈠崟鐘舵�佹棤娉曢��娆�"); } - order.PayStatus = LifePayStatusEnum.宸查��娆�; - order.RefundCredentialsImgUrl = input.RefundCredentialsImgUrl; - order.RefundTime = DateTime.Now; + var outRefundNo = order.ChannelId + CreateRefundOrderNo(); + order.RefundOrderNo = outRefundNo; + switch (order.LifePayType) + { + case LifePayTypeEnum.WxPay: + var wxRefundResult = await WxPayDomesticRefunds(order.OrderNo, outRefundNo,order.RefundApplyRemark, Convert.ToInt32(input.RefundPrice * 100), Convert.ToInt32(order.PayAmount * 100)); + if (wxRefundResult.Status == "SUCCESS") + { + order.LifePayOrderStatus = LifePayOrderStatusEnum.宸查��娆�; + order.LifePayRefundStatus = LifePayRefundStatusEnum.宸查��娆�; + } + else if (wxRefundResult.Status == "PROCESSING") + { + order.LifePayOrderStatus = LifePayOrderStatusEnum.閫�娆句腑; + order.LifePayRefundStatus = LifePayRefundStatusEnum.閫�娆句腑; + } + else if (wxRefundResult.Message == "璁㈠崟宸插叏棰濋��娆�") + { + order.LifePayOrderStatus = LifePayOrderStatusEnum.宸查��娆�; + order.LifePayRefundStatus = LifePayRefundStatusEnum.宸查��娆�; + } + else + { + order.LifePayOrderStatus = LifePayOrderStatusEnum.寰呴��娆�; + order.LifePayRefundStatus = LifePayRefundStatusEnum.寰呴��娆�; + } - await _lifePayOrderRepository.UpdateAsync(order); + break; + case LifePayTypeEnum.AliPay: + var aliRefundResult = await AliTradeRefund(new AlipayTradeRefundRequest() { OutTradeNo = order.OrderNo, RefundAmount = input.RefundPrice.ToString() }); + if (aliRefundResult.Code != AlipayResultCode.Success) + { + throw new UserFriendlyException("閫�娆惧け璐�:" + aliRefundResult.SubMsg); + } + + order.LifePayOrderStatus = LifePayOrderStatusEnum.宸查��娆�; + order.LifePayRefundStatus = LifePayRefundStatusEnum.宸查��娆�; + break; + default: throw new UserFriendlyException("閫�娆惧け璐�"); + } + + order.RefundCredentialsImgUrl = input.RefundCredentialsImgUrl; + order.RefundCheckRemark = input.RefundCheckRemark; + order.RefundTime = DateTime.Now; + order.RefundCheckUserId = CurrentUser.Id; + order.RefundPrice = input.RefundPrice; + + //await _lifePayOrderRepository.UpdateAsync(order); #region 璁板綍鏃ュ織 - await PublishLifePayOrderHistoryEvent("閫�娆�", "閫�娆�", order.Id); + await LifePayOrderHistory("閫�娆�", "閫�娆�", order.Id, (int)OperateHistoryTypeEnum.LifePayRefund); #endregion } + /// <summary> + /// 鐢ㄦ埛鍙戣捣鐢熸椿缂磋垂閫�娆� + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + /// <exception cref="UserFriendlyException"></exception> + public async Task RefundUserLifePayOrder(RefundUserLifePayOrderInput input) + { + var order = await _lifePayOrderRepository.FirstOrDefaultAsync(x => x.Id == input.Id); + CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "璁㈠崟涓嶅瓨鍦�"); + if (order.UserId != input.UserId) + { + throw new UserFriendlyException("闈炵敤鎴锋湰浜洪��娆�"); + } + + if (order.LifePayRefundStatus == LifePayRefundStatusEnum.宸查��娆�) + { + return; + } + + if (order.PayStatus == LifePayStatusEnum.宸叉敮浠� && order.LifePayOrderStatus != LifePayOrderStatusEnum.宸插畬鎴� + && order.LifePayOrderStatus != LifePayOrderStatusEnum.寰呴��娆� && order.LifePayOrderStatus != LifePayOrderStatusEnum.宸查��娆�) + { + order.LifePayOrderStatus = LifePayOrderStatusEnum.寰呴��娆�; + order.LifePayRefundStatus = LifePayRefundStatusEnum.寰呴��娆�; + order.RefundApplyRemark = input.RefundApplyRemark; + order.RefundApplyTime = DateTime.Now; + await _lifePayOrderRepository.UpdateAsync(order); + } + else if (order.LifePayOrderStatus == LifePayOrderStatusEnum.寰呴��娆� || order.LifePayRefundStatus == LifePayRefundStatusEnum.寰呴��娆� || + order.LifePayOrderStatus == LifePayOrderStatusEnum.閫�娆句腑 || order.LifePayRefundStatus == LifePayRefundStatusEnum.閫�娆句腑 || + order.LifePayOrderStatus == LifePayOrderStatusEnum.宸查��娆� || order.LifePayRefundStatus == LifePayRefundStatusEnum.宸查��娆�) + { + throw new UserFriendlyException("褰撳墠璁㈠崟鏃犳硶閲嶅鐢宠閫�娆�"); + } + else + { + throw new UserFriendlyException("褰撳墠璁㈠崟鐘舵�佹棤娉曠敵璇烽��娆�"); + } + } + + /// <summary> + /// 寰俊閫�娆� + /// </summary> + /// <param name="outTradeNo"></param> + /// <param name="reason"></param> + /// <param name="refund"></param> + /// <param name="total"></param> + /// <param name="currency"></param> + /// <returns></returns> + public async Task<WxPayDomesticRefundsReponse> WxPayDomesticRefunds(string outTradeNo,string outRefundNo, string reason, int refund, int total, string currency = "CNY") + { + WxPayDomesticRefundsRequest req = new WxPayDomesticRefundsRequest + { + OutTradeNo = outTradeNo, + OutRefundNo = outRefundNo, + //Reason = reason, + Amount = new Model_WxPayDomesticRefunds_Amount + { + Refund = refund, + Total = total, + Currency = "CNY" + }, + NotifyUrl = $"{_wxPayOptions.NotifyUrl}{LifePaymentConstant.WxPayDomesticRefundsNotifySectionUrl}", + }; + + var res = await _wxPayApi.WxPayDomesticRefunds(req); + return res; + } + + private async Task<AlipayTradeRefundResponse> AliTradeRefund(AlipayTradeRefundRequest input) + { + return await _aliPayApi.TradeRefund(input); + } + + public async Task<int> AddUpdateUserAccount(AddUpdateUserAccountInput input) + { + var user = await _lifePayUserRepository.Where(r => r.Id == input.UserId && !r.IsDeleted).FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(user == null, "鐢ㄦ埛涓嶅瓨鍦�"); + + if (input.Id.HasValue) + { + var userAccount = await _lifePayAccount.Where(x => x.UserId == input.UserId && x.Id == input.Id) + .FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(userAccount == null, "鎴峰彿涓嶅瓨鍦�"); + var repeatAccountContent = await _lifePayAccount.Where(x => x.UserId == input.UserId && x.LifePayType == input.LifePayType && x.Content == input.Content && x.Id != input.Id) + .FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(repeatAccountContent != null, "鎴峰彿宸插瓨鍦�"); + + userAccount.LifePayType = input.LifePayType; + userAccount.Content = input.Content; + userAccount.Province = input.Province; + userAccount.City = input.City; + userAccount.Remark = input.Remark; + userAccount.Operators = input.Operators; + userAccount.ExtraProperties = input.ExtraProperties; + } + else + { + var repeatAccountContent = await _lifePayAccount.Where(x => x.UserId == input.UserId && x.LifePayType == input.LifePayType && x.Content == input.Content) + .FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(repeatAccountContent != null, "鎴峰彿宸插瓨鍦�"); + var userAccount = new LifePayAccount + { + Id = Guid.NewGuid(), + UserId = input.UserId, + Content = input.Content, + Province = input.Province, + LifePayType = input.LifePayType, + City = input.City, + Remark = input.Remark, + Operators = input.Operators, + ExtraProperties = input.ExtraProperties, + }; + await _lifePayAccount.InsertAsync(userAccount); + } + + if (input.LifePayType == LifePayOrderTypeEnum.璇濊垂璁㈠崟) + { + var extraProperties = JsonConvert.DeserializeObject<Model_UserAccountExtraProperties>(input.ExtraProperties); + if (!string.IsNullOrEmpty(extraProperties.Name) && extraProperties.Phone == user.PhoneNumber) + { + user.Name = extraProperties.Name; + } + } + + + return Constant.SUCCESS; + } + + /// <summary> + /// 鐢ㄦ埛鍒犻櫎鎴峰彿淇℃伅 + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public async Task<int> DeleteUserAccount(Guid id) + { + var userAccount = await _lifePayAccount.Where(x => x.Id == id) + .FirstOrDefaultAsync(); + CheckExtensions.IfTrueThrowUserFriendlyException(userAccount == null, "鎴峰彿涓嶅瓨鍦�"); + userAccount.DeleterId = userAccount.UserId; + userAccount.DeletionTime = DateTime.Now; + userAccount.IsDeleted = true; + return Constant.SUCCESS; + } + + /// <summary> + /// 閫�娆鹃┏鍥� + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + /// <exception cref="UserFriendlyException"></exception> + public async Task RejectRefundLifePayOrder(RefundLifePayOrderInput input) + { + var order = await _lifePayOrderRepository.FirstOrDefaultAsync(x => x.Id == input.Id); + CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "璁㈠崟涓嶅瓨鍦�"); + + if (order.LifePayRefundStatus == LifePayRefundStatusEnum.宸查��娆�) + { + return; + } + + if (order.LifePayOrderStatus == LifePayOrderStatusEnum.寰呴��娆� || order.LifePayRefundStatus == LifePayRefundStatusEnum.寰呴��娆�) + { + if (order.ACOOLYStatus == ACOOLYStatusEnum.宸插畬鎴� || order.ACOOLYStatus == ACOOLYStatusEnum.鍏呭�兼垚鍔� || order.ACOOLYStatus == ACOOLYStatusEnum.閮ㄥ垎鍏呭�兼垚鍔�) + { + order.LifePayOrderStatus = LifePayOrderStatusEnum.宸插畬鎴�; + } + + order.RefundCheckRemark = input.RefundCheckRemark; + order.RefundCheckUserId = CurrentUser.Id; + order.LifePayRefundStatus = LifePayRefundStatusEnum.閫�娆鹃┏鍥�; + + await _lifePayOrderRepository.UpdateAsync(order); + + #region 璁板綍鏃ュ織 + + await PublishLifePayOrderHistoryEvent("閫�娆鹃┏鍥�", "閫�娆�", order.Id); + + #endregion + } + else + { + throw new UserFriendlyException("褰撳墠璁㈠崟鐘舵�佹棤娉曢��娆�"); + } + + + } + + public async Task CreateEditPayChannels(CreateEditPayChannelsInput input) + { + if (input.Id.HasValue) + { + var dto = await _lifePayChannlesRep.FirstOrDefaultAsync(r => r.Id == input.Id.Value); + CheckExtensions.IfTrueThrowUserFriendlyException(dto == null, "鏈幏鍙栧埌娓犻亾鎶樻墸鏁版嵁"); + dto.ChannlesName = input.ChannlesName; + dto.ChannlesNum = input.ChannlesNum; + dto.ChannlesRate = input.ChannlesRate; + dto.ChannlesRakeRate = input.ChannlesRakeRate; + dto.SwitchType = input.SwitchType; + dto.ChannlesType = input.ChannlesType; + dto.Status = input.Status; + #region 璁板綍鏃ュ織 + + await PublishLifePayOrderHistoryEvent("娓犻亾绠$悊", "缂栬緫", input.Id.Value, TableType.LifePayChannles); + + #endregion + } + else + { + CheckExtensions.IfTrueThrowUserFriendlyException(input.ChannlesRate < 0.01m, "娓犻亾鎶樻墸璁剧疆閿欒"); + input.Id = Guid.NewGuid(); + var entity = ObjectMapper.Map<CreateEditPayChannelsInput, LifePayChannles>(input); + await _lifePayChannlesRep.InsertAsync(entity); + + #region 璁板綍鏃ュ織 + + await PublishLifePayOrderHistoryEvent("娓犻亾绠$悊", "鏂板", input.Id.Value, TableType.LifePayChannles); + + #endregion + } + + + } + + public async Task SetLifePayChannelsStatus(Guid id, LifePayChannelsStatsEnum status) + { + await _lifePayChannlesRep.Where(r => r.Id == id).UpdateAsync(r => new LifePayChannles + { + Status = status, + }); + + #region 璁板綍鏃ュ織 + + await PublishLifePayOrderHistoryEvent("娓犻亾绠$悊", status.GetDescription(), id, TableType.LifePayChannles); + + #endregion + } + + public async Task<bool> CheckChannelsStatus(string channlesId) + { + var dto = await _lifePayChannlesRep.FirstOrDefaultAsync(r => r.ChannlesNum == channlesId); + CheckExtensions.IfTrueThrowUserFriendlyException(dto == null, "褰撳墠娓犻亾鍟嗕笉瀛樺湪"); + CheckExtensions.IfTrueThrowUserFriendlyException(dto.Status == LifePayChannelsStatsEnum.绂佺敤, "褰撳墠娓犻亾鍟嗗凡绂佺敤"); + return true; + } + + public async Task CreateEditLifePayRate(List<LifePayRateInput> input) + { + CheckExtensions.IfTrueThrowUserFriendlyException(input.Where(r => r.Rate <= 0).Any(), "鎶樻墸涓嶅緱灏忎簬绛変簬0"); + var baseRate = input.FirstOrDefault(r => r.RateType == LifePayRateTypeEnum.渚涘簲鍟嗘姌鎵d环)?.Rate; + var listData = new List<LifePayRate>(); + foreach (var item in input) + { + CheckExtensions.IfTrueThrowUserFriendlyException(item.Rate < (baseRate ?? 0), "鎶樻墸涓嶅緱灏忎簬渚涘簲鍟嗘姌鎵�"); + var tmpDto = await _lifePayRateRepository.FirstOrDefaultAsync(r => r.RateType == item.RateType); + if (tmpDto != null) + { + tmpDto.Rate = item.Rate; + } + else + { + listData.Add(new LifePayRate + { + CreationTime = DateTime.Now, + Rate = item.Rate, + RateType = item.RateType, + Id = Guid.NewGuid(), + }); + } + } + + if (listData.Any()) + { + await _lifePayRateRepository.InsertManyAsync(listData); + } + } + + public async Task CreateEditLifePayPremium(List<LifePayPremiumInput> input) + { + CheckExtensions.IfTrueThrowUserFriendlyException(input.Where(r => r.Rate < 0).Any(), "鎶樻墸涓嶅緱灏忎簬0"); + var listData = new List<LifePayPremium>(); + foreach (var item in input) + { + var tmpDto = await _lifePayPremiumRepository.FirstOrDefaultAsync(r => r.PremiumType == item.PremiumType); + if (tmpDto != null) + { + tmpDto.Rate = item.Rate; + } + else + { + listData.Add(new LifePayPremium + { + CreationTime = DateTime.Now, + Rate = item.Rate, + PremiumType = item.PremiumType, + Id = Guid.NewGuid(), + }); + } + } + + if (listData.Any()) + { + await _lifePayPremiumRepository.InsertManyAsync(listData); + } + } + + public async Task EditIntroInfo(LifePayIntroInfoInput input) + { + var listData = new List<LifePayIntroInfo>(); + foreach (var item in input.Data) + { + var tmpDto = await _lifePayIntroInfoRepository.Where(r => r.LifePayType == input.LifePayType).DeleteAsync(); + + listData.Add(new LifePayIntroInfo + { + LifePayType = input.LifePayType, + CreationTime = DateTime.Now, + Type = item.Type, + ContentSummary = item.ContentSummary, + Content = item.Content, + Path = item.Path, + Sequence = item.Sequence, + Id = Guid.NewGuid(), + }); + } + + if (listData.Any()) + { + await _lifePayIntroInfoRepository.InsertManyAsync(listData); + } + } #endregion #region 绉佹湁 @@ -641,9 +1759,19 @@ return "JF" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + GlobalRandom.GetRandomNum(4); } + private string CreateRefundOrderNo() + { + return "JFTK" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + GlobalRandom.GetRandomNum(4); + } + private (decimal PayAmont, decimal DiscountAmount, decimal RechargeAmount) CalculateAmount(decimal amount, decimal rate) { - var payAmount = decimal.Round(amount * rate, 2, MidpointRounding.AwayFromZero); + /// 姝e父鏀粯 + //var payAmount = decimal.Round(amount * rate / 100, 2, MidpointRounding.AwayFromZero); + + /// 1鍒嗛挶鏀粯 + decimal payAmount = 0.01m; + CheckExtensions.IfTrueThrowUserFriendlyException(payAmount < 0.01m, "鏀粯閲戦閿欒"); return (payAmount, amount - payAmount, amount); @@ -658,7 +1786,7 @@ order.FinishTime = DateTime.Now; break; case ACOOLYConstant.Code.PROCESSING: - order.LifePayOrderStatus = LifePayOrderStatusEnum.寰呯‘璁�; + order.LifePayOrderStatus = LifePayOrderStatusEnum.鍏呭�间腑; break; default: break; @@ -684,6 +1812,20 @@ await _distributedEventBus.PublishAsync(recordEto, false); } + private async Task LifePayOrderHistory(string operateContent, string operateName, Guid relationId, int? tableType = (int)OperateHistoryTypeEnum.LifePayRefund) + { + var operateHistory = new OperateHistory + { + CreatorName = CurrentUser.Name, + OperateContent = operateName, + OperateName = operateName, + RelationId = relationId, + TableType = tableType + + }; + await _operateHistory.InsertAsync(operateHistory); + } + /// <summary> /// 鑾峰彇鏀粯浜岀淮鐮� /// </summary> @@ -697,9 +1839,6 @@ { var codeUrl = string.Empty; switch (payType) - - - { case LifePayTypeEnum.AliPay: codeUrl = await GetAliPayQRCode(outTradeNo, description, amount); @@ -765,7 +1904,6 @@ CheckExtensions.IfTrueThrowUserFriendlyException(amount <= 0, CustomeErrorMessage.SometingMustSometing, "鑾峰彇鏀粯浜岀淮鐮佹椂閲戦", "澶т簬0"); - var res = await _wxPayApi.PayTransactionsH5(new PayTransactionsNativeH5 { Appid = _wxPayOptions.AppID, @@ -818,6 +1956,7 @@ return res.QrCode; } + /// <summary> /// 鏋勯�犲緟绛惧悕瀛楃涓� /// </summary> @@ -834,5 +1973,167 @@ } + private async Task<IQueryable<LifePayOrderListOutput>> GetLifePayOrderListFilter(QueryLifePayOrderListInput input) + { + var channles = await _lifePayChannlesRep.Where(x => x.ChannlesName.Contains(input.KeyWords)).Select(x => x.ChannlesNum).ToListAsync(); + var result = (from a in _channelFilter.GetChannelLifePayOrderFilter(_lifePayOrderRepository) + .WhereIf(input.BeginFinishTime.HasValue, x => x.FinishTime >= input.BeginFinishTime) + .WhereIf(input.EndFinishTime.HasValue, x => x.FinishTime <= input.EndFinishTime) + .WhereIf(input.BeginPayTime.HasValue, x => x.PayTime >= input.BeginPayTime) + .WhereIf(input.LifePayType.HasValue, x => x.LifePayType == input.LifePayType) + .WhereIf(input.EndPayTime.HasValue, x => x.PayTime <= input.EndPayTime) + .WhereIf(input.LifePayOrderStatus.HasValue, x => x.LifePayOrderStatus == input.LifePayOrderStatus.Value) + .WhereIf(input.PayStatus.HasValue, x => x.PayStatus == input.PayStatus.Value) + .WhereIf(input.ACOOLYStatus.HasValue, x => x.ACOOLYStatus == input.ACOOLYStatus.Value) + .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayOrderType == input.LifePayOrderType.Value) + .WhereIf(input.UserId.HasValue, x => x.UserId == input.UserId.Value) + .WhereIf(input.KeyWords.IsNotNullOrEmpty(), x => x.OrderNo.Contains(input.KeyWords) || x.OutOrderNo.Contains(input.KeyWords) || x.ACOOLYOrderNo.Contains(input.KeyWords) || channles.Contains(x.ChannelId)) + join b in _lifePayChannlesRep on a.ChannelId equals b.ChannlesNum into temp + from b in temp.DefaultIfEmpty() + select new LifePayOrderListOutput + { + DiscountAmount = a.DiscountAmount, + FinishTime = a.FinishTime, + Id = a.Id, + LifePayOrderStatus = a.LifePayOrderStatus, + LifePayOrderType = a.LifePayOrderType, + LifePayType = a.LifePayType, + OrderNo = a.OrderNo, + PayAmount = a.PayAmount, + PhoneNumber = a.PhoneNumber, + RechargeAmount = a.RechargeAmount, + UserId = a.UserId, + OutOrderNo = a.OutOrderNo, + PayStatus = a.PayStatus, + PayTime = a.PayTime, + ACOOLYOrderNo = a.ACOOLYOrderNo, + RefundCredentialsImgUrl = a.RefundCredentialsImgUrl.GetOssPath(), + RefundPrice = a.RefundPrice, + CreationTime = a.CreationTime, + RefundCheckRemark = a.RefundCheckRemark, + RefundApplyRemark = a.RefundApplyRemark, + RefundTime = a.RefundTime, + ChannelName = b.ChannlesName, + ActualRechargeAmount = a.ActualRechargeAmount, + PlatformDeductionAmount = a.PlatformDeductionAmount, + ACOOLYStatus = a.ACOOLYStatus, + LifePayRefundStatus = a.LifePayRefundStatus, + }); + + + return result; + } + + private async Task<IQueryable<LifePayOrderListOutput>> GetLifePayRefundOrderListFilter(QueryLifePayRefundOrderListInput input) + { + var result = (from a in _channelFilter.GetChannelLifePayOrderFilter(_lifePayOrderRepository) + .Where(x => x.LifePayOrderStatus == LifePayOrderStatusEnum.寰呴��娆� || x.LifePayOrderStatus == LifePayOrderStatusEnum.宸查��娆� || x.LifePayOrderStatus == LifePayOrderStatusEnum.閫�娆句腑 + || (x.LifePayRefundStatus > LifePayRefundStatusEnum.鏃犻渶閫�娆� && x.LifePayRefundStatus != LifePayRefundStatusEnum.閫�娆鹃┏鍥�)) + .WhereIf(input.BeginRefundTime.HasValue, x => x.RefundTime >= input.BeginRefundTime) + .WhereIf(input.EndRefundTime.HasValue, x => x.RefundTime <= input.EndRefundTime) + .WhereIf(input.BeginRefundApplyTime.HasValue, x => x.RefundApplyTime >= input.BeginRefundApplyTime) + .WhereIf(input.LifePayType.HasValue, x => x.LifePayType == input.LifePayType) + .WhereIf(input.EndRefundApplyTime.HasValue, x => x.RefundApplyTime <= input.EndRefundApplyTime) + .WhereIf(input.LifePayOrderStatus.HasValue, x => x.LifePayOrderStatus == input.LifePayOrderStatus.Value) + .WhereIf(input.ACOOLYStatus.HasValue, x => x.ACOOLYStatus == input.ACOOLYStatus.Value) + .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayOrderType == input.LifePayOrderType.Value) + .WhereIf(input.UserId.HasValue, x => x.UserId == input.UserId.Value) + .WhereIf(input.KeyWords.IsNotNullOrEmpty(), x => x.PhoneNumber.Contains(input.KeyWords) || x.OrderNo.Contains(input.KeyWords) || x.OutOrderNo.Contains(input.KeyWords) || x.ACOOLYOrderNo.Contains(input.KeyWords)) + join b in _lifePayChannlesRep on a.ChannelId equals b.ChannlesNum into temp + from b in temp.DefaultIfEmpty() + select new LifePayOrderListOutput + { + DiscountAmount = a.DiscountAmount, + FinishTime = a.FinishTime, + Id = a.Id, + LifePayOrderStatus = a.LifePayOrderStatus, + LifePayOrderType = a.LifePayOrderType, + LifePayType = a.LifePayType, + OrderNo = a.OrderNo, + PayAmount = a.PayAmount, + PhoneNumber = a.PhoneNumber, + RechargeAmount = a.RechargeAmount, + UserId = a.UserId, + OutOrderNo = a.OutOrderNo, + PayStatus = a.PayStatus, + PayTime = a.PayTime, + ACOOLYOrderNo = a.ACOOLYOrderNo, + RefundCredentialsImgUrl = a.RefundCredentialsImgUrl.GetOssPath(), + CreationTime = a.CreationTime, + RefundCheckRemark = a.RefundCheckRemark, + RefundApplyRemark = a.RefundApplyRemark, + RefundApplyTime = a.RefundApplyTime, + RefundTime = a.RefundTime, + RefundPrice = a.RefundPrice, + ChannelName = b.ChannlesName, + ActualRechargeAmount = a.ActualRechargeAmount, + PlatformDeductionAmount = a.PlatformDeductionAmount, + ACOOLYStatus = a.ACOOLYStatus, + LifePayRefundStatus = a.LifePayRefundStatus, + ActualReceivedAmount = a.ActualReceivedAmount.HasValue? a.ActualReceivedAmount.Value : 0 + }); + return result; + } + private IQueryable<CreateEditPayChannelsInput> GetLifePayChannlesListFilter() + { + return _lifePayChannlesRep.Select(x => + new CreateEditPayChannelsInput + { + Id = x.Id, + ChannlesRate = x.ChannlesRate, + ChannlesRakeRate = x.ChannlesRakeRate, + ChannlesName = x.ChannlesName, + ChannlesNum = x.ChannlesNum, + Status = x.Status, + SwitchType = x.SwitchType, + ChannlesType = x.ChannlesType, + }); + } + + public async Task<OrderPriceReturn> GetOrderPrice(decimal price, decimal priceAmount, decimal? platformRate,decimal? channleRate, + decimal? channlesRakeRate,decimal? premiumRate) + { + /// 姣涘埄 + var grossProfit = price * (channleRate - platformRate) / 100; + + /// 骞冲彴鎵f閲戦 鍏呭�奸潰棰� * 骞冲彴鎶樻墸姣斾緥 + var platformPrice = price * platformRate / 100; + + /// 鎵嬬画璐� + var premiumPrice = priceAmount * premiumRate / 100; + + /// 娓犻亾浣i噾 锛�(鍏呭�奸潰棰� * 娓犻亾鎶樻墸姣斾緥)-(鍏呭�奸潰棰� * 骞冲彴鎶樻墸姣斾緥)锛�* 浣i噾姣斾緥 + var channlesRakePrice = grossProfit * channlesRakeRate / 100; + + /// 鍒╂鼎 + var profit = grossProfit - channlesRakePrice - premiumPrice; + + return new OrderPriceReturn() + { + PlatformPrice = platformPrice.HasValue? platformPrice.Value :0, + PremiumPrice = premiumPrice.HasValue ? premiumPrice.Value : 0, + ChannlesRakePrice = channlesRakePrice.HasValue? channlesRakePrice.Value:0, + Profit = profit.HasValue ? profit.Value : 0 + }; + } + + public async Task<decimal> GetLifePayRate(string channelId, LifePayRateTypeEnum lifePayRateType) + { + if (string.IsNullOrEmpty(channelId)) + { + var rate = await GetRate(); + CheckExtensions.IfTrueThrowUserFriendlyException(rate.IsNullOrEmpty(), "鏈厤缃姌鎵�"); + var result = rate.FirstOrDefault(x => x.RateType == lifePayRateType).Rate; + return result; + } + else + { + var channel = await _lifePayChannlesRep.Where(x => x.ChannlesNum == channelId).FirstOrDefaultAsync(); + + CheckExtensions.IfTrueThrowUserFriendlyException(channel == null, "鏈壘鍒板搴旀笭閬�"); + return channel.ChannlesRate; + } + } + #endregion } -- Gitblit v1.9.1