using LifePayment.Application.Contracts; using LifePayment.Domain; using LifePayment.Domain.LifePay; using LifePayment.Domain.Models; using LifePayment.Domain.Shared; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic.Core; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application.Services; using Volo.Abp.Data; using Volo.Abp.Domain.Repositories; using Volo.Abp.EventBus.Distributed; using Z.EntityFramework.Plus; using ZeroD.Util; using Alipay.EasySDK.Payment.Common.Models; using static LifePayment.Domain.Shared.LifePaymentConstant; namespace LifePayment.Application; public class LifePayService : ApplicationService, ILifePayService { private readonly IDistributedEventBus _distributedEventBus; private readonly ILogger _logger; private readonly IRepository _lifePayRateRepository; private readonly IRepository _lifePayPremiumRepository; private readonly IRepository _lifePayOrderRepository; private readonly IRepository _lifePayUserRepository; private readonly IRepository _lifePayIntroInfoRepository; private readonly IRepository _lifePayChannlesRep; private readonly IRepository _lifePayAccount; private readonly IDataFilter dataFilter; private readonly IChannelFilter _channelFilter; private readonly IAliPayApi _aliPayApi; private readonly IWxPayApi _wxPayApi; private readonly WxPayOption _wxPayOptions; private readonly IACOOLYManager _aCOOLYManager; public LifePayService(IDistributedEventBus distributedEventBus, ILogger logger, IACOOLYManager aCOOLYManager, IRepository lifePayRateRepository, IRepository lifePayOrderRepository, IRepository lifePayUserRepository, IRepository lifePayPremiumRepository, IRepository lifePayIntroInfoRepository, IAliPayApi aliPayApi, IWxPayApi wxPayApi, IOptions wxPayOptions, IRepository lifePayChannlesRep, IRepository lifePayAccount, IDataFilter dataFilter, IChannelFilter channelFilter) { _logger = logger; _aCOOLYManager = aCOOLYManager; _lifePayRateRepository = lifePayRateRepository; _lifePayOrderRepository = lifePayOrderRepository; _lifePayUserRepository = lifePayUserRepository; _lifePayPremiumRepository = lifePayPremiumRepository; _lifePayIntroInfoRepository = lifePayIntroInfoRepository; _aliPayApi = aliPayApi; _wxPayApi = wxPayApi; _wxPayOptions = wxPayOptions.Value; _distributedEventBus = distributedEventBus; _lifePayChannlesRep = lifePayChannlesRep; _lifePayAccount = lifePayAccount; this.dataFilter = dataFilter; _channelFilter = channelFilter; } #region 查询 /// /// 获取电费面值 /// /// /// public async Task GetElectricParValue() { return await _aCOOLYManager.ElectricParValue(new ACOOLYRequestBaseInput()); } /// /// 获取电费充值区域 /// /// public async Task GetElectricSupportArea() { return await _aCOOLYManager.GetElectricSupportArea(new ACOOLYRequestBaseInput()); } /// /// 获取话费面值 /// /// /// public async Task GetPhoneParValue() { return await _aCOOLYManager.PhoneParValue(new ACOOLYRequestBaseInput()); } /// /// 获取话费面值 /// /// /// public async Task GetGasParValue() { return await _aCOOLYManager.GasParValue(new GasParValueRequestInput()); } /// /// 获取燃气支持商户 /// /// public async Task GetGasOrgType() { return await _aCOOLYManager.GasOrgType(new GasOrgTypeRequestInput()); } /// /// 获取折扣 /// /// public async Task> GetRate() { return await _lifePayRateRepository.Where(x => x.IsDeleted == false).Select(x => new LifePayRateListOutput() { Id = x.Id, Rate = x.Rate, RateType = x.RateType }) .ToListAsync(); } /// /// 获取手续费费率 /// /// public async Task> GetPremium() { return await _lifePayPremiumRepository.Where(x => x.IsDeleted == false).Select(x => new LifePayPremiumListOutput() { Id = x.Id, Rate = x.Rate, PremiumType = x.PremiumType }) .ToListAsync(); } /// /// 须知配置 /// /// public async Task> 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(); } /// /// 获取用户分页数据 /// /// /// public async Task> GetUserPage(QueryUserPageInput input) { 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.CreationTime.HasValue, x => x.CreationTime.ToString("yyyy-MM-dd") == input.CreationTime.Value.ToString("yyyy-MM-dd")) .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); } /// /// 获取用户户号分页数据 /// /// /// public async Task> GetAccountPage(QueryUserAccountListInput input) { using (dataFilter.Disable()) { 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); } } /// /// 获取订单分页数据 /// /// /// public async Task> GetLifePayOrderPage(QueryLifePayOrderListInput input) { 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.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, RefundTime = a.RefundTime, ChannelName = b.ChannlesName, ActualRechargeAmount = a.ActualRechargeAmount, PlatformDeductionAmount = a.PlatformDeductionAmount, ACOOLYStatus = a.ACOOLYStatus, LifePayRefundStatus = a.LifePayRefundStatus, }).GetPageResult(input.PageModel); return result; } public async Task GetLifePayOrderDetail(string orderNo) { var result = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo) .Select(x => new LifePayOrderOutput { 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; } /// /// 获取我的订单分页数据 /// /// /// public async Task> GetUserLifePayOrderPage(QueryLifePayOrderListInput input) { if (!input.UserId.HasValue) { return new PageOutput(); } 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) .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.UserId.HasValue, x => x.UserId == input.UserId.Value) .WhereIf(input.LifePayOrderType.HasValue, x => x.LifePayOrderType == input.LifePayOrderType) .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, }) .GetPageResult(input.PageModel); } public async Task 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; } /// /// 根据订单号获取支付状态 /// /// /// public async Task GetPayStatusByOrderNo(string orderNo) { return await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo) .Select(x => x.PayStatus) .FirstOrDefaultAsync(); } public async Task> GetLifePayChannlesPage(PageInput input) { return await GetLifePayChannlesListFilter().GetPageResult(input.PageModel); } public async Task> GetLifePayChannlesAllList() { return await GetLifePayChannlesListFilter().Where(x => x.Status == LifePayChannelsStatsEnum.启用).ToListAsync(); } public async Task 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 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 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> GetUserAccountList(QueryUserAccountListInput input) { if (!input.UserId.HasValue) { return new PageOutput(); } 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> GetUserAccountAllList(QueryUserAccountAllListInput input) { if (!input.UserId.HasValue) { return new List(); } 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 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> 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, PhoneNumber = x.PhoneNumber, RechargeAmount = x.RechargeAmount, OutOrderNo = x.OutOrderNo, PayStatus = x.PayStatus, PayTime = x.PayTime, ACOOLYOrderNo = x.ACOOLYOrderNo, CreationTime = x.CreationTime, RefundApplyRemark = x.RefundApplyRemark, ChannelName = x.ChannelName }).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.yyyyMMddHHmm); 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.yyyyMMddHHmm); s.LifePayTypeStr = s.LifePayType.GetDescription(); s.PayStatusStr = s.PayStatus.GetDescription(); s.LifePayOrderStatusStr = s.LifePayOrderStatus.GetDescription(); s.FinishTimeStr = !s.FinishTime.HasValue ? string.Empty : s.FinishTime.Value.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmm); }); return result; } #endregion #region 操作 /// /// 创建生活缴费话费订单 /// /// /// public async Task CreateLifePayPhoneOrder(CreateLifePayOrderInput 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 amount = CalculateAmount(input.ProductData.ParValue, rate.FirstOrDefault(x => x.RateType == LifePayRateTypeEnum.默认话费折扣).Rate); 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); var result = new CreateLifePayOrderOutput() { OrderNo = orderInput.OrderNo, }; return result; } /// /// 创建生活缴费电费订单 /// /// /// public async Task CreateLifePayElectricOrder(CreateLifePayOrderInput 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 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); var result = new CreateLifePayOrderOutput() { OrderNo = orderInput.OrderNo, }; return result; } /// /// 创建生活缴费燃气订单 /// /// /// public async Task CreateLifePayGasOrder(CreateLifePayOrderInput 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 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); var result = new CreateLifePayOrderOutput() { OrderNo = orderInput.OrderNo, }; return result; } /// /// 设置生活缴费支付类型 /// /// /// public async Task SetLifePayOrderPayType(SetLifePayOrderPayTypeInput input, string ip) { var order = await _lifePayOrderRepository.Where(x => x.OrderNo == input.OrderNo).FirstOrDefaultAsync(); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "订单不存在"); CheckExtensions.IfTrueThrowUserFriendlyException(order.LifePayType.HasValue, "当前订单已选择支付类型"); order.LifePayType = input.LifePayType; await _lifePayOrderRepository.UpdateAsync(order); var desc = "生活缴费-"; switch (order.LifePayOrderType) { case LifePayOrderTypeEnum.话费订单: desc += "话费"; break; case LifePayOrderTypeEnum.电费订单: desc += "电费"; break; default: break; } #if DEBUG //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); #else //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); #endif return payUrl; } /// /// 设置生活缴费支付类型 /// /// /// public async Task GetPayOrderForJsAPI(GetPayOrderForJsAPIInput input, string ip) { var order = await _lifePayOrderRepository.Where(x => x.OrderNo == input.OrderNo).FirstOrDefaultAsync(); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "订单不存在"); CheckExtensions.IfTrueThrowUserFriendlyException(order.LifePayType.HasValue, "当前订单已选择支付类型"); order.LifePayType = input.LifePayType; await _lifePayOrderRepository.UpdateAsync(order); var desc = "生活缴费-"; switch (order.LifePayOrderType) { case LifePayOrderTypeEnum.话费订单: desc += "话费"; break; case LifePayOrderTypeEnum.电费订单: desc += "电费"; break; case LifePayOrderTypeEnum.燃气订单: desc += "燃气"; break; default: break; } //var result = await PayTransactionsJsAPI(input.OpenId, input.Attach, 0.01m, input.OrderNo, desc); //return result; // 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); } /// /// 创建生活缴费订单 /// /// /// public async Task CreateLifePayOrder(CreateLifePayOrderInput input) { CheckExtensions.IfTrueThrowUserFriendlyException(input.RechargeAmount < 0.01m || input.PayAmount < 0.01m || input.DiscountAmount < 0, "订单金额错误"); var entity = ObjectMapper.Map(input); await _lifePayOrderRepository.InsertAsync(entity); } /// /// 创建ACOOLY话费订单 /// /// /// public async Task<(string Code, string RequestNo, string ACOOLYOrderNo)> CreateACOOLYPhoneOrder(LifePhoneData input, string orderNo) { var requestInput = new ConfirmPhoneOrderRequestInput() { IspCode = input.IspCode, ParValue = input.ParValue, Phone = input.Phone, OutOrderNo = orderNo, Name = input.Name }; var result = await _aCOOLYManager.ConfirmPhoneOrder(requestInput); #if DEBUG _logger.LogInformation($"CreateACOOLYPhoneOrder:{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.PhoneChargeOrder.BusiOrderNo); } /// /// 创建ACOOLY电费订单 /// /// /// public async Task<(string Code, string RequestNo, string ACOOLYOrderNo)> CreateACOOLYElectricOrder(LifeElectricData input, string orderNo) { var requestInput = new ConfirmElectricOrderRequestInput() { City = input.City, ElectricAccount = input.ElectricAccount, ElectricAccountType = input.ElectricAccountType, ElectricType = input.ElectricType, ParValue = input.ParValue, Province = input.Province, SixID = input.SixID, OutOrderNo = orderNo }; var result = await _aCOOLYManager.ConfirmElectricOrder(requestInput); #if DEBUG _logger.LogInformation($"CreateACOOLYElectricOrder:{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.ElectricChargeOrder.BusiOrderNo); } /// /// 创建ACOOLY燃气订单 /// /// /// public async Task<(string Code, string RequestNo, string ACOOLYOrderNo)> CreateACOOLYGasOrder(LifeGasData input, string orderNo) { 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 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 = appId, Mchid = _wxPayOptions.Mchid, Attach = order_guid, Description = description, OutTradeNo = outTradeNo, Amount = new Model_MiniPay_Amount { Total = Convert.ToInt32(100 * amount), Currency = "CNY" }, NotifyUrl = $"{_wxPayOptions.NotifyUrl}{LifePaymentConstant.WxRechargeNotifySectionUrl}", Payer = new Model_MiniPay_Payer { OpenId = openid } }; var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); string nonce = Guid.NewGuid().ToString(); var res = await _wxPayApi.PayTransactionsJsAPI(req); string package = "prepay_id=" + res.PrepayId; ModelPaymentMiniPay info = new ModelPaymentMiniPay(); if (res != null) { string paytext = BuildSignByPay(appId, timestamp, nonce, package); string paysign = _wxPayApi.GeneratePaySignByKey(paytext); info.Timestamp = timestamp.ToString(); info.NonceStr = nonce; info.Package = package; info.SignType = "RSA"; info.PaySign = paysign; info.TimeExpire = time_expire; } return info; } /// /// 构造签名串 /// /// 小程序的AppID /// 时间戳 /// 随机字符串 /// package值 /// 签名串 public string BuildSignByPay(string appId, long timestamp, string nonceStr, string package) { string format = $"{appId}\n{timestamp}\n{nonceStr}\n{package}\n"; return format; } /// /// 支付成功回调处理 /// /// /// /// public async Task LifePaySuccessHandler(string orderNo, string outOrderNo) { var order = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo).FirstOrDefaultAsync(); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "订单不存在"); if (order.PayStatus == LifePayStatusEnum.已支付) { return; } order.PayStatus = LifePayStatusEnum.已支付; order.PayTime = DateTime.Now; order.OutOrderNo = outOrderNo; try { var result = (Code: "Fail", RequestNo: "", ACOOLYOrderNo: ""); switch (order.LifePayOrderType) { case LifePayOrderTypeEnum.话费订单: result = await CreateACOOLYPhoneOrder(JsonConvert.DeserializeObject(order.OrderParamDetailJsonStr), order.OrderNo); break; case LifePayOrderTypeEnum.电费订单: result = await CreateACOOLYElectricOrder(JsonConvert.DeserializeObject(order.OrderParamDetailJsonStr), order.OrderNo); break; case LifePayOrderTypeEnum.燃气订单: result = await CreateACOOLYGasOrder(JsonConvert.DeserializeObject(order.OrderParamDetailJsonStr), order.OrderNo); break; default: break; } order.LifePayOrderStatus = LifePayOrderStatusEnum.待确认; //SetOrderStatus(order, result.Code); order.OutRequestNo = result.RequestNo.IsNullOrEmpty() ? null : result.RequestNo; order.ACOOLYOrderNo = result.ACOOLYOrderNo.IsNullOrEmpty() ? null : result.ACOOLYOrderNo; } catch (Exception ex) { _logger.LogError(ex, "处理生活缴费支付成功回调时异常"); order.LifePayOrderStatus = LifePayOrderStatusEnum.已失败; order.PayStatus = LifePayStatusEnum.待退款; } _logger.LogError("生活缴费订单状态:" + order.LifePayOrderStatus.ToString()); await _lifePayOrderRepository.UpdateAsync(order); } /// /// ACOOLYO订单通知处理 /// /// /// /// public async Task ACOOLYOrderNotifyHandler(string orderNo, string acoolyOrderNo, LifePayOrderStatusEnum status, ACOOLYStatusEnum acoolyStatus, decimal payAmount) { var order = await _lifePayOrderRepository.Where(x => x.OrderNo == orderNo).FirstOrDefaultAsync(); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "订单不存在"); if (order.LifePayOrderStatus == LifePayOrderStatusEnum.已完成) { return; } order.LifePayOrderStatus = status; order.ACOOLYStatus = acoolyStatus; order.PlatformDeductionAmount = payAmount; if (acoolyOrderNo.IsNotNullOrEmpty()) { order.ACOOLYOrderNo = acoolyOrderNo; } if (order.LifePayOrderStatus == LifePayOrderStatusEnum.已完成) { order.FinishTime = DateTime.Now; } if (order.LifePayOrderStatus == LifePayOrderStatusEnum.已失败 && order.PayStatus != LifePayStatusEnum.已退款) { order.PayStatus = LifePayStatusEnum.待退款; } await _lifePayOrderRepository.UpdateAsync(order); } /// /// 退款生活缴费订单 /// /// /// /// public async Task RefundLifePayOrder(RefundLifePayOrderInput input) { var order = await _lifePayOrderRepository.FirstOrDefaultAsync(x => x.Id == input.Id); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "订单不存在"); if (order.PayStatus == LifePayStatusEnum.已退款) { return; } if (order.LifePayOrderStatus != LifePayOrderStatusEnum.已失败 && order.PayStatus != LifePayStatusEnum.待退款 && order.LifePayOrderStatus != LifePayOrderStatusEnum.退款待审核) { throw new UserFriendlyException("当前订单状态无法退款"); } switch (order.LifePayType) { case LifePayTypeEnum.WxPay: var wxRefundResult = await WxPayDomesticRefunds(order.OrderNo, order.RefundApplyRemark, Convert.ToInt32(order.PayAmount * 100), Convert.ToInt32(order.PayAmount * 100)); if (wxRefundResult.Status == "SUCCESS") { order.PayStatus = LifePayStatusEnum.已退款; order.LifePayOrderStatus = LifePayOrderStatusEnum.已退款; } else if (wxRefundResult.Status == "PROCESSING") { order.PayStatus = LifePayStatusEnum.退款中; order.LifePayOrderStatus = LifePayOrderStatusEnum.退款中; } else { throw new UserFriendlyException("退款失败"); } break; case LifePayTypeEnum.AliPay: var aliRefundResult = await AliTradeRefund(new AlipayTradeRefundRequest() { OutTradeNo = order.OrderNo, RefundAmount = order.PayAmount.ToString() }); if (aliRefundResult.Code != AlipayResultCode.Success) { throw new UserFriendlyException("退款失败"); } order.PayStatus = LifePayStatusEnum.已退款; order.LifePayOrderStatus = LifePayOrderStatusEnum.已退款; break; default: throw new UserFriendlyException("退款失败"); } order.RefundCredentialsImgUrl = input.RefundCredentialsImgUrl; order.RefundCheckRemark = input.RefundCheckRemark; order.RefundTime = DateTime.Now; order.RefundCheckUserId = CurrentUser.Id; order.RefundPrice = order.PayAmount; await _lifePayOrderRepository.UpdateAsync(order); #region 记录日志 await PublishLifePayOrderHistoryEvent("退款", "退款", order.Id); #endregion } /// /// 用户发起生活缴费退款 /// /// /// /// 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.PayStatus == LifePayStatusEnum.已退款) { return; } if (order.LifePayOrderStatus != LifePayOrderStatusEnum.待确认 && order.LifePayOrderStatus != LifePayOrderStatusEnum.已失败 && order.PayStatus != LifePayStatusEnum.已支付) { throw new UserFriendlyException("当前订单状态无法申请退款"); } order.LifePayOrderStatus = LifePayOrderStatusEnum.退款待审核; order.RefundApplyRemark = input.RefundApplyRemark; order.RefundApplyTime = DateTime.Now; await _lifePayOrderRepository.UpdateAsync(order); } /// /// 微信退款 /// /// /// /// /// /// /// public async Task WxPayDomesticRefunds(string outTradeNo, string reason, int refund, int total, string currency = "CNY") { WxPayDomesticRefundsRequest req = new WxPayDomesticRefundsRequest { OutTradeNo = outTradeNo, OutRefundNo = CreateRefundOrderNo(), 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 AliTradeRefund(AlipayTradeRefundRequest input) { return await _aliPayApi.TradeRefund(input); } public async Task 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(input.ExtraProperties); if (!string.IsNullOrEmpty(extraProperties.Name)) { user.Name = extraProperties.Name; } } return Constant.SUCCESS; } /// /// 用户删除户号信息 /// /// /// public async Task 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; } /// /// 退款驳回 /// /// /// /// public async Task RejectRefundLifePayOrder(RefundLifePayOrderInput input) { var order = await _lifePayOrderRepository.FirstOrDefaultAsync(x => x.Id == input.Id); CheckExtensions.IfTrueThrowUserFriendlyException(order == null, "订单不存在"); if (order.PayStatus == LifePayStatusEnum.已退款) { return; } if ((order.LifePayOrderStatus == LifePayOrderStatusEnum.已失败 && order.PayStatus == LifePayStatusEnum.待退款) || order.LifePayOrderStatus == LifePayOrderStatusEnum.退款待审核 || order.LifePayOrderStatus == LifePayOrderStatusEnum.待确认) { order.LifePayOrderStatus = LifePayOrderStatusEnum.退款失败; order.RefundCheckRemark = input.RefundCheckRemark; order.RefundCheckUserId = CurrentUser.Id; 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(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 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 input) { CheckExtensions.IfTrueThrowUserFriendlyException(input.Where(r => r.Rate <= 0).Any(), "折扣不得小于等于0"); var baseRate = input.FirstOrDefault(r => r.RateType == LifePayRateTypeEnum.供应商折扣价)?.Rate; var listData = new List(); 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 input) { CheckExtensions.IfTrueThrowUserFriendlyException(input.Where(r => r.Rate < 0).Any(), "折扣不得小于0"); var listData = new List(); 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(); 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 私有 private string CreateOrderNo() { 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 / 100, 2, MidpointRounding.AwayFromZero); /// 1分钱支付 decimal payAmount = 0.01m; CheckExtensions.IfTrueThrowUserFriendlyException(payAmount < 0.01m, "支付金额错误"); return (payAmount, amount - payAmount, amount); } private void SetOrderStatus(LifePayOrder order, string code) { switch (code) { case ACOOLYConstant.Code.SUCCESS: order.LifePayOrderStatus = LifePayOrderStatusEnum.已完成; order.FinishTime = DateTime.Now; break; case ACOOLYConstant.Code.PROCESSING: order.LifePayOrderStatus = LifePayOrderStatusEnum.待确认; break; default: break; } } /// /// 记录相关的操作历史 /// /// /// private async Task PublishLifePayOrderHistoryEvent(string operateContent, string operateName, Guid relationId, int? tableType = TableType.LifePayOrder) { var recordEto = new RecordOperateHistoryEto { CreatorName = CurrentUser.Name, OperateContent = operateContent, OperateName = operateName, RelationId = relationId, TableType = tableType }; await _distributedEventBus.PublishAsync(recordEto, false); } /// /// 获取支付二维码 /// /// /// /// /// /// /// public async Task GetPayQRCode(LifePayTypeEnum payType, string outTradeNo, string description, decimal amount, string ip, string h5Type) { var codeUrl = string.Empty; switch (payType) { case LifePayTypeEnum.AliPay: codeUrl = await GetAliPayQRCode(outTradeNo, description, amount); break; case LifePayTypeEnum.WxPay: codeUrl = await GetWxPayQRCode(outTradeNo, description, amount); //native // codeUrl = await GetWxPayH5Url(outTradeNo, description, amount, ip, h5Type); //h5 break; default: throw new UserFriendlyException(string.Format(CustomeErrorMessage.NotImplementedWhenSometing, "获取支付二维码")); } return codeUrl; } /// /// 获取微信支付二维码 /// /// /// /// /// /// private async Task GetWxPayQRCode(string outTradeNo, string description, decimal amount) { CheckExtensions.IfTrueThrowUserFriendlyException(amount <= 0, CustomeErrorMessage.SometingMustSometing, "获取支付二维码时金额", "大于0"); var res = await _wxPayApi.PayTransactionsNative(new PayTransactionsNativeInput { Appid = _wxPayOptions.AppID, Mchid = _wxPayOptions.Mchid, Description = description, OutTradeNo = outTradeNo, Amount = new PayAmount { Total = Convert.ToInt32(100 * amount), }, NotifyUrl = $"{_wxPayOptions.NotifyUrl}{LifePaymentConstant.WxRechargeNotifySectionUrl}", }); if (res == null || res.CodeUrl.IsNullOrEmpty()) { _logger.LogError($"获取微信支付二维码异常:{(res == null ? "返回参数为空" : $"{res.Code} --{res.Message}")}"); throw new UserFriendlyException(string.Format(CustomeErrorMessage.SometingError, "获取支付二维码时")); } return res.CodeUrl; } /// /// 获取微信支付二维码 /// /// /// /// /// /// private async Task GetWxPayH5Url(string outTradeNo, string description, decimal amount, string ip, string h5Type) { CheckExtensions.IfTrueThrowUserFriendlyException(amount <= 0, CustomeErrorMessage.SometingMustSometing, "获取支付二维码时金额", "大于0"); var res = await _wxPayApi.PayTransactionsH5(new PayTransactionsNativeH5 { Appid = _wxPayOptions.AppID, Mchid = _wxPayOptions.Mchid, Description = description, OutTradeNo = outTradeNo, Amount = new PayAmount { Total = Convert.ToInt32(100 * amount), }, NotifyUrl = $"{_wxPayOptions.NotifyUrl}{LifePaymentConstant.WxRechargeNotifySectionUrl}", SceneInfo = new H5SceneInfo() { PayerClientIp = ip, H5Info = new H5Info() { Type = h5Type } } }); if (res == null || res.H5Url.IsNullOrEmpty()) { _logger.LogError($"获取微信支付Url异常:{(res == null ? "返回参数为空" : $"{res.Code} --{res.Message}")}"); throw new UserFriendlyException(string.Format(CustomeErrorMessage.SometingError, "获取支付Url时")); } return res.H5Url; } /// /// 获取支付宝二维码 /// /// /// /// /// /// private async Task GetAliPayQRCode(string outTradeNo, string description, decimal amount) { CheckExtensions.IfTrueThrowUserFriendlyException(amount < 0.01M, CustomeErrorMessage.SometingMustSometing, "获取支付二维码时金额", "大于0.01"); var res = await _aliPayApi.GetAliPayQRCode(new GetPayQrCodeInput { Subject = description, OutTradeNo = outTradeNo, TotalAmount = amount, }); if (res == null || res.QrCode.IsNullOrEmpty()) { _logger.LogError($"获取支付宝支付二维码异常:{(res == null ? "返回参数为空" : $"{res.Code} --{res.Msg}")}"); throw new UserFriendlyException(string.Format(CustomeErrorMessage.SometingError, "获取支付二维码时")); } return res.QrCode; } /// /// 构造待签名字符串 /// /// HTTP请求方法 /// API接口的相对路径 /// 时间戳(秒级) /// 随机字符串 /// 请求体的JSON字符串 /// 待签名字符串 public static string BuildSignByUniOrder(string method, string uri, long timestamp, string nonce, string body) { string message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{body}\n"; return message; } private async Task> GetLifePayOrderListFilter(QueryLifePayOrderListInput input) { var result = (from a in _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) .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.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, RefundTime = a.RefundTime, ChannelName = b.ChannlesName }); return result; } private IQueryable 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, }); } #endregion }