zhengyuxuan
2025-03-28 83971e864fbee9e1a12d25239fbf005760ee983f
fix:支付查询
14个文件已修改
1个文件已添加
416 ■■■■■ 已修改文件
LifePayment/LifePayment.Application.Contracts/LifePay/ILifePayOrderService.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application.Contracts/LifePay/LifePayInput.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application/LifePay/LifePayOrderService.cs 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application/LifePay/LifePayService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain.Shared/Ali/GetPayQrCodeInput.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain/Ali/AliPayApi.cs 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain/Ali/AlipayApiConstant.cs 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain/LifePay/LifePayExpensesReceipts.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Domain/LifePay/LifePayRechargeReceipts.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.EntityFrameworkCore/LifePaymentServicesDbContext.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Host/LifePaymentService.HttpApi.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Host/LifePaymentServices.Application.Contracts.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.HttpApi/LifePay/AliPayNotifyController.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.HttpApi/LifePay/WxPayNotifyController.cs 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LifePayment/LifePayment.Application.Contracts/LifePay/ILifePayOrderService.cs
@@ -12,6 +12,7 @@
{
    Task<LifePayRechargeReceiptsPageOutput<LifePayRechargeReceiptsListOutput>> GetLifePayRechargeReceiptsPage(LifePayRechargeReceiptsPageInput input);
    Task AddUpdatePayRechargeReceipts(AddUpdatePayRechargeReceiptsInput input);
    Task AddLifePayExpensesReceipts(AddLifePayExpensesReceiptsInput input);
}
LifePayment/LifePayment.Application.Contracts/LifePay/LifePayInput.cs
@@ -643,4 +643,31 @@
    public decimal PayAmount { get; set; }
    public LifePayTypeEnum LifePayType { get; set; }
}
public class AddLifePayExpensesReceiptsInput
{
    /// <summary>
    /// 平台订单号
    /// </summary>
    public string OrderNo { get; set; }
    /// <summary>
    /// 渠道流水号
    /// </summary>
    public string OutOrderNo { get; set; }
    /// <summary>
    /// 支付渠道
    /// </summary>
    public LifePayTypeEnum LifePayType { get; set; }
    /// <summary>
    /// 收支类型
    /// </summary>
    public ExpensesReceiptsTypeEnum ExpensesReceiptsType { get; set; }
    /// <summary>
    /// 交易金额
    /// </summary>
    public decimal Amount { get; set; }
}
LifePayment/LifePayment.Application/LifePay/LifePayOrderService.cs
@@ -11,17 +11,27 @@
using Volo.Abp.Domain.Repositories;
using Microsoft.EntityFrameworkCore;
using ZeroD.Util;
using LifePayment.Domain;
namespace LifePayment.Application.LifePay
{
    public class LifePayOrderService : ApplicationService, ILifePayOrderService
    {
        private readonly IRepository<LifePayRechargeReceipts, Guid> _lifePayRechargeReceiptsRepository;
        private readonly IRepository<LifePayExpensesReceipts, Guid> _lifePayExpensesReceiptsRepository;
        private readonly IAliPayApi _aliPayApi;
        private readonly IWxPayApi _wxPayApi;
        public LifePayOrderService(
                              IRepository<LifePayRechargeReceipts, Guid> lifePayRechargeReceiptsRepository)
                              IRepository<LifePayRechargeReceipts, Guid> lifePayRechargeReceiptsRepository,
                              IRepository<LifePayExpensesReceipts, Guid> lifePayExpensesReceiptsRepository,
                              IAliPayApi aliPayApi,
                              IWxPayApi wxPayApi)
        {
            _lifePayRechargeReceiptsRepository = lifePayRechargeReceiptsRepository;
            _lifePayExpensesReceiptsRepository = lifePayExpensesReceiptsRepository;
            _aliPayApi = aliPayApi;
            _wxPayApi = wxPayApi;
        }
        /// <summary>
@@ -53,11 +63,7 @@
            return result;
        }
        //public async Task<decimal> GetTotalLifePayRechargeReceipts()
        //{
        //    var result = await _lifePayRechargeReceiptsRepository.Where(x => x.IsDeleted == false).SumAsync(x => x.RechargeAmount);
        //    return result;
        //}
        /// <summary>
        /// 编辑充值流水
