diff --git a/Admin.NET/Admin.NET.Core/Entity/SysWechatPay.cs b/Admin.NET/Admin.NET.Core/Entity/SysWechatPay.cs
index 62e5c127..aff68a15 100644
--- a/Admin.NET/Admin.NET.Core/Entity/SysWechatPay.cs
+++ b/Admin.NET/Admin.NET.Core/Entity/SysWechatPay.cs
@@ -11,8 +11,21 @@ namespace Admin.NET.Core;
///
[SugarTable(null, "系统微信支付表")]
[SysTable]
+[SugarIndex("sys_wechat_pay_order_id", nameof(OrderId), OrderByType.Desc)]
public partial class SysWechatPay : EntityBase
{
+ ///
+ /// 关联的商户订单号
+ ///
+ [SugarColumn(ColumnDescription = "OrderId")]
+ public virtual long OrderId { get; set; }
+
+ ///
+ /// 关联的商户订单状态(或者为第几次支付,有些订单涉及多次支付,比如先付预付款,后补尾款)
+ ///
+ [SugarColumn(ColumnDescription = "OrderStatus")]
+ public virtual int OrderStatus { get; set; }
+
///
/// 微信商户号
///
@@ -154,7 +167,7 @@ public partial class SysWechatPay : EntityBase
///
/// 子商户AppId
///
- [SugarColumn(ColumnDescription = "回调通知地址")]
+ [SugarColumn(ColumnDescription = "子商户AppId")]
public string? SubAppId { get; set; }
///
diff --git a/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs b/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs
new file mode 100644
index 00000000..8a309673
--- /dev/null
+++ b/Admin.NET/Admin.NET.Core/Entity/SysWechatRefund.cs
@@ -0,0 +1,121 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+///
+/// 微信退款表
+///
+[SugarTable(null, "系统微信退款表")]
+[SysTable]
+[SugarIndex("sys_wechat_refund_order_id", nameof(OrderId), OrderByType.Desc)]
+public class SysWechatRefund : EntityBase
+{
+ ///
+ /// 微信支付订单号(原支付交易对应的微信订单号)
+ ///
+ [SugarColumn(ColumnDescription = "微信支付订单号", Length = 32)]
+ [Required]
+ public string TransactionId { get; set; }
+
+ ///
+ /// 商户订单号(原交易对应的商户付款单号)
+ ///
+ [SugarColumn(ColumnDescription = "商户付款单号", Length = 32)]
+ [Required]
+ public string OutTradeNumber { get; set; }
+
+ ///
+ /// 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
+ ///
+ [SugarColumn(ColumnDescription = "商户退款单号", Length = 64)]
+ [Required]
+ public string OutRefundNo { get; set; }
+
+ ///
+ /// 退款原因,示例:商品已售完
+ ///
+ [SugarColumn(ColumnDescription = "退款原因", Length = 80)]
+ public string Reason { get; set; }
+
+ ///
+ /// 退款金额
+ ///
+ [SugarColumn(ColumnDescription = "退款金额")]
+ public int Refund { get; set; }
+
+ ///
+ /// 原订单总金额
+ ///
+ [SugarColumn(ColumnDescription = "订单总金额")]
+ public int Total { get; set; }
+
+ ///
+ /// 退款结果回调url
+ ///
+ [SugarColumn(ColumnDescription = "退款结果回调url", Length = 256)]
+ public string? NotifyUrl { get; set; }
+
+ ///
+ /// 退款资金来源, 可不传,默认使用未结算资金退款(仅对老资金流商户适用)
+ ///
+ [SugarColumn(ColumnDescription = "退款资金来源", Length = 32)]
+ public string FundsAccount { get; set; }
+
+ ///
+ /// 关联的商户订单号
+ ///
+ [SugarColumn(ColumnDescription = "关联的用户订单号")]
+ public long OrderId { get; set; }
+
+ ///
+ /// 关联的商户订单状态(或者为第几次支付,有些订单涉及多次支付,比如先付预付款,后补尾款)
+ ///
+ [SugarColumn(ColumnDescription = "关联的商户订单状态")]
+ public int OrderStatus { get; set; }
+
+ ///
+ /// 关联的商户商品编码
+ ///
+ [SugarColumn(ColumnDescription = "关联的商户商品编码", Length = 32)]
+ public string MerchantGoodsId { get; set; }
+
+ ///
+ /// 关联的商户商品名称
+ ///
+ [SugarColumn(ColumnDescription = "关联的商户商品名称", Length = 256)]
+ public string GoodsName { get; set; }
+
+ ///
+ /// 关联的商户商品单价
+ ///
+ [SugarColumn(ColumnDescription = "关联的商户商品单价")]
+ public int UnitPrice { get; set; }
+
+ ///
+ /// 关联的商户商品退款金额
+ ///
+ [SugarColumn(ColumnDescription = "关联的商户商品退款金额")]
+ public int RefundAmount { get; set; }
+
+ ///
+ /// 关联的商户商品退货数量
+ ///
+ [SugarColumn(ColumnDescription = "关联的商户商品退货数量")]
+ public int RefundQuantity { get; set; } = 1;
+
+ ///
+ /// 附加数据
+ ///
+ [SugarColumn(ColumnDescription = "附加数据")]
+ public string? Attachment { get; set; }
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注")]
+ public string? Remark { get; set; }
+}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayInput.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayInput.cs
index 4d29621a..84fe10af 100644
--- a/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayInput.cs
+++ b/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayInput.cs
@@ -32,6 +32,16 @@ public class WechatPayTransactionInput
/// 优惠标记
///
public string GoodsTag { get; set; }
+
+ ///
+ /// 关联的商户订单号
+ ///
+ public long OrderId { get; set; }
+
+ ///
+ /// 关联的商户订单付款状态(或者为第几次支付,有些订单涉及多次支付,比如先付预付款,后补尾款)
+ ///
+ public int OrderStatus { get; set; } = 0;
}
public class WechatPayParaInput
@@ -40,4 +50,95 @@ public class WechatPayParaInput
/// 订单Id
///
public string PrepayId { get; set; }
+}
+
+
+public class RefundRequestInput // : WechatTenpayRequest
+{
+ ///
+ /// 商户订单号(原支付交易对应的付款单号)
+ ///
+ public string OutTradeNumber { get; set; }
+ /////
+ ///// 退款单号
+ /////
+ //public string OutRefundNumber { get; set; }
+ ///
+ /// 原订单金额(分)
+ ///
+ public int Total { get; set; }
+ ///
+ /// 退款金额(分)
+ ///
+ public int Refund { get; set; }
+ ///
+ /// 退款原因
+ ///
+ public string Reason { get; set; }
+ ///
+ /// 关联的商户订单号
+ ///
+ public long OrderId { get; set; }
+ ///
+ /// 关联的商户订单状态(或者为第几次支付,有些订单涉及多次支付,比如先付预付款,后补尾款)
+ ///
+ public int OrderStatus { get; set; }
+ ///
+ /// 关联的商户商品编码
+ ///
+ public string MerchantGoodsId { get; set; }
+ ///
+ /// 关联的商户商品名称
+ ///
+ public string GoodsName { get; set; }
+ ///
+ /// 关联的商户商品单价
+ ///
+ public int UnitPrice { get; set; } = 0;
+ ///
+ /// 关联的商户商品退款金额
+ ///
+ public int RefundAmount { get; set; } = 0;
+ ///
+ /// 关联的商户商品退货数量
+ ///
+ public int RefundQuantity { get; set; } = 1;
+ ///
+ /// 附加数据
+ ///
+ public string Attachment { get; set; }
+ ///
+ /// 备注
+ ///
+ public string Remark { get; set; }
+}
+
+public class PageSysWechatPayInput : BasePageInput
+{
+ ///
+ /// order_id
+ ///
+ ///
+ public long? OrderId { get; set; } = -1;
+ ///
+ /// order_status
+ ///
+ ///
+ public long? OrderStatus { get; set; } = -1;
+
+ ///
+ /// out_trade_number
+ ///
+ ///
+ public string OutTradeNumber { get; set; }
+ ///
+ /// success_time范围
+ ///
+ ///
+ public List SuccessTimeRange { get; set; }
+ ///
+ /// expire_time范围
+ ///
+ ///
+ public List ExpireTimeRange { get; set; }
}
\ No newline at end of file
diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayOutput.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayOutput.cs
index b00e16aa..9a664e5d 100644
--- a/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayOutput.cs
+++ b/Admin.NET/Admin.NET.Core/Service/Wechat/Dto/WechatPayOutput.cs
@@ -12,19 +12,51 @@ public class WechatPayOutput
/// OpenId
///
public string OpenId { get; set; }
-
+ ///
+ /// 商户(支付交易)单号,微信唯一
+ ///
+ public string OutTradeNumber { get; set; }
+ ///
+ /// 关联的商户(商品交易)订单号
+ ///
+ public long OrderId { get; set; }
+ ///
+ /// 关联的商户订单状态(或者为第几次支付,有些订单涉及多次支付,比如先付预付款,后补尾款)
+ ///
+ public int OrderStatus { get; set; }
///
/// 订单金额
///
public int Total { get; set; }
-
///
/// 附加数据
///
public string Attachment { get; set; }
-
///
/// 优惠标记
///
public string GoodsTag { get; set; }
-}
\ No newline at end of file
+ ///
+ /// 支付发起时间
+ ///
+ public DateTimeOffset CreateTime { get; set; }
+ ///
+ /// 支付完成时间
+ ///
+ public DateTimeOffset SuccessTime { get; set; }
+ ///
+ /// 交易状态(支付成功后,微信返回)
+ ///
+ public string? TradeState { get; set; }
+
+ ///
+ /// 交易状态描述(支付成功后,微信返回)
+ ///
+ public string? TradeStateDescription { get; set; }
+}
+
+public class CreatePayTransactionOutput
+{
+ public string PrepayId { get; set; }
+ public string OutTradeNumber { get; set; }
+}
diff --git a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs
index 957af35e..1a6d9360 100644
--- a/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs
+++ b/Admin.NET/Admin.NET.Core/Service/Wechat/SysWechatPayService.cs
@@ -12,18 +12,20 @@ namespace Admin.NET.Core.Service;
[ApiDescriptionSettings(Order = 210)]
public class SysWechatPayService : IDynamicApiController, ITransient
{
- private readonly SqlSugarRepository _sysWechatPayUserRep;
-
+ private readonly SqlSugarRepository _sysWechatPayRep;
+ private readonly SqlSugarRepository _sysWechatRefundRep;
private readonly WechatPayOptions _wechatPayOptions;
private readonly PayCallBackOptions _payCallBackOptions;
private readonly WechatTenpayClient _wechatTenpayClient;
- public SysWechatPayService(SqlSugarRepository sysWechatPayUserRep,
- IOptions wechatPayOptions,
- IOptions payCallBackOptions)
+ public SysWechatPayService(SqlSugarRepository sysWechatPayRep
+ , SqlSugarRepository sysWechatRefundRep
+ , IOptions wechatPayOptions
+ , IOptions payCallBackOptions)
{
- _sysWechatPayUserRep = sysWechatPayUserRep;
+ _sysWechatPayRep = sysWechatPayRep;
+ this._sysWechatRefundRep = sysWechatRefundRep;
_wechatPayOptions = wechatPayOptions.Value;
_payCallBackOptions = payCallBackOptions.Value;
@@ -64,11 +66,20 @@ public class SysWechatPayService : IDynamicApiController, ITransient
/// 微信支付统一下单获取Id(商户直连) 🔖
///
[DisplayName("微信支付统一下单获取Id(商户直连)")]
- public async Task CreatePayTransaction([FromBody] WechatPayTransactionInput input)
+ public async Task CreatePayTransaction([FromBody] WechatPayTransactionInput input)
{
+ string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一)
+
+ //检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断)
+ var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus);
+ if (wechatPay != null)
+ {
+ outTradeNumber = wechatPay.OutTradeNumber;
+ }
+
var request = new CreatePayTransactionJsapiRequest()
{
- OutTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000), // 订单号
+ OutTradeNumber = outTradeNumber,
AppId = _wechatPayOptions.AppId,
Description = input.Description,
Attachment = input.Attachment,
@@ -80,27 +91,32 @@ public class SysWechatPayService : IDynamicApiController, ITransient
};
var response = await _wechatTenpayClient.ExecuteCreatePayTransactionJsapiAsync(request);
if (!response.IsSuccessful())
- throw Oops.Oh(response.ErrorMessage);
+ throw Oops.Oh(response.ErrorMessage);
- // 保存订单信息
- var wechatPay = new SysWechatPay()
+ if (wechatPay == null)
{
- AppId = _wechatPayOptions.AppId,
- MerchantId = _wechatPayOptions.MerchantId,
- OutTradeNumber = request.OutTradeNumber,
- Description = input.Description,
- Attachment = input.Attachment,
- GoodsTag = input.GoodsTag,
- Total = input.Total,
- OpenId = input.OpenId,
- TransactionId = ""
- };
- await _sysWechatPayUserRep.InsertAsync(wechatPay);
+ // 保存订单信息
+ wechatPay = new SysWechatPay()
+ {
+ AppId = _wechatPayOptions.AppId,
+ MerchantId = _wechatPayOptions.MerchantId,
+ OutTradeNumber = request.OutTradeNumber,
+ Description = input.Description,
+ Attachment = input.Attachment,
+ GoodsTag = input.GoodsTag,
+ Total = input.Total,
+ OpenId = input.OpenId,
+ TransactionId = "",
+ OrderId = input.OrderId,
+ OrderStatus = input.OrderStatus
+ };
+ await _sysWechatPayRep.InsertAsync(wechatPay);
+ }
- return new
+ return new CreatePayTransactionOutput
{
- response.PrepayId,
- request.OutTradeNumber
+ PrepayId = response.PrepayId,
+ OutTradeNumber = request.OutTradeNumber
};
}
@@ -108,11 +124,20 @@ public class SysWechatPayService : IDynamicApiController, ITransient
/// 微信支付统一下单获取Id(服务商模式) 🔖
///
[DisplayName("微信支付统一下单获取Id(服务商模式)")]
- public async Task CreatePayPartnerTransaction([FromBody] WechatPayTransactionInput input)
+ public async Task CreatePayPartnerTransaction([FromBody] WechatPayTransactionInput input)
{
+ string outTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000); // 微信需要的订单号(唯一)
+
+ //检查订单信息是否已存在(使用“商户交易单号+状态”唯一性判断)
+ var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OrderId == input.OrderId && u.OrderStatus == input.OrderStatus);
+ if (wechatPay != null)
+ {
+ outTradeNumber = wechatPay.OutTradeNumber;
+ }
+
var request = new CreatePayPartnerTransactionJsapiRequest()
{
- OutTradeNumber = DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff") + (new Random()).Next(100, 1000), // 订单号
+ OutTradeNumber = outTradeNumber,
AppId = _wechatPayOptions.AppId,
MerchantId = _wechatPayOptions.MerchantId,
SubAppId = _wechatPayOptions.AppId,
@@ -127,29 +152,31 @@ public class SysWechatPayService : IDynamicApiController, ITransient
};
var response = await _wechatTenpayClient.ExecuteCreatePayPartnerTransactionJsapiAsync(request);
if (!response.IsSuccessful())
- throw Oops.Oh(response.ErrorMessage);
-
- // 保存订单信息
- var wechatPay = new SysWechatPay()
+ throw Oops.Oh($"JSAPI 下单失败(状态码:{response.GetRawStatus()},错误代码:{response.ErrorCode},错误描述:{response.ErrorMessage})");
+ if (wechatPay == null)
{
- AppId = _wechatPayOptions.AppId,
- MerchantId = _wechatPayOptions.MerchantId,
- SubAppId = _wechatPayOptions.AppId,
- SubMerchantId = _wechatPayOptions.MerchantId,
- OutTradeNumber = request.OutTradeNumber,
- Description = input.Description,
- Attachment = input.Attachment,
- GoodsTag = input.GoodsTag,
- Total = input.Total,
- OpenId = input.OpenId,
- TransactionId = ""
- };
- await _sysWechatPayUserRep.InsertAsync(wechatPay);
+ // 保存订单信息
+ wechatPay = new SysWechatPay()
+ {
+ AppId = _wechatPayOptions.AppId,
+ MerchantId = _wechatPayOptions.MerchantId,
+ SubAppId = _wechatPayOptions.AppId,
+ SubMerchantId = _wechatPayOptions.MerchantId,
+ OutTradeNumber = request.OutTradeNumber,
+ Description = input.Description,
+ Attachment = input.Attachment,
+ GoodsTag = input.GoodsTag,
+ Total = input.Total,
+ OpenId = input.OpenId,
+ TransactionId = ""
+ };
+ await _sysWechatPayRep.InsertAsync(wechatPay);
+ }
- return new
+ return new CreatePayTransactionOutput
{
- response.PrepayId,
- request.OutTradeNumber
+ PrepayId = response.PrepayId,
+ OutTradeNumber = request.OutTradeNumber
};
}
@@ -161,7 +188,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
[DisplayName("获取支付订单详情")]
public async Task GetPayInfo(string tradeId)
{
- return await _sysWechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == tradeId);
+ return await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == tradeId);
}
///
@@ -183,7 +210,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
var callbackResource = _wechatTenpayClient.DecryptEventResource(callbackModel);
// 修改订单支付状态
- var wechatPay = await _sysWechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber
+ var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber
&& u.MerchantId == callbackResource.MerchantId);
if (wechatPay == null) return null;
//wechatPay.OpenId = callbackResource.Payer.OpenId; // 支付者标识
@@ -198,7 +225,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
wechatPay.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额
wechatPay.SuccessTime = callbackResource.SuccessTime; // 支付完成时间
- await _sysWechatPayUserRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
+ await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
return new WechatPayOutput()
{
@@ -230,7 +257,7 @@ public class SysWechatPayService : IDynamicApiController, ITransient
var callbackResource = _wechatTenpayClient.DecryptEventResource(callbackModel);
// 修改订单支付状态
- var wechatPay = await _sysWechatPayUserRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber
+ var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == callbackResource.OutTradeNumber
&& u.MerchantId == callbackResource.MerchantId);
if (wechatPay == null) return;
//wechatPay.OpenId = callbackResource.Payer.OpenId; // 支付者标识
@@ -245,7 +272,187 @@ public class SysWechatPayService : IDynamicApiController, ITransient
wechatPay.PayerTotal = callbackResource.Amount.PayerTotal; // 用户支付金额
wechatPay.SuccessTime = callbackResource.SuccessTime; // 支付完成时间
- await _sysWechatPayUserRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
+ await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
}
}
+
+ ///
+ /// 退款申请
+ /// https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/create.html
+ ///
+ ///
+ ///
+ [DisplayName("微信退款申请)")]
+ public async Task Refund(RefundRequestInput input)
+ {
+ var request = new CreateRefundDomesticRefundRequest()
+ {
+ OutTradeNumber = input.OutTradeNumber,
+ OutRefundNumber = "REFUND_" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"),
+ Amount = new CreateRefundDomesticRefundRequest.Types.Amount()
+ {
+ Total = input.Total,
+ Refund = input.Refund
+ },
+ Reason = input.Reason,
+ };
+ var response = await _wechatTenpayClient.ExecuteCreateRefundDomesticRefundAsync(request);
+
+ if (!response.IsSuccessful())
+ throw Oops.Oh($"JSAPI 退款申请失败(状态码:{response.GetRawStatus()},错误代码:{response.ErrorCode},错误描述:{response.ErrorMessage})");
+
+ var wechatRefund = await _sysWechatRefundRep.GetFirstAsync(u => u.OutTradeNumber == input.OutTradeNumber);
+ if (wechatRefund == null)
+ {
+ // 保存退款申请信息
+ wechatRefund = new SysWechatRefund()
+ {
+ TransactionId = input.OutTradeNumber,
+ OutTradeNumber = request.OutTradeNumber,
+ OutRefundNo = request.OutTradeNumber, //每笔付款只退一次,所以这里直接用付款单号
+ Reason = request.Reason,
+ Refund = input.Refund,
+ Total = input.Total,
+ //NotifyUrl = "",
+ OrderId = input.OrderId,
+ OrderStatus = input.OrderStatus,
+ MerchantGoodsId = input.MerchantGoodsId,
+ GoodsName = input.GoodsName,
+ UnitPrice = input.UnitPrice,
+ RefundAmount = input.RefundAmount,
+ RefundQuantity = input.RefundQuantity,
+ Attachment = input.Attachment,
+ Remark = input.Remark
+ };
+ await _sysWechatRefundRep.InsertAsync(wechatRefund);
+ }
+ }
+
+ ///
+ /// 查询单笔退款(通过商户退款单号)
+ /// https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/query-by-out-refund-no.html
+ ///
+ ///
+ ///
+ [DisplayName("微信查询单笔退款)")]
+ public async Task GetRefundByOutRefundNumber(string outRefundNumber)
+ {
+ var request = new GetRefundDomesticRefundByOutRefundNumberRequest()
+ {
+ OutRefundNumber = outRefundNumber
+ };
+ return await _wechatTenpayClient.ExecuteGetRefundDomesticRefundByOutRefundNumberAsync(request);
+ }
+
+ ///
+ /// 微信支付订单号查询(校正)
+ /// https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id}
+ ///
+ ///
+ ///
+ [DisplayName("微信支付订单号查询(校正)")]
+ public async Task GetPayTransactionByIdAsync(string transactionId)
+ {
+ var request = new GetPayTransactionByIdRequest()
+ {
+ MerchantId = _wechatPayOptions.MerchantId,
+ TransactionId = transactionId,
+ WechatpayCertificateSerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber
+ };
+ var response = await _wechatTenpayClient.ExecuteGetPayTransactionByIdAsync(request);
+ if (response.TradeState == "SUCCESS")
+ {
+ // 修正订单支付状态
+ var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.TransactionId == transactionId && u.MerchantId == request.MerchantId);
+ if (wechatPay != null && string.IsNullOrEmpty(wechatPay.TradeState))
+ {
+ wechatPay.TransactionId = response.TransactionId; // 支付订单号
+ wechatPay.TradeType = response.TradeType; // 交易类型
+ wechatPay.TradeState = response.TradeState; // 交易状态
+ wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述
+ wechatPay.BankType = response.BankType; // 付款银行类型
+ wechatPay.Total = response.Amount.Total; // 订单总金额
+ wechatPay.PayerTotal = response.Amount.PayerTotal; // 用户支付金额
+ wechatPay.SuccessTime = response.SuccessTime; // 支付完成时间
+
+ await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
+ return wechatPay.Adapt();
+ }
+ }
+ return response.Adapt();
+ }
+
+ ///
+ /// 商户订单号查询(校正)
+ /// https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}
+ ///
+ ///
+ ///
+ [DisplayName("微信商户订单号查询(校正)")]
+ public async Task GetPayTransactionByOutTradeNumberAsync(string outTradeNumber)
+ {
+ var request = new GetPayTransactionByOutTradeNumberRequest()
+ {
+ MerchantId = _wechatPayOptions.MerchantId,
+ OutTradeNumber = outTradeNumber,
+ WechatpayCertificateSerialNumber = _wechatPayOptions.MerchantCertificateSerialNumber
+ };
+ var response = await _wechatTenpayClient.ExecuteGetPayTransactionByOutTradeNumberAsync(request);
+ if (response.TradeState == "SUCCESS")
+ {
+ // 修正订单支付状态
+ var wechatPay = await _sysWechatPayRep.GetFirstAsync(u => u.OutTradeNumber == outTradeNumber && u.MerchantId == request.MerchantId);
+ if (wechatPay != null && string.IsNullOrEmpty(wechatPay.TradeState))
+ {
+ wechatPay.TransactionId = response.TransactionId; // 支付订单号
+ wechatPay.TradeType = response.TradeType; // 交易类型
+ wechatPay.TradeState = response.TradeState; // 交易状态
+ wechatPay.TradeStateDescription = response.TradeStateDescription; // 交易状态描述
+ wechatPay.BankType = response.BankType; // 付款银行类型
+ wechatPay.Total = response.Amount.Total; // 订单总金额
+ wechatPay.PayerTotal = response.Amount.PayerTotal; // 用户支付金额
+ wechatPay.SuccessTime = response.SuccessTime; // 支付完成时间
+ await _sysWechatPayRep.AsUpdateable(wechatPay).IgnoreColumns(true).ExecuteCommandAsync();
+ return wechatPay.Adapt();
+ }
+ }
+ return response.Adapt();
+ }
+
+ ///
+ /// 获取支付记录列表(分页)
+ ///
+ /// PageSysWechatPayInput
+ ///
+ [DisplayName("获取支付记录列表(分页)")]
+ public async Task> PageAsync(PageSysWechatPayInput input)
+ {
+ var query = _sysWechatPayRep.AsQueryable()
+ .WhereIF(input.OrderId > 0, u => u.OrderId == input.OrderId)
+ .WhereIF(input.OrderStatus > 0, u => u.OrderStatus == input.OrderStatus)
+ .WhereIF(!string.IsNullOrWhiteSpace(input.OutTradeNumber), u => u.OutTradeNumber.Contains(input.OutTradeNumber.Trim()));
+
+ if (input.SuccessTimeRange != null && input.SuccessTimeRange.Count > 0)
+ {
+ DateTime? start = input.SuccessTimeRange[0];
+ query = query.WhereIF(start.HasValue, u => u.SuccessTime > start);
+ if (input.SuccessTimeRange.Count > 1 && input.SuccessTimeRange[1].HasValue)
+ {
+ var end = input.SuccessTimeRange[1].Value.AddDays(1);
+ query = query.Where(u => u.SuccessTime < end);
+ }
+ }
+ if (input.ExpireTimeRange != null && input.ExpireTimeRange.Count > 0)
+ {
+ DateTime? start = input.ExpireTimeRange[0];
+ query = query.WhereIF(start.HasValue, u => u.ExpireTime > start);
+ if (input.ExpireTimeRange.Count > 1 && input.ExpireTimeRange[1].HasValue)
+ {
+ var end = input.ExpireTimeRange[1].Value.AddDays(1);
+ query = query.Where(u => u.ExpireTime < end);
+ }
+ }
+ query = query.OrderByDescending(u => u.CreateTime);
+ return await query.ToPagedListAsync(input.Page, input.PageSize);
+ }
}
\ No newline at end of file