LifePayment/LifePayment.Application.Contracts/LifePay/ILifePayService.cs
@@ -1,18 +1,10 @@ using LifePayment.Application.Contracts; using LifePayment.Domain; using LifePayment.Domain.Shared; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using LifePayment.Domain.Shared; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; using Volo.Abp.EventBus.Distributed; using ZeroD.Util; using static LifePayment.Domain.Shared.LifePaymentConstant; namespace LifePayment.Application.Contracts; @@ -35,6 +27,18 @@ /// </summary> /// <returns></returns> Task<PhoneParValueResponse> GetPhoneParValue(); /// <summary> /// 获取燃气面值 /// </summary> /// <returns></returns> Task<GasParValueResponse> GetGasParValue(); /// <summary> /// 获取燃气支持商户 /// </summary> /// <returns></returns> Task<GasOrgTypeValueResponse> GetGasOrgType(); /// <summary> /// 支付成功回调处理 @@ -68,12 +72,48 @@ Task<CreateLifePayOrderOutput> CreateLifePayElectricOrder(CreateLifePayOrderInput<LifeElectricData> input); /// <summary> /// 创建生活缴费燃气订单 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<CreateLifePayOrderOutput> CreateLifePayGasOrder(CreateLifePayOrderInput<LifeGasData> input); /// <summary> /// 退款生活缴费订单 /// </summary> /// <param name="input"></param> /// <returns></returns> /// <exception cref="UserFriendlyException"></exception> Task RefundLifePayOrder(RefundLifePayOrderInput input); /// <summary> /// 用户发起生活缴费退款 /// </summary> /// <param name="input"></param> /// <returns></returns> Task RefundUserLifePayOrder(RefundUserLifePayOrderInput input); /// <summary> /// 用户修改户号信息 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<int> AddUpdateUserAccount(AddUpdateUserAccountInput input); /// <summary> /// 删除用户户号 /// </summary> /// <param name="id"></param> /// <returns></returns> Task<int> DeleteUserAccount(Guid id); Task RejectRefundLifePayOrder(RefundLifePayOrderInput input); Task CreateEditPayChannels(CreateEditPayChannelsInput input); Task SetLifePayChannelsStatus(Guid id, LifePayChannelsStatsEnum status); Task CreateEditLifePayRate(List<LifePayRateInput> input); /// <summary> /// 获取折扣 @@ -89,11 +129,26 @@ Task<PageOutput<UserLifePayOrderOutput>> GetUserLifePayOrderPage(QueryLifePayOrderListInput input); /// <summary> /// 获取我的订单详情 /// </summary> /// <param name="orderNo"></param> /// <returns></returns> Task<UserLifePayOrderOutput> GetUserLifePayOrderDetail(string orderNo); /// <summary> /// 获取用户分页数据 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<PageOutput<UserListOutput>> GetUserPage(PageInput input); /// <summary> /// 获取用户户号分页数据 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<PageOutput<UserAccountOutput>> GetAccountPage(QueryUserAccountListInput input); /// <summary> /// 获取订单分页数据 @@ -108,6 +163,43 @@ /// <param name="orderNo"></param> /// <returns></returns> Task<LifePayStatusEnum> GetPayStatusByOrderNo(string orderNo); /// <summary> /// 获取渠道分页 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<PageOutput<CreateEditPayChannelsInput>> GetLifePayChannlesPage(PageInput input); Task<CreateEditPayChannelsInput> GetLifePayChannlesDto(Guid id); Task<CreateEditPayChannelsInput> GetLifePayChannlesDtoByNum(string channlesNum); Task<UserLifePayOrderRefundOutput> GetUserLifePayOrderRefund(Guid id); /// <summary> /// 获取我的户号列表 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<PageOutput<UserAccountOutput>> GetUserAccountList(QueryUserAccountListInput input); /// <summary> /// 获取我的全部户号列表 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<List<UserAccountOutput>> GetUserAccountAllList(QueryUserAccountAllListInput input); /// <summary> /// 获取我的户号详情 /// </summary> /// <param name="id"></param> /// <returns></returns> Task<UserAccountOutput> GetUserAccountDetail(Guid id); Task<List<LifePayOrderListTemplate>> GetLifePayOrderPageExport(QueryLifePayOrderListInput input); /// <summary> /// 设置生活缴费支付类型 @@ -134,4 +226,6 @@ /// <returns></returns> /// <exception cref="UserFriendlyException"></exception> Task<string> GetPayQRCode(LifePayTypeEnum payType, string outTradeNo, string description, decimal amount, string ip, string h5Type); Task<bool> CheckChannelsStatus(string channlesId); } LifePayment/LifePayment.Application.Contracts/LifePay/LifePayInput.cs
@@ -1,18 +1,21 @@ using LifePayment.Domain.Shared; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; using ZeroD.Util; using static LifePayment.Domain.Shared.LifePaymentConstant; namespace LifePayment.Application.Contracts; public class CreateLifePayOrderInput<T> where T : class public class CreateLifePayOrderInput<T> : ChannelsBaseInput where T : class { public Guid UserId { get; set; } /// <summary> /// 渠道名称 /// </summary> public string ChannelId { get; set; } //public string CheckChannelId { get; set; } ///// <summary> ///// 生活缴费支付类型 @@ -42,6 +45,7 @@ /// 手机号。 /// </summary> [Required(ErrorMessage = "手机号是必填项。")] [RegularExpression(RegularExpression.PhoneNumberRegEx, ErrorMessage = "手机号格式不正确")] [JsonProperty("phone")] public string Phone { get; set; } @@ -77,7 +81,7 @@ /// 电费户号。 /// </summary> [Required(ErrorMessage = "电费户号是必填项。")] [StringLength(50, ErrorMessage = "电费户号长度不能超过50个字符。")] [RegularExpression(RegularExpression.ElectricAccountRegEx, ErrorMessage = "请输入13位电网户号")] public string ElectricAccount { get; set; } /// <summary> @@ -98,6 +102,42 @@ /// 客户身份证后6位,南网必传。 /// </summary> public string SixID { get; set; } } public class LifeGasData { /// <summary> /// 充值面额,单位为元。 /// </summary> [Required(ErrorMessage = "充值面额是必填项。")] public decimal ParValue { get; set; } /// <summary> /// 天然气公司类型,"zhong_ran"代表中燃燃气,"bei_jing"代表北京燃气。 /// </summary> [Required(ErrorMessage = "燃气类型是必填项。")] public string GasOrgType { get; set; } /// <summary> /// 燃气户号 /// </summary> [Required(ErrorMessage = "燃气户号是必填项。")] public string GasAccount { get; set; } /// <summary> /// 省份 /// </summary> [Required(ErrorMessage = "省份是必填项。")] [StringLength(20, ErrorMessage = "省份长度不能超过20个字符。")] public string Province { get; set; } /// <summary> /// 城市 /// </summary> //[Required(ErrorMessage = "城市是必填项。")] [StringLength(20, ErrorMessage = "城市长度不能超过20个字符。")] public string City { get; set; } } public class CreateLifePayOrderInput @@ -174,14 +214,34 @@ /// </summary> public string OrderParamDetailJsonStr { get; set; } /// <summary> /// 下单渠道 /// </summary> public Guid? ChannelId { get; set; } } public class QueryLifePayOrderListInput : PageInput //public class ChannelsBaseInput : PageInput //{ // public string CheckChannelId { get; set; } //} public class GetPayStatusByOrderNoInput : ChannelsBaseInput { public string OrderNo { get; set; } } public class QueryLifePayOrderListInput : ChannelsBaseInput { /// <summary> /// 订单类型 /// </summary> public LifePayOrderTypeEnum? LifePayOrderType { get; set; } /// <summary> /// 生活缴费支付类型 /// </summary> public LifePayTypeEnum? LifePayType { get; set; } /// <summary> /// 开始支付时间 @@ -217,6 +277,12 @@ /// 用户Id /// </summary> public Guid? UserId { get; set; } /// <summary> /// 搜索关键词 /// </summary> public string KeyWords { get; set; } } public class RefundLifePayOrderInput @@ -224,4 +290,103 @@ public Guid Id { get; set; } public string RefundCredentialsImgUrl { get; set; } public string RefundCheckRemark { get; set; } } public class RefundUserLifePayOrderInput : ChannelsBaseInput { public Guid Id { get; set; } /// <summary> /// 用户Id /// </summary> public Guid? UserId { get; set; } public string RefundApplyRemark { get; set; } } public class CreateEditPayChannelsInput { public Guid? Id { get; set; } public string ChannlesName { get; set; } public string ChannlesNum { get; set; } public decimal ChannlesRate { get; set; } public LifePaySwitchTypeEnum SwitchType { get; set; } public LifePayChannelsStatsEnum Status { get; set; } public LifePayChannlesTypeEnum ChannlesType { get; set; } } public class QueryUserAccountListInput : ChannelsBaseInput { /// <summary> /// 用户Id /// </summary> public Guid? UserId { get; set; } public LifePayOrderTypeEnum? LifePayOrderType { get; set; } } public class QueryUserAccountAllListInput : ChannelsBaseInput { /// <summary> /// 用户Id /// </summary> public Guid? UserId { get; set; } public LifePayOrderTypeEnum? LifePayOrderType { get; set; } } public class AddUpdateUserAccountInput : ChannelsBaseInput { public Guid? Id { get; set; } /// <summary> /// 用户编号 /// </summary> public Guid UserId { get; set; } /// <summary> /// 生活缴费类型 /// </summary> public LifePayOrderTypeEnum LifePayType { get; set; } /// <summary> /// 运营商 /// </summary> [Required(ErrorMessage = "运营商不能为空;")] public string Operators { get; set; } /// <summary> /// 手机号/户号 /// </summary> public string Content { get; set; } /// <summary> /// 省 /// </summary> public string Province { get; set; } /// <summary> /// 市 /// </summary> public string City { get; set; } /// <summary> /// 拓展字段(电费类型) /// </summary> public string ExtraProperties { get; set; } /// <summary> /// 备注 /// </summary> [StringLength(30, ErrorMessage = "备注信息仅支持填写30个字符。")] public string Remark { get; set; } = string.Empty; } LifePayment/LifePayment.Application.Contracts/LifePay/LifePayOutput.cs
@@ -1,10 +1,6 @@ using LifePayment.Domain.Shared; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ZeroD.Util; using ZeroD.Base.Web.Models; namespace LifePayment.Application.Contracts; @@ -13,6 +9,17 @@ public LifePayRateTypeEnum RateType { get; set; } public decimal Rate { get; set; } public Guid Id { get; set; } } public class LifePayRateInput { public LifePayRateTypeEnum RateType { get; set; } public decimal Rate { get; set; } public Guid? Id { get; set; } } public class UserListOutput @@ -44,6 +51,11 @@ /// 生活缴费支付类型 /// </summary> public LifePayTypeEnum? LifePayType { get; set; } /// <summary> /// 渠道名称 /// </summary> public string ChannelName { get; set; } /// <summary> /// 订单类型 @@ -104,6 +116,120 @@ /// 下单时间 /// </summary> public DateTime CreationTime { get; set; } /// <summary> /// 退款时间 /// </summary> public DateTime? RefundTime { get; set; } public string RefundApplyRemark { get; set; } public string RefundCheckRemark { get; set; } public string ACOOLYOrderNo { get; set; } } public class LifePayOrderListTemplate { [Name("序号")] public int SerialNumber { get; set; } [Name("手机号")] public string PhoneNumber { get; set; } public LifePayTypeEnum? LifePayType { get; set; } public LifePayOrderTypeEnum LifePayOrderType { get; set; } [Name("充值类型")] public string LifePayOrderTypeStr { get; set; } [Name("充值渠道")] public string ChannelName { get; set; } /// <summary> /// 下单时间 /// </summary> public DateTime CreationTime { get; set; } [Name("下单时间")] public string CreationTimeStr { get; set; } [Name("平台订单号")] public string OrderNo { get; set; } /// <summary> /// 充值金额 /// </summary> public decimal RechargeAmount { get; set; } [Name("充值金额")] public string RechargeAmountStr { get; set; } /// <summary> /// 优惠金额 /// </summary> public decimal DiscountAmount { get; set; } /// <summary> /// 实付金额 /// </summary> public decimal PayAmount { get; set; } [Name("实付金额")] public string PayAmountStr { get; set; } /// <summary> /// 支付时间 /// </summary> public DateTime? PayTime { get; set; } [Name("支付时间")] public string PayTimeStr { get; set; } [Name("支付渠道")] public string LifePayTypeStr { get; set; } [Name("外部订单号")] public string ACOOLYOrderNo { get; set; } /// <summary> /// 支付状态 /// </summary> public LifePayStatusEnum PayStatus { get; set; } [Name("支付状态")] public string PayStatusStr { get; set; } [Name("支付渠道流水号")] public string OutOrderNo { get; set; } [Name("退款申请")] public string RefundApplyRemark { get; set; } /// <summary> /// 订单状态 /// </summary> public LifePayOrderStatusEnum LifePayOrderStatus { get; set; } [Name("订单状态")] public string LifePayOrderStatusStr { get; set; } /// <summary> /// 完成时间 /// </summary> public DateTime? FinishTime { get; set; } [Name("完成时间")] public string FinishTimeStr { get; set; } } public class UserLifePayOrderOutput @@ -174,9 +300,100 @@ /// 退款时间 /// </summary> public DateTime? RefundTime { get; set; } /// <summary> /// 退款凭证 /// </summary> public string RefundCredentialsImgUrl { get; set; } public string RefundApplyRemark { get; set; } public string RefundCheckRemark { get; set; } /// <summary> /// 渠道流水号 /// </summary> public string ACOOLYOrderNo { get; set; } } public class CreateLifePayOrderOutput { public string OrderNo { get; set; } } public class UserLifePayOrderRefundOutput { /// <summary> /// 订单编号 /// </summary> public Guid Id { get; set; } /// <summary> /// 订单号 /// </summary> public string OrderNo { get; set; } /// <summary> /// 退款原因 /// </summary> public string RefundApplyRemark { get; set; } /// <summary> /// 后台填写的驳回原因 /// </summary> public string RefundCheckRemark { get; set; } /// <summary> /// 订单状态 /// </summary> public LifePayOrderStatusEnum LifePayOrderStatus { get; set; } } public class UserAccountOutput { public Guid Id { get; set; } /// <summary> /// 生活缴费类型 /// </summary> public LifePayOrderTypeEnum LifePayType { get; set; } /// <summary> /// 运营商 /// </summary> public string Operators { get; set; } /// <summary> /// 手机号/户号 /// </summary> public string Content { get; set; } /// <summary> /// 省 /// </summary> public string Province { get; set; } /// <summary> /// 市 /// </summary> public string City { get; set; } /// <summary> /// 拓展字段(电费类型) /// </summary> public string ExtraProperties { get; set; } /// <summary> /// 备注 /// </summary> public string Remark { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime CreationTime { get; set; } public bool IsDeleted { get; set; } } LifePayment/LifePayment.Application/LifePay/LifePayService.cs
@@ -26,6 +26,8 @@ using ZeroD.Util.Fadd; using static LifePayment.Domain.Shared.LifePaymentConstant; using static IdentityServer4.Models.IdentityResources; using Volo.Abp.Data; using Z.EntityFramework.Plus; namespace LifePayment.Application; @@ -37,6 +39,9 @@ private readonly IRepository<LifePayRate, Guid> _lifePayRateRepository; private readonly IRepository<LifePayOrder, Guid> _lifePayOrderRepository; private readonly IRepository<LifePayUser, Guid> _lifePayUserRepository; private readonly IRepository<LifePayChannles, Guid> _lifePayChannlesRep; private readonly IRepository<LifePayAccount, Guid> _lifePayAccount; private readonly IDataFilter dataFilter; private readonly IAliPayApi _aliPayApi; private readonly IWxPayApi _wxPayApi; @@ -52,7 +57,10 @@ IRepository<LifePayUser, Guid> lifePayUserRepository, IAliPayApi aliPayApi, IWxPayApi wxPayApi, IOptions<WxPayOption> wxPayOptions) IOptions<WxPayOption> wxPayOptions, IRepository<LifePayChannles, Guid> lifePayChannlesRep, IRepository<LifePayAccount, Guid> lifePayAccount, IDataFilter dataFilter) { _logger = logger; _aCOOLYManager = aCOOLYManager; @@ -63,6 +71,9 @@ _wxPayApi = wxPayApi; _wxPayOptions = wxPayOptions.Value; _distributedEventBus = distributedEventBus; _lifePayChannlesRep = lifePayChannlesRep; _lifePayAccount = lifePayAccount; this.dataFilter = dataFilter; } #region 查询 @@ -97,12 +108,31 @@ } /// <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(); } @@ -125,42 +155,82 @@ } /// <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> /// 获取订单分页数据 /// </summary> /// <param name="input"></param> /// <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 result = await (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.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) .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.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.Id 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 }).GetPageResult(input.PageModel); return result; } /// <summary> @@ -199,10 +269,45 @@ 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, RefundTime = x.RefundTime, ACOOLYOrderNo = x.ACOOLYOrderNo, }) .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 +322,184 @@ .FirstOrDefaultAsync(); } public async Task<PageOutput<CreateEditPayChannelsInput>> GetLifePayChannlesPage(PageInput input) { return await _lifePayChannlesRep.Select(x => new CreateEditPayChannelsInput { Id = x.Id, ChannlesRate = x.ChannlesRate, ChannlesName = x.ChannlesName, ChannlesNum = x.ChannlesNum, Status = x.Status, SwitchType = x.SwitchType, ChannlesType = x.ChannlesType, }) .GetPageResult(input.PageModel); } 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, 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, 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 _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, 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 操作 @@ -228,8 +511,14 @@ /// <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(), "未配置折扣"); @@ -249,6 +538,7 @@ PayAmount = amount.PayAmont, DiscountAmount = amount.DiscountAmount, RechargeAmount = amount.RechargeAmount, ChannelId = channle.Id }; await CreateLifePayOrder(orderInput); @@ -270,6 +560,10 @@ 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(), "未配置折扣"); @@ -288,6 +582,51 @@ PayAmount = amount.PayAmont, DiscountAmount = amount.DiscountAmount, RechargeAmount = amount.RechargeAmount, ChannelId = channle.Id }; 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 orderInput = new CreateLifePayOrderInput { OrderNo = 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.Id }; await CreateLifePayOrder(orderInput); @@ -363,6 +702,9 @@ case LifePayOrderTypeEnum.电费订单: desc += "电费"; break; case LifePayOrderTypeEnum.燃气订单: desc += "燃气"; break; default: break; } @@ -373,12 +715,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 +794,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, @@ -486,7 +858,7 @@ 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(); @@ -542,6 +914,9 @@ break; 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; @@ -613,14 +988,17 @@ return; } if (order.LifePayOrderStatus != LifePayOrderStatusEnum.已失败 && order.PayStatus != LifePayStatusEnum.待退款) if (order.LifePayOrderStatus != LifePayOrderStatusEnum.已失败 && order.PayStatus != LifePayStatusEnum.待退款 && order.LifePayOrderStatus != LifePayOrderStatusEnum.退款待审核) { throw new UserFriendlyException("当前订单状态无法退款"); } order.PayStatus = LifePayStatusEnum.已退款; order.LifePayOrderStatus = LifePayOrderStatusEnum.已退款; order.RefundCredentialsImgUrl = input.RefundCredentialsImgUrl; order.RefundCheckRemark = input.RefundCheckRemark; order.RefundTime = DateTime.Now; order.RefundCheckUserId = CurrentUser.Id; await _lifePayOrderRepository.UpdateAsync(order); @@ -631,6 +1009,227 @@ #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.PayStatus == LifePayStatusEnum.已退款) { return; } if (order.LifePayOrderStatus != LifePayOrderStatusEnum.待确认 && order.LifePayOrderStatus != LifePayOrderStatusEnum.已失败 && order.PayStatus != LifePayStatusEnum.已支付) { throw new UserFriendlyException("当前订单状态无法申请退款"); } order.LifePayOrderStatus = LifePayOrderStatusEnum.退款待审核; order.RefundApplyRemark = input.RefundApplyRemark; order.RefundTime = DateTime.Now; await _lifePayOrderRepository.UpdateAsync(order); } public async Task<int> AddUpdateUserAccount(AddUpdateUserAccountInput input) { 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); } 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.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.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.供应商折扣价)?.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); } } #endregion @@ -643,7 +1242,12 @@ private (decimal PayAmont, decimal DiscountAmount, decimal RechargeAmount) CalculateAmount(decimal amount, decimal rate) { var payAmount = decimal.Round(amount * rate, 2, MidpointRounding.AwayFromZero); /// 正常支付 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); @@ -697,9 +1301,6 @@ { var codeUrl = string.Empty; switch (payType) { case LifePayTypeEnum.AliPay: codeUrl = await GetAliPayQRCode(outTradeNo, description, amount); @@ -834,5 +1435,47 @@ } private async Task<IQueryable<LifePayOrderListOutput>> 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.Id 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; } #endregion } LifePayment/LifePayment.Domain.Shared/ACOOLY/ACOOLYConstant.cs
@@ -1,11 +1,4 @@ using Nest; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LifePayment.Domain.Shared; namespace LifePayment.Domain.Shared; public static class ACOOLYConstant { @@ -24,6 +17,10 @@ /// 提交燃气订单 /// </summary> public const string ConfirmGasOrder = "confirmGasOrder"; /// <summary> /// 查询燃气支持商户 /// </summary> public const string QueryGasOrgType = "queryGasOrgType"; /// <summary> /// 获取电费面值 LifePayment/LifePayment.Domain.Shared/ACOOLY/ACOOLYInput.cs
@@ -1,10 +1,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; using ZeroD.Util; namespace LifePayment.Domain.Shared; @@ -85,6 +82,21 @@ [JsonProperty("gasOrgType")] public string GasOrgType { get; set; } } public class GasOrgTypeRequestInput : ACOOLYRequestBaseInput { /// <summary> /// 外部商户订单号 /// </summary> [JsonProperty("outOrderNo")] public string OutOrderNo { get; set; } /// <summary> /// 平台订单号 /// </summary> [JsonProperty("busiOrderNo")] public string BusiOrderNo { get; set; } } /// <summary> @@ -231,8 +243,11 @@ [JsonProperty("name")] public string Name { get; set; } } public class SetLifePayOrderPayTypeInput public class ChannelsBaseInput : PageInput { public string CheckChannelId { get; set; } } public class SetLifePayOrderPayTypeInput : ChannelsBaseInput { [Required(ErrorMessage = "订单号不可为空")] public string OrderNo { get; set; } @@ -252,9 +267,10 @@ /// </summary> public string Attach { get; set; } } public class GetPayOrderForJsAPIInput public class GetPayOrderForJsAPIInput : ChannelsBaseInput { [Required(ErrorMessage = "订单号不可为空")] public string OrderNo { get; set; } @@ -272,4 +288,11 @@ /// </summary> public string Attach { get; set; } /// <summary> /// 支付应用的appId /// </summary> public string PayAppId { get; set; } //public string CheckChannelId { get; set; } } LifePayment/LifePayment.Domain.Shared/ACOOLY/ACOOLYOption.cs
@@ -1,10 +1,4 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LifePayment.Domain.Shared; namespace LifePayment.Domain.Shared; public class ACOOLYOption { LifePayment/LifePayment.Domain.Shared/ACOOLY/ACOOLYOutput.cs
@@ -1,10 +1,5 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LifePayment.Domain.Shared; @@ -136,10 +131,31 @@ /// 天然气公司类型 /// </summary> [JsonProperty("gasParValue")] public GasParValueOutput GasParValue { get; set; } public List<GasParValueOutput> GasParValue { get; set; } } public class GasOrgTypeValueResponse : ACOOLYRequestBaseResponse { /// <summary> /// 天然气公司类型 /// </summary> [JsonProperty("gasSupportMerchantInfos")] public List<GasSupportMerchantInfos> GasSupportMerchantInfos { get; set; } } public class GasSupportMerchantInfos { /// <summary> /// 燃气支持商户编码 /// </summary> public string gasOrgTypeCode { get; set; } /// <summary> /// 燃气支持商户名称 /// </summary> public string gasOrgTypeName { get; set; } } /// <summary> /// 燃气面值数据 /// </summary> LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs
@@ -1,51 +1,95 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel; namespace LifePayment.Domain.Shared; public enum LifePayTypeEnum { [Description("微信支付")] WxPay = 10, [Description("支付宝支付")] AliPay = 20 } public enum LifePayOrderTypeEnum { [Description("话费订单")] 话费订单 = 10, [Description("电费订单")] 电费订单 = 20, [Description("燃气订单")] 燃气订单 = 30, } public enum LifePayStatusEnum { [Description("未支付")] 未支付 = 10, [Description("已支付")] 已支付 = 20, [Description("待退款")] 待退款 = 30, 已退款 = 40 [Description("已退款")] 已退款 = 40, } public enum LifePayOrderStatusEnum { [Description("待确认")] 待确认 = 10, [Description("已失败")] 已失败 = 20, 已完成 = 30 [Description("支付宝支付")] 已完成 = 30, [Description("退款待审核")] 退款待审核 = 40, [Description("已退款")] 已退款 = 50, [Description("退款失败")] 退款失败 = 60, } public enum LifePayRateTypeEnum { 默认话费折扣=10, 默认电费折扣=20 默认电费折扣=20, 默认燃气折扣=30, 供应商折扣价=40, } public enum LifePaySwitchTypeEnum { H5 = 10, 微信小程序 = 20, 微信公众号 = 30, } public enum LifePayChannelsStatsEnum { 启用 = 10, 禁用 = 20, } public enum LifePayChannlesTypeEnum { 内部渠道 = 10, 外部渠道 = 20, } LifePayment/LifePayment.Domain.Shared/LifePaymentConstant.cs
@@ -725,6 +725,8 @@ public const int LgGigWorkerSignFreeSetting = 151; public const int LifePayOrder = 200; public const int LifePayChannles = 210; } public static class LogsSpecies @@ -1022,6 +1024,7 @@ /// </summary> public const string PhoneNumberRegEx = @"^1[3-9]\d{9}$"; /// <summary> /// 手机号码+座机正则表达式 /// </summary> @@ -1051,6 +1054,11 @@ /// 用户账号正则表达式 /// </summary> public const string UserNameEx = @"^[A-Za-z0-9]{8,13}$"; /// <summary> /// 电费户号正则表达式 /// </summary> public const string ElectricAccountRegEx = @"^.{13}$"; } public static class ResponseCode LifePayment/LifePayment.Domain/ACOOLY/ACOOLYClient.cs
@@ -1,24 +1,14 @@ using LifePayment.Application.Contracts; using LifePayment.Domain.Shared; using LifePayment.Domain.Shared; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Reflection; using System.Security.Cryptography; using System.Security.Policy; using System.Text; using System.Threading.Tasks; using System.Web; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Services; using ZeroD.Util; using ZeroD.Util.Fadd; namespace LifePayment.Domain { LifePayment/LifePayment.Domain/ACOOLY/ACOOLYManager.cs
@@ -1,17 +1,7 @@ using LifePayment.Application; using LifePayment.Application.Contracts; using LifePayment.Domain.Shared; using Microsoft.AspNetCore.Components.Forms; using LifePayment.Domain.Shared; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Volo.Abp.Domain.Services; using Volo.Abp.Users; using ZeroD.Util.Fadd; namespace LifePayment.Domain; @@ -39,6 +29,12 @@ return await PostAsync<GasParValueRequestInput, GasParValueResponse>(input); } public async Task<GasOrgTypeValueResponse> GasOrgType(GasOrgTypeRequestInput input) { SetBaseInfo(input, ACOOLYConstant.Sevice.QueryGasOrgType); return await PostAsync<GasOrgTypeRequestInput, GasOrgTypeValueResponse>(input); } /// <summary> /// 提交燃气订单 /// </summary> LifePayment/LifePayment.Domain/ACOOLY/IACOOLYManager.cs
@@ -1,10 +1,5 @@ using LifePayment.Domain.Shared; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Volo.Abp.Domain.Services; namespace LifePayment.Domain; @@ -21,6 +16,13 @@ Task<GasParValueResponse> GasParValue(GasParValueRequestInput input); /// <summary> /// 获取燃气支持商户 /// </summary> /// <param name="input"></param> /// <returns></returns> Task<GasOrgTypeValueResponse> GasOrgType(GasOrgTypeRequestInput input); /// <summary> /// 提交燃气订单 /// </summary> /// <param name="input"></param> LifePayment/LifePayment.Domain/LifePay/LifePayAccount.cs
New file @@ -0,0 +1,53 @@ using LifePayment.Domain.Shared; using System; using Volo.Abp; using Volo.Abp.Domain.Entities.Auditing; namespace LifePayment.Domain.Models { public partial class LifePayAccount : FullAuditedEntity<Guid>, IDataUserFilter { public LifePayAccount() { } /// <summary> /// 用户编号 /// </summary> public Guid UserId { get; set; } /// <summary> /// 生活缴费类型 /// </summary> public LifePayOrderTypeEnum LifePayType { get; set; } /// <summary> /// 运营商 /// </summary> public string Operators { get; set; } /// <summary> /// 手机号/户号 /// </summary> public string Content { get; set; } /// <summary> /// 省 /// </summary> public string Province { get; set; } /// <summary> /// 市 /// </summary> public string City { get; set; } /// <summary> /// 拓展字段(电费类型) /// </summary> public string ExtraProperties { get; set; } /// <summary> /// 备注 /// </summary> public string Remark { get; set; } } } LifePayment/LifePayment.Domain/LifePay/LifePayChannles.cs
New file @@ -0,0 +1,25 @@ using LifePayment.Domain.Shared; using System; using Volo.Abp; using Volo.Abp.Domain.Entities.Auditing; namespace LifePayment.Domain; public partial class LifePayChannles : FullAuditedEntity<Guid>, IDataUserFilter { public LifePayChannles() { } public string ChannlesName { get; set; } public string ChannlesNum { get; set; } public decimal ChannlesRate { get; set; } public LifePaySwitchTypeEnum SwitchType { get; set; } public LifePayChannelsStatsEnum Status { get; set; } public LifePayChannlesTypeEnum ChannlesType { get; set; } } LifePayment/LifePayment.Domain/LifePay/LifePayOrder.cs
@@ -1,5 +1,4 @@ using LifePayment.Domain.Shared; using Org.BouncyCastle.Bcpg.OpenPgp; using System; using Volo.Abp; using Volo.Abp.Domain.Entities.Auditing; @@ -65,6 +64,11 @@ public string OutOrderNo { get; set; } /// <summary> /// 渠道流水号 /// </summary> public string ACOOLYOrderNo { get; set; } /// <summary> /// 订单状态 /// </summary> public LifePayOrderStatusEnum LifePayOrderStatus { get; set; } @@ -90,13 +94,16 @@ public string OutRequestNo { get; set; } /// <summary> /// ACOOLY订单号 /// </summary> public string ACOOLYOrderNo { get; set; } /// <summary> /// 退款时间 /// </summary> public DateTime? RefundTime { get; set; } public string RefundApplyRemark { get; set; } public string RefundCheckRemark { get; set; } public Guid? RefundCheckUserId { get; set; } public Guid? ChannelId { get; set; } } } LifePayment/LifePayment.EntityFrameworkCore/LifePaymentServicesDbContext.cs
@@ -22,6 +22,12 @@ public virtual DbSet<LifePayRate> LifePayRate { get; set; } public virtual DbSet<LifePayChannles> LifePayChannles { get; set; } public virtual DbSet<LifePayAccount> LifePayAccount { get; set; } [UnitOfWork] protected override void OnModelCreating(ModelBuilder builder) { LifePayment/LifePayment.Host/LifePaymentServices.Application.Contracts.xml
@@ -22,6 +22,18 @@ </summary> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetGasParValue"> <summary> 获取燃气面值 </summary> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetGasOrgType"> <summary> 获取燃气支持商户 </summary> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.LifePaySuccessHandler(System.String,System.String)"> <summary> 支付成功回调处理 @@ -53,6 +65,13 @@ <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.CreateLifePayGasOrder(LifePayment.Application.Contracts.CreateLifePayOrderInput{LifePayment.Application.Contracts.LifeGasData})"> <summary> 创建生活缴费燃气订单 </summary> <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.RefundLifePayOrder(LifePayment.Application.Contracts.RefundLifePayOrderInput)"> <summary> 退款生活缴费订单 @@ -60,6 +79,27 @@ <param name="input"></param> <returns></returns> <exception cref="T:Volo.Abp.UserFriendlyException"></exception> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.RefundUserLifePayOrder(LifePayment.Application.Contracts.RefundUserLifePayOrderInput)"> <summary> 用户发起生活缴费退款 </summary> <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.AddUpdateUserAccount(LifePayment.Application.Contracts.AddUpdateUserAccountInput)"> <summary> 用户修改户号信息 </summary> <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.DeleteUserAccount(System.Guid)"> <summary> 删除用户户号 </summary> <param name="id"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetRate"> <summary> @@ -74,9 +114,23 @@ <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetUserLifePayOrderDetail(System.String)"> <summary> 获取我的订单详情 </summary> <param name="orderNo"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetUserPage(ZeroD.Util.PageInput)"> <summary> 获取用户分页数据 </summary> <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetAccountPage(LifePayment.Application.Contracts.QueryUserAccountListInput)"> <summary> 获取用户户号分页数据 </summary> <param name="input"></param> <returns></returns> @@ -93,6 +147,34 @@ 根据订单号获取支付状态 </summary> <param name="orderNo"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetLifePayChannlesPage(ZeroD.Util.PageInput)"> <summary> 获取渠道分页 </summary> <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetUserAccountList(LifePayment.Application.Contracts.QueryUserAccountListInput)"> <summary> 获取我的户号列表 </summary> <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetUserAccountAllList(LifePayment.Application.Contracts.QueryUserAccountAllListInput)"> <summary> 获取我的全部户号列表 </summary> <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.GetUserAccountDetail(System.Guid)"> <summary> 获取我的户号详情 </summary> <param name="id"></param> <returns></returns> </member> <member name="M:LifePayment.Application.Contracts.ILifePayService.SetLifePayOrderPayType(LifePayment.Domain.Shared.SetLifePayOrderPayTypeInput,System.String)"> @@ -120,6 +202,11 @@ <param name="amount"></param> <returns></returns> <exception cref="T:Volo.Abp.UserFriendlyException"></exception> </member> <member name="P:LifePayment.Application.Contracts.CreateLifePayOrderInput`1.ChannelId"> <summary> 渠道名称 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePhoneData.IspCode"> <summary> @@ -174,6 +261,31 @@ <member name="P:LifePayment.Application.Contracts.LifeElectricData.SixID"> <summary> 客户身份证后6位,南网必传。 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifeGasData.ParValue"> <summary> 充值面额,单位为元。 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifeGasData.GasOrgType"> <summary> 天然气公司类型,"zhong_ran"代表中燃燃气,"bei_jing"代表北京燃气。 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifeGasData.GasAccount"> <summary> 燃气户号 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifeGasData.Province"> <summary> 省份 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifeGasData.City"> <summary> 城市 </summary> </member> <member name="P:LifePayment.Application.Contracts.CreateLifePayOrderInput.PhoneNumber"> @@ -241,9 +353,19 @@ 订单参数详情 </summary> </member> <member name="P:LifePayment.Application.Contracts.CreateLifePayOrderInput.ChannelId"> <summary> 下单渠道 </summary> </member> <member name="P:LifePayment.Application.Contracts.QueryLifePayOrderListInput.LifePayOrderType"> <summary> 订单类型 </summary> </member> <member name="P:LifePayment.Application.Contracts.QueryLifePayOrderListInput.LifePayType"> <summary> 生活缴费支付类型 </summary> </member> <member name="P:LifePayment.Application.Contracts.QueryLifePayOrderListInput.BeginPayTime"> @@ -281,6 +403,66 @@ 用户Id </summary> </member> <member name="P:LifePayment.Application.Contracts.QueryLifePayOrderListInput.KeyWords"> <summary> 搜索关键词 </summary> </member> <member name="P:LifePayment.Application.Contracts.RefundUserLifePayOrderInput.UserId"> <summary> 用户Id </summary> </member> <member name="P:LifePayment.Application.Contracts.QueryUserAccountListInput.UserId"> <summary> 用户Id </summary> </member> <member name="P:LifePayment.Application.Contracts.QueryUserAccountAllListInput.UserId"> <summary> 用户Id </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.UserId"> <summary> 用户编号 </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.LifePayType"> <summary> 生活缴费类型 </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.Operators"> <summary> 运营商 </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.Content"> <summary> 手机号/户号 </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.Province"> <summary> 省 </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.City"> <summary> 市 </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.ExtraProperties"> <summary> 拓展字段(电费类型) </summary> </member> <member name="P:LifePayment.Application.Contracts.AddUpdateUserAccountInput.Remark"> <summary> 备注 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserListOutput.PhoneNumber"> <summary> 用户手机号 @@ -294,6 +476,11 @@ <member name="P:LifePayment.Application.Contracts.LifePayOrderListOutput.LifePayType"> <summary> 生活缴费支付类型 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListOutput.ChannelName"> <summary> 渠道名称 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListOutput.LifePayOrderType"> @@ -354,6 +541,51 @@ <member name="P:LifePayment.Application.Contracts.LifePayOrderListOutput.CreationTime"> <summary> 下单时间 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListOutput.RefundTime"> <summary> 退款时间 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.CreationTime"> <summary> 下单时间 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.RechargeAmount"> <summary> 充值金额 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.DiscountAmount"> <summary> 优惠金额 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.PayAmount"> <summary> 实付金额 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.PayTime"> <summary> 支付时间 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.PayStatus"> <summary> 支付状态 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.LifePayOrderStatus"> <summary> 订单状态 </summary> </member> <member name="P:LifePayment.Application.Contracts.LifePayOrderListTemplate.FinishTime"> <summary> 完成时间 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderOutput.LifePayType"> @@ -421,6 +653,81 @@ 退款时间 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderOutput.RefundCredentialsImgUrl"> <summary> 退款凭证 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderOutput.ACOOLYOrderNo"> <summary> 渠道流水号 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderRefundOutput.Id"> <summary> 订单编号 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderRefundOutput.OrderNo"> <summary> 订单号 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderRefundOutput.RefundApplyRemark"> <summary> 退款原因 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderRefundOutput.RefundCheckRemark"> <summary> 后台填写的驳回原因 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserLifePayOrderRefundOutput.LifePayOrderStatus"> <summary> 订单状态 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.LifePayType"> <summary> 生活缴费类型 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.Operators"> <summary> 运营商 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.Content"> <summary> 手机号/户号 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.Province"> <summary> 省 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.City"> <summary> 市 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.ExtraProperties"> <summary> 拓展字段(电费类型) </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.Remark"> <summary> 备注 </summary> </member> <member name="P:LifePayment.Application.Contracts.UserAccountOutput.CreationTime"> <summary> 创建时间 </summary> </member> <member name="P:LifePayment.Application.Contracts.RecordOperateHistoryEto.RelationId"> <summary> 关联关系ID