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