From 874a98a34bd35b565dc9a33338bdfe407c9e8725 Mon Sep 17 00:00:00 2001
From: lingling <kety1122@163.com>
Date: 星期二, 18 三月 2025 14:19:25 +0800
Subject: [PATCH] Merge branch 'master' of http://120.26.58.240:8888/r/LifePaymentApi

---
 LifePayment/LifePayment.Domain/WeChat/WxClient.cs                  |   18 ++-
 LifePayment/LifePayment.Domain/WeChat/IWxPayApi.cs                 |    3 
 LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs  |   19 +++
 LifePayment/LifePayment.Domain/WeChat/WxPayApi.cs                  |    6 +
 LifePayment/LifePayment.Application/LifePay/LifePayService.cs      |   29 +++++
 LifePayment/LifePayment.Domain.Shared/LifePaymentConstant.cs       |   16 +++
 LifePayment/LifePayment.Domain.Shared/WeChat/WxPayPostBaseModel.cs |  178 +++++++++++++++++++++++++++++++++++
 7 files changed, 261 insertions(+), 8 deletions(-)

diff --git a/LifePayment/LifePayment.Application/LifePay/LifePayService.cs b/LifePayment/LifePayment.Application/LifePay/LifePayService.cs
index fc3e010..5338c44 100644
--- a/LifePayment/LifePayment.Application/LifePay/LifePayService.cs
+++ b/LifePayment/LifePayment.Application/LifePay/LifePayService.cs
@@ -993,6 +993,9 @@
             throw new UserFriendlyException("褰撳墠璁㈠崟鐘舵�佹棤娉曢��娆�");
         }
 
+        /// TODO 閫�娆捐姹傚畬鎴愬悗濡備綍鎿嶄綔
+        /// var refundResult = await WxPayDomesticRefunds(order.OrderNo, order.RefundApplyRemark, Convert.ToInt32(order.PayAmount * 100), Convert.ToInt32(order.PayAmount * 100));
+
         order.PayStatus = LifePayStatusEnum.宸查��娆�;
         order.LifePayOrderStatus = LifePayOrderStatusEnum.宸查��娆�;
         order.RefundCredentialsImgUrl = input.RefundCredentialsImgUrl;
@@ -1043,6 +1046,26 @@
         await _lifePayOrderRepository.UpdateAsync(order);
     }
 
+    public async Task<WxPayDomesticRefundsReponse> 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;
+    }
+
     public async Task<int> AddUpdateUserAccount(AddUpdateUserAccountInput input)
     {
         if (input.Id.HasValue)
@@ -1064,7 +1087,6 @@
         }
         else
         {
-
             var repeatAccountContent = await _lifePayAccount.Where(x => x.UserId == input.UserId && x.LifePayType == input.LifePayType && x.Content == input.Content)
                                             .FirstOrDefaultAsync();
             CheckExtensions.IfTrueThrowUserFriendlyException(repeatAccountContent != null, "鎴峰彿宸插瓨鍦�");
@@ -1240,6 +1262,11 @@
         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)
     {
         /// 姝e父鏀粯
diff --git a/LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs b/LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs
index 78394fa..c0bcca7 100644
--- a/LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs
+++ b/LifePayment/LifePayment.Domain.Shared/Enum/LifePay/LifePayEnum.cs
@@ -59,6 +59,25 @@
     閫�娆惧け璐� = 60,
 }
 
+public enum LifePayRefundStatusEnum
+{
+    [Description("鏃犻渶閫�娆�")]
+    鏃犻渶閫�娆� = 0,
+
+    [Description("寰呴��娆�")]
+    寰呴��娆� = 10,
+
+    [Description("閫�娆句腑")]
+    閫�娆句腑 = 20,
+
+    [Description("宸查��娆�")]
+    宸查��娆� = 30,
+
+    [Description("閫�娆鹃┏鍥�")]
+    閫�娆鹃┏鍥� = 40,
+
+}
+
 public enum LifePayRateTypeEnum
 { 
     榛樿璇濊垂鎶樻墸=10,
diff --git a/LifePayment/LifePayment.Domain.Shared/LifePaymentConstant.cs b/LifePayment/LifePayment.Domain.Shared/LifePaymentConstant.cs
index 747fde5..b093ed8 100644
--- a/LifePayment/LifePayment.Domain.Shared/LifePaymentConstant.cs
+++ b/LifePayment/LifePayment.Domain.Shared/LifePaymentConstant.cs
@@ -53,7 +53,11 @@
 
         public const string PayTransactionsH5 = "/v3/pay/transactions/h5";
 
+        public const string WxPayDomesticRefunds = "/v3/refund/domestic/refunds";
+
         public const string WxRechargeNotifySectionUrl = "/api/WxPayNotify/WxRechargeNotify";
+
+        public const string WxPayDomesticRefundsNotifySectionUrl = "/api/WxPayNotify/WxPayDomesticRefundsNotify";
 
         public const string AliRechargeNotifySectionUrl = "/api/AliPayNotify/AliRechargeNotify";
 
@@ -423,6 +427,18 @@
 
             public const string 鏀粯鎴愬姛 = "SUCCESS";
         }
+
+        public static class WxPayRefundStatus
+        {
+            public const string 閫�娆炬垚鍔� = "SUCCESS";
+
+            public const string 閫�娆惧叧闂� = "CLOSED";
+
+            public const string 閫�娆惧鐞嗕腑 = "PROCESSING";
+
+            public const string 閫�娆惧紓甯� = "ABNORMAL";
+
+        }
         public static class ThumbsUpStatus
         {
             public const int 鍙栨秷 = 0;
diff --git a/LifePayment/LifePayment.Domain.Shared/WeChat/WxPayPostBaseModel.cs b/LifePayment/LifePayment.Domain.Shared/WeChat/WxPayPostBaseModel.cs
index 6663b7e..1cbcb93 100644
--- a/LifePayment/LifePayment.Domain.Shared/WeChat/WxPayPostBaseModel.cs
+++ b/LifePayment/LifePayment.Domain.Shared/WeChat/WxPayPostBaseModel.cs
@@ -594,4 +594,182 @@
 
         public string Attach { get; set; }
     }