@@ -92,5 +98,54 @@
                await _lifePayRechargeReceiptsRepository.InsertAsync(payRechargeReceipts);
            }
        }
        /// <summary>
        /// 插入收支流水
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task AddLifePayExpensesReceipts(AddLifePayExpensesReceiptsInput input)
        {
            var repeat = await _lifePayExpensesReceiptsRepository.Where(x => x.ExpensesReceiptsType == input.ExpensesReceiptsType
            && x.OrderNo == input.OrderNo).FirstOrDefaultAsync();
            if (repeat == null)
            {
                var data = new LifePayExpensesReceipts()
                {
                    Id = Guid.NewGuid(),
                    OrderNo = input.OrderNo,
                    OutOrderNo = input.OutOrderNo,
                    LifePayType = input.LifePayType,
                    ExpensesReceiptsType = input.ExpensesReceiptsType,
                    Amount = input.Amount
                };
                switch (input.LifePayType)
                {
                    case LifePayTypeEnum.AliPay:
                        if (input.ExpensesReceiptsType == ExpensesReceiptsTypeEnum.Expenses)
                        {
                            var query = await _aliPayApi.OrderInQuiry(new OrderInQuiryInput() { OutTradeNo = input.OrderNo });
                            if (query.Code == AlipayResultCode.Success && query.TradeStatus == AlipayStatus.TRADESUCCESS)
                            {
                                await _lifePayExpensesReceiptsRepository.InsertAsync(data);
                            }
                        }
                        else
                        {
                            var query = await _aliPayApi.QueryAlipayTradeRefund(new OrderInQuiryInput() { OutTradeNo = input.OrderNo });
                            if (query.Code == AlipayResultCode.Success && query.RefundStatus == AlipayRefundStatus.Success)
                            {
                                await _lifePayExpensesReceiptsRepository.InsertAsync(data);
                            }
                        }
                        break;
                    case LifePayTypeEnum.WxPay: break;
                    default: break;
                }
            }
        }
    }
}
LifePayment/LifePayment.Application/LifePay/LifePayService.cs
@@ -1418,7 +1418,7 @@
                break;
            case LifePayTypeEnum.AliPay:
                var aliRefundResult = await AliTradeRefund(new AlipayTradeRefundRequest() { OutTradeNo = order.OrderNo, RefundAmount = input.RefundPrice.ToString() });
                var aliRefundResult = await AliTradeRefund(new AlipayTradeRefundRequest() { OutTradeNo = order.OrderNo, OutRefundNo = outRefundNo, RefundAmount = input.RefundPrice.ToString() });
                if (aliRefundResult.Code != AlipayResultCode.Success)
                {
                    throw new UserFriendlyException("退款失败:" + aliRefundResult.SubMsg);
LifePayment/LifePayment.Domain.Shared/Ali/GetPayQrCodeInput.cs
@@ -33,6 +33,14 @@
        /// </summary>
        public string OutTradeNo { get; set; }
        /// <summary>
        /// 退款金额
        /// </summary>
        public string RefundAmount { get; set; }
        /// <summary>
        /// 退款订单号
        /// </summary>
        public string OutRefundNo { get; set; }
    }
}
LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs
@@ -11,6 +11,8 @@
    AliPay = 20
}
public enum LifePayOrderTypeEnum
{
    [Description("话费订单")]
@@ -185,4 +187,14 @@
    [Description("部分退款")]
    部分退款 = 20
}
}
public enum ExpensesReceiptsTypeEnum
{
    [Description("收入")]
    Expenses = 10,
    [Description("支出")]
    Receipts = 20,
}
LifePayment/LifePayment.Domain/Ali/AliPayApi.cs
@@ -5,7 +5,11 @@
using LifePayment.Domain.Shared;
using Microsoft.Extensions.Options;
using Nest;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Tea;
namespace LifePayment.Domain
{
@@ -13,10 +17,12 @@
    {
        private readonly Config _options;
        protected Alipay.EasySDK.Kernel.Client _kernel;
        public AliPayApi(
               IOptionsMonitor<Config> optionsMonitor)
               IOptionsMonitor<Config> optionsMonitor, Client kernel)
        {
            _options = optionsMonitor.CurrentValue;
            _kernel = kernel;
        }
        public async Task<AlipayTradePrecreateResponse> GetAliPayQRCode(GetPayQrCodeInput input)
@@ -40,6 +46,7 @@
            return response;
        }
        /// <summary>
        /// 查询支付宝退款订单信息
        /// </summary>
@@ -53,9 +60,139 @@
        public async Task<AlipayTradeRefundResponse> TradeRefund(AlipayTradeRefundRequest input)
        {
            AlipayTradeRefundResponse response = await Factory.Payment.Common().RefundAsync(input.OutTradeNo,input.RefundAmount);
            AlipayTradeRefundResponse response = await TradeRefund(input.OutTradeNo,input.OutRefundNo, input.RefundAmount);
            return response;
        }
        private async Task<AlipayTradeRefundResponse> TradeRefund(string outTradeNo, string outRefundNo, string refundAmount)
        {
            Dictionary<string, object> runtime_ = new Dictionary<string, object>
        {
            {
                "ignoreSSL",
                _kernel.GetConfig("ignoreSSL")
            },
            {
                "httpProxy",
                _kernel.GetConfig("httpProxy")
            },
            { "connectTimeout", 15000 },
            { "readTimeout", 15000 },
            {
                "retry",
                new Dictionary<string, int?> { { "maxAttempts", 0 } }
            }
        };
            TeaRequest _lastRequest = null;
            Exception innerException = null;
            long _now = DateTime.Now.Millisecond;
            int _retryTimes = 0;
            while (TeaCore.AllowRetry((IDictionary)runtime_["retry"], _retryTimes, _now))
            {
                if (_retryTimes > 0)
                {
                    int backoffTime = TeaCore.GetBackoffTime((IDictionary)runtime_["backoff"], _retryTimes);
                    if (backoffTime > 0)
                    {
                        TeaCore.Sleep(backoffTime);
                    }
                }
                _retryTimes++;
                try
                {
                    TeaRequest teaRequest = new TeaRequest();
                    Dictionary<string, string> dictionary = new Dictionary<string, string>
                {
                    { "method", "alipay.trade.refund" },
                    {
                        "app_id",
                        _kernel.GetConfig("appId")
                    },
                    {
                        "timestamp",
                        _kernel.GetTimestamp()
                    },
                    { "format", "json" },
                    { "version", "1.0" },
                    {
                        "alipay_sdk",
                        _kernel.GetSdkVersion()
                    },
                    { "charset", "UTF-8" },
                    {
                        "sign_type",
                        _kernel.GetConfig("signType")
                    },
                    {
                        "app_cert_sn",
                        _kernel.GetMerchantCertSN()
                    },
                    {
                        "alipay_root_cert_sn",
                        _kernel.GetAlipayRootCertSN()
                    }
                };
                    Dictionary<string, object> bizParams = new Dictionary<string, object>
                {
                    { "out_trade_no", outTradeNo },
                    { "out_request_no", outRefundNo },
                    { "refund_amount", refundAmount }
                };
                    Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
                    teaRequest.Protocol = _kernel.GetConfig("protocol");
                    teaRequest.Method = "POST";
                    teaRequest.Pathname = "/gateway.do";
                    teaRequest.Headers = new Dictionary<string, string>
                {
                    {
                        "host",
                        _kernel.GetConfig("gatewayHost")
                    },
                    { "content-type", "application/x-www-form-urlencoded;charset=utf-8" }
                };
                    teaRequest.Query = _kernel.SortMap(TeaConverter.merge<string>(new object[3]
                    {
                    new Dictionary<string, string> {
                    {
                        "sign",
                        _kernel.Sign(dictionary, bizParams, dictionary2, _kernel.GetConfig("merchantPrivateKey"))
                    } },
                    dictionary,
                    dictionary2
                    }));
                    teaRequest.Body = TeaCore.BytesReadable(_kernel.ToUrlEncodedRequestBody(bizParams));
                    _lastRequest = teaRequest;
                    TeaResponse response = await TeaCore.DoActionAsync(teaRequest, runtime_);
                    Dictionary<string, object> respMap = await _kernel.ReadAsJsonAsync(response, "alipay.trade.refund");
                    if (_kernel.IsCertMode())
                    {
                        if (_kernel.Verify(respMap, _kernel.ExtractAlipayPublicKey(_kernel.GetAlipayCertSN(respMap))))
                        {
                            return TeaModel.ToObject<AlipayTradeRefundResponse>(_kernel.ToRespModel(respMap));
                        }
                    }
                    else if (_kernel.Verify(respMap, _kernel.GetConfig("alipayPublicKey")))
                    {
                        return TeaModel.ToObject<AlipayTradeRefundResponse>(_kernel.ToRespModel(respMap));
                    }
                    throw new TeaException(new Dictionary<string, string> { { "message", "验签失败,请检查支付宝公钥设置是否正确。" } });
                }
                catch (Exception ex)
                {
                    if (TeaCore.IsRetryable(ex))
                    {
                        innerException = ex;
                        continue;
                    }
                    throw ex;
                }
            }
            throw new TeaUnretryableException(_lastRequest, innerException);
        }
    }
}
LifePayment/LifePayment.Domain/Ali/AlipayApiConstant.cs
@@ -29,7 +29,39 @@
    }
    public class AlipayStatus
    {
        /// <summary>
        /// 交易创建,等待买家付款
        /// </summary>
        public const string WAITBUYERPAY = "WAIT_BUYER_PAY";
        /// <summary>
        /// 未付款交易超时关闭,或支付完成后全额退款
        /// </summary>
        public const string TRADECLOSED = "TRADE_CLOSED";
        /// <summary>
        /// 交易支付成功
        /// </summary>
        public const string TRADESUCCESS = "TRADE_SUCCESS";
        /// <summary>
        /// 交易结束,不可退款
        /// </summary>
        public const string TRADEFINISHED = "TRADE_FINISHED";
    }
    /// <summary>
    /// 交易状态
    /// </summary>
    public class AlipayRefundStatus
    {
        /// <summary>
        /// 退款处理成功:REFUND_SUCCESS    未返回该字段表示退款请求未收到或者退款失败
        /// </summary>
        public const string Success = "REFUND_SUCCESS";
    }
    public class AlipayResultCode
    {
        public const string Success = "10000";
LifePayment/LifePayment.Domain/LifePay/LifePayExpensesReceipts.cs
New file
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp;
using LifePayment.Domain.Shared;
namespace LifePayment.Domain.LifePay
{
    /// <summary>
    /// 收支流水
    /// </summary>
    public class LifePayExpensesReceipts : FullAuditedEntity<Guid>, IDataUserFilter
    {
        public LifePayExpensesReceipts()
        {
        }
        /// <summary>
        /// 平台订单号
        /// </summary>
        public string OrderNo { get; set; }
        /// <summary>
        /// 渠道流水号
        /// </summary>
        public string OutOrderNo { get; set; }
        /// <summary>
        /// 支付渠道
        /// </summary>
        public LifePayTypeEnum LifePayType { get; set; }
        /// <summary>
        /// 收支类型
        /// </summary>
        public ExpensesReceiptsTypeEnum ExpensesReceiptsType { get; set; }
        /// <summary>
        /// 交易金额
        /// </summary>
        public decimal Amount { get; set; }
        /// <summary>
        /// 交易时间
        /// </summary>
        public DateTime FinishTime { get; set; }
        /// <summary>
        /// 拓展熟悉
        /// </summary>
        public string ExtraProperties { get; set; }
    }
}
LifePayment/LifePayment.Domain/LifePay/LifePayRechargeReceipts.cs
@@ -8,6 +8,9 @@
namespace LifePayment.Domain.LifePay
{
    /// <summary>
    /// 充值流水
    /// </summary>
    public class LifePayRechargeReceipts : FullAuditedEntity<Guid>, IDataUserFilter
    {
        public LifePayRechargeReceipts()
LifePayment/LifePayment.EntityFrameworkCore/LifePaymentServicesDbContext.cs
@@ -27,6 +27,8 @@
        public virtual DbSet<LifePayRechargeReceipts> LifePayRechargeReceipts { get; set; }
        public virtual DbSet<LifePayExpensesReceipts> LifePayExpensesReceipts { get; set; }
        public virtual DbSet<Area> Area { get; set; }
        public virtual DbSet<User> Users { get; set; }
LifePayment/LifePayment.Host/LifePaymentService.HttpApi.xml
@@ -508,5 +508,12 @@
            <param name="input"></param>
            <returns></returns>
        </member>
        <member name="M:LifePayment.HttpApi.WxPayNotifyController.WxPayDomesticRefundsNotify(LifePayment.Application.Contracts.WxRechargeNotifyInput)">
            <summary>
            微信退款通知回调
            </summary>
            <param name="input"></param>
            <returns></returns>
        </member>
    </members>
</doc>
LifePayment/LifePayment.Host/LifePaymentServices.Application.Contracts.xml
@@ -751,6 +751,31 @@
            充值凭证
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.AddLifePayExpensesReceiptsInput.OrderNo">
            <summary>
            平台订单号
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.AddLifePayExpensesReceiptsInput.OutOrderNo">
            <summary>
            渠道流水号
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.AddLifePayExpensesReceiptsInput.LifePayType">
            <summary>
            支付渠道
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.AddLifePayExpensesReceiptsInput.ExpensesReceiptsType">
            <summary>
            收支类型
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.AddLifePayExpensesReceiptsInput.Amount">
            <summary>
            交易金额
            </summary>
        </member>
        <member name="P:LifePayment.Application.Contracts.LifePayIntroInfoInput.LifePayType">
            <summary>
            生活缴费类型
LifePayment/LifePayment.HttpApi/LifePay/AliPayNotifyController.cs
@@ -22,6 +22,7 @@
    {
        private readonly ILifePayService _lifePayService;
        private readonly ILifePayOrderService _lifePayOrderService;
        private readonly ILogger<AliPayNotifyController> _logger;
@@ -29,10 +30,12 @@
               ILogger<AliPayNotifyController> logger,
               ILifePayService lifePayService)
               ILifePayService lifePayService,
               ILifePayOrderService lifePayOrderService)
        {
            _logger = logger;
            _lifePayService = lifePayService;
            _lifePayOrderService = lifePayOrderService;
        }
        /// <summary>
@@ -57,6 +60,9 @@
                if (input.TradeStatus == LifePaymentConstant.AliPayStatus.支付成功)
                {
                    await _lifePayService.LifePaySuccessHandler(input.OutTradeNo, input.TradeNo);
                    await _lifePayOrderService.AddLifePayExpensesReceipts(new AddLifePayExpensesReceiptsInput() { OrderNo = input.OutTradeNo,
                        OutOrderNo = input.TradeNo ,LifePayType = LifePayTypeEnum.AliPay,ExpensesReceiptsType = ExpensesReceiptsTypeEnum.Expenses,
                        Amount = input.ReceiptAmount.Value });
                }
            }
            else
LifePayment/LifePayment.HttpApi/LifePay/WxPayNotifyController.cs
@@ -21,16 +21,19 @@
        private readonly IWxPayApi _wxPayApi;
        private readonly ILifePayService _lifePayService;
        private readonly ILifePayOrderService _lifePayOrderService;
        private readonly ILogger<WxPayNotifyController> _logger;
        public WxPayNotifyController(
               IWxPayApi wxPayApi,
               ILogger<WxPayNotifyController> logger,
               ILifePayService lifePayService)
               ILifePayService lifePayService,
               ILifePayOrderService lifePayOrderService)
        {
            _wxPayApi = wxPayApi;
            _logger = logger;
            _lifePayService = lifePayService;
            _lifePayOrderService = lifePayOrderService;
        }
        /// <summary>
@@ -53,6 +56,14 @@
                    if (wxPayNotice.TradeState == LifePaymentConstant.WxPayStatus.支付成功)
                    {
                        await _lifePayService.LifePaySuccessHandler(wxPayNotice.OutTradeNo, wxPayNotice.TransactionId);
                        await _lifePayOrderService.AddLifePayExpensesReceipts(new AddLifePayExpensesReceiptsInput()
                        {
                            OrderNo = wxPayNotice.OutTradeNo,
                            OutOrderNo = wxPayNotice.TransactionId,
                            LifePayType = LifePayTypeEnum.WxPay,
                            ExpensesReceiptsType = ExpensesReceiptsTypeEnum.Expenses,
                            Amount = wxPayNotice.Amount.Total
                        });
                    }
                }
            }
@@ -72,7 +83,11 @@
            };
        }
        /// <summary>
        /// 微信退款通知回调
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        [UnitOfWork]
        public async Task<WxRechargeNotifyResult> WxPayDomesticRefundsNotify(WxRechargeNotifyInput input)
@@ -92,8 +107,6 @@
                    switch (wxPayNotice.RefundStatus)
                    {
                        case LifePaymentConstant.WxPayRefundStatus.退款成功:
                            await _lifePayService.WxPayDomesticRefundsHandler(wxPayNotice.OutTradeNo, LifePayRefundStatusEnum.已退款);
                            break;
                        case LifePaymentConstant.WxPayRefundStatus.退款关闭:
                            await _lifePayService.WxPayDomesticRefundsHandler(wxPayNotice.OutTradeNo, LifePayRefundStatusEnum.已退款);
                            break;