From 5ce19e37621a1c5a5d1e92280f560be97786594e Mon Sep 17 00:00:00 2001
From: zhengyuxuan <zhengyuxuan1995>
Date: 星期二, 18 三月 2025 14:10:45 +0800
Subject: [PATCH] fix:新增微信退款接口
---
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