+
+    /// <summary>
+    /// 鐢宠閫�娆�
+    /// </summary>
+    public class WxPayDomesticRefundsRequest
+    {
+        /// <summary>
+        /// 寰俊鏀粯璁㈠崟鍙� 鍜宱ut_trade_no蹇呴』浜岄�変竴杩涜浼犲弬
+        /// </summary>
+        [JsonProperty("transaction_id")]
+        public string TransactionId { get; set; }
+
+        /// <summary>
+        /// 鍟嗘埛璁㈠崟鍙� 鍜宱ut_trade_no蹇呴』浜岄�変竴杩涜浼犲弬
+        /// </summary>
+        [JsonProperty("out_trade_no")]
+        public string OutTradeNo { get; set; }
+
+        /// <summary>
+        /// 鍟嗘埛閫�娆惧崟鍙� 蹇呭~
+        /// </summary>
+        [JsonProperty("out_refund_no")]
+        public string OutRefundNo { get; set; }
+
+        /// <summary>
+        ///  閫�娆惧師鍥�
+        /// </summary>
+        [JsonProperty("reason")]
+        public string Reason { get; set; }
+
+        /// <summary>
+        /// 閫�娆剧粨鏋滃洖璋僽rl
+        /// </summary>
+        [JsonProperty("notify_url")]
+        public string NotifyUrl { get; set; }
+
+        /// <summary>
+        /// 閫�娆捐祫閲戞潵婧�
+        /// </summary>
+        [JsonProperty("funds_account")]
+        public string FundsAccount { get; set; }
+
+        /// <summary>
+        /// 閲戦淇℃伅 蹇呭~
+        /// </summary>
+        [JsonProperty("amount")]
+        public Model_WxPayDomesticRefunds_Amount Amount { get; set; }
+    }
+    public class Model_WxPayDomesticRefunds_Amount
+    {
+        /// <summary>
+        /// 閫�娆鹃噾棰濓紝鍗曚綅涓哄垎锛屽彧鑳戒负鏁存暟
+        /// </summary>
+        [JsonProperty("refund")]
+        public int Refund { get; set; }
+
+        /// <summary>
+        /// 鍘熻鍗曢噾棰�
+        /// </summary>
+        [JsonProperty("total")]
+        public int Total { get; set; }
+
+        /// <summary>
+        /// 閫�娆惧竵绉�
+        /// </summary>
+        [JsonProperty("currency")]
+        public string Currency { get; set; } = "CNY";
+    }
+
+    public class WxPayDomesticRefundsReponse
+    {
+        /// <summary>
+        /// 寰俊鏀粯閫�娆惧崟鍙�
+        /// </summary>
+        [JsonProperty("refund_id")]
+        public string RefundId { get; set; }
+
+        /// <summary>
+        /// 鍟嗘埛閫�娆惧崟鍙�
+        /// </summary>
+        [JsonProperty("out_refund_no")]
+        public string OutRefundNo { get; set; }
+
+        /// <summary>
+        /// 寰俊鏀粯璁㈠崟鍙�
+        /// </summary>
+        [JsonProperty("transaction_id")]
+        public string TransactionId { get; set; }
+
+        /// <summary>
+        /// 鍟嗘埛璁㈠崟鍙�
+        /// </summary>
+        [JsonProperty("out_trade_no")]
+        public string OutTradeNo { get; set; }
+
+        /// <summary>
+        /// 閫�娆炬笭閬� ORIGINAL: 鍘熻矾閫�娆� BALANCE: 閫�鍥炲埌浣欓 OTHER_BALANCE: 鍘熻处鎴峰紓甯搁��鍒板叾浠栦綑棰濊处鎴� OTHER_BANKCARD: 鍘熼摱琛屽崱寮傚父閫�鍒板叾浠栭摱琛屽崱(鍙戣捣寮傚父閫�娆炬垚鍔熷悗杩斿洖)
+        /// </summary>
+        [JsonProperty("channel")]
+        public string Channel {  get; set; }
+
+        /// <summary>
+        /// 閫�娆惧叆璐﹁处鎴�
+        /// </summary>
+        [JsonProperty("user_received_account")]
+        public string UserReceivedAccount { get; set; }
+
+        /// <summary>
+        /// 閫�娆炬垚鍔熸椂闂�
+        /// </summary>
+        [JsonProperty("success_time")]
+        public string SuccessTime { get; set; }
+
+        /// <summary>
+        /// 閫�娆惧垱寤烘椂闂�
+        /// </summary>
+        [JsonProperty("create_time")]
+        public string CreateTime { get; set; }
+
+        /// <summary>
+        /// 閫�娆剧姸鎬�
+        /// </summary>
+        [JsonProperty("status")]
+        public string Status { get; set; }
+
+        /// <summary>
+        /// 璧勯噾璐︽埛
+        /// </summary>
+        [JsonProperty("funds_account")]
+        public string FundsAccount { get; set; }
+
+        /// <summary>
+        /// 閲戦淇℃伅
+        /// </summary>
+        [JsonProperty("amount")]
+        public Model_WxPayRetuenDomesticRefunds_Amount Amount { get; set; }
+
+    }
+
+    public class Model_WxPayRetuenDomesticRefunds_Amount: Model_WxPayDomesticRefunds_Amount
+    {
+        /// <summary>
+        /// 鐢ㄦ埛瀹為檯鏀粯閲戦
+        /// </summary>
+        [JsonProperty("payer_total")]
+        public int PayerTotal { get; set; }
+
+        /// <summary>
+        /// 鐢ㄦ埛閫�娆鹃噾棰�
+        /// </summary>
+        [JsonProperty("payer_refund")]
+        public int PayerRefund { get; set; }
+
+        /// <summary>
+        /// 搴旂粨閫�娆鹃噾棰�
+        /// </summary>
+        [JsonProperty("settlement_refund")]
+        public int SettlementRefund { get; set; }
+
+        /// <summary>
+        /// 搴旂粨璁㈠崟閲戦
+        /// </summary>
+        [JsonProperty("settlement_total")]
+        public int SettlementTotal { get; set; }
+
+        /// <summary>
+        /// 浼樻儬閫�娆鹃噾棰�
+        /// </summary>
+        [JsonProperty("discount_refund")]
+        public int DiscountRefund { get; set; }
+
+        /// <summary>
+        /// 鎵嬬画璐归��娆鹃噾棰�
+        /// </summary>
+        [JsonProperty("refund_fee")]
+        public int RefundFee { get; set; }
+
+    }
 }
\ No newline at end of file
diff --git a/LifePayment/LifePayment.Domain/WeChat/IWxPayApi.cs b/LifePayment/LifePayment.Domain/WeChat/IWxPayApi.cs
index aecaf8c..3b34e5d 100644
--- a/LifePayment/LifePayment.Domain/WeChat/IWxPayApi.cs
+++ b/LifePayment/LifePayment.Domain/WeChat/IWxPayApi.cs
@@ -21,6 +21,7 @@
         Task<ModelPayPrePayId> PayTransactionsJsAPI(ModelMiniPayRequest input);
 
         string GeneratePaySignByKey(string message);
-      
+
+        Task<WxPayDomesticRefundsReponse> WxPayDomesticRefunds(WxPayDomesticRefundsRequest input);
     }
 }
\ No newline at end of file
diff --git a/LifePayment/LifePayment.Domain/WeChat/WxClient.cs b/LifePayment/LifePayment.Domain/WeChat/WxClient.cs
index 63ef888..4d30661 100644
--- a/LifePayment/LifePayment.Domain/WeChat/WxClient.cs
+++ b/LifePayment/LifePayment.Domain/WeChat/WxClient.cs
@@ -35,7 +35,18 @@
             AddAuthHeader(client, BuildAuth(body, function));
             var data = new StringContent(body, Encoding.UTF8, "application/json");
             var responseMessage = await client.PostAsync($"{Options.Url}{function}", data);
-            
+            var str = await responseMessage.Content.ReadAsStringAsync();
+            var result = JsonConvert.DeserializeObject<TResult>(str);
+            return result;
+        }
+
+        public async Task<TResult> RefundsPostAsync<TInput, TResult>(TInput input, string function)
+        {
+            var client = HttpClientFactory.CreateClient(LifePaymentConstant.WxPayHttpClientName);
+            var body = JsonConvert.SerializeObject(input);
+            AddAuthHeader(client, BuildAuth(body, function));
+            var data = new StringContent(body, Encoding.UTF8, "application/json");
+            var responseMessage = await client.PostAsync($"{Options.Url}{function}", data);
             var str = await responseMessage.Content.ReadAsStringAsync();
             var result = JsonConvert.DeserializeObject<TResult>(str);
             return result;
@@ -129,9 +140,9 @@
             gcmBlockCipher.DoFinal(plaintext, length);
             return Encoding.UTF8.GetString(plaintext);
         }
+
         public string GeneratePaySignByKey(string message)
         {
-           
             return WxPayRsaHelper.Sign(message);
         }
 
@@ -148,8 +159,5 @@
             string signature = WxPayRsaHelper.Sign(message);
             return $"mchid=\"{Options.Mchid}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{Options.SerialNo}\",signature=\"{signature}\"";
         }
-
-
-
     }
 }
\ No newline at end of file
diff --git a/LifePayment/LifePayment.Domain/WeChat/WxPayApi.cs b/LifePayment/LifePayment.Domain/WeChat/WxPayApi.cs
index 7f5612f..c26f1e6 100644
--- a/LifePayment/LifePayment.Domain/WeChat/WxPayApi.cs
+++ b/LifePayment/LifePayment.Domain/WeChat/WxPayApi.cs
@@ -29,6 +29,10 @@
             return result;
         }
 
-
+        public async Task<WxPayDomesticRefundsReponse> WxPayDomesticRefunds(WxPayDomesticRefundsRequest input)
+        {
+            var result = await RefundsPostAsync<WxPayDomesticRefundsRequest, WxPayDomesticRefundsReponse>(input, LifePaymentConstant.WxPayDomesticRefunds);
+            return result;
+        }
     }
 }
\ No newline at end of file

--
Gitblit v1.9.1