|
|
@ -23,7 +23,7 @@ using Microsoft.AspNetCore.Authorization;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using Mapster;
|
|
|
|
using Mapster;
|
|
|
|
using Furion.FriendlyException;
|
|
|
|
using Furion.FriendlyException;
|
|
|
|
|
|
|
|
using Senparc.CO2NET.Cache.Redis;
|
|
|
|
|
|
|
|
|
|
|
|
namespace GDZZ.Application.Service.WXPay
|
|
|
|
namespace GDZZ.Application.Service.WXPay
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -42,7 +42,7 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
|
|
|
|
|
|
|
|
private readonly SqlSugarRepository<MiniRecharge> rechargeRep; //充值仓储
|
|
|
|
private readonly SqlSugarRepository<MiniRecharge> rechargeRep; //充值仓储
|
|
|
|
private readonly SqlSugarRepository<MiniPayTake> payTakeRep; //支付仓储
|
|
|
|
private readonly SqlSugarRepository<MiniPayTake> payTakeRep; //支付仓储
|
|
|
|
|
|
|
|
private readonly SqlSugarRepository<ReFund> refundRep; //退款仓储
|
|
|
|
|
|
|
|
|
|
|
|
private readonly WechatOAuth _wechatOAuth; //微信权限服务
|
|
|
|
private readonly WechatOAuth _wechatOAuth; //微信权限服务
|
|
|
|
private readonly IHttpContextAccessor _httpContextAccessor; //http服务
|
|
|
|
private readonly IHttpContextAccessor _httpContextAccessor; //http服务
|
|
|
@ -66,11 +66,13 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
SqlSugarRepository<SeIF> Self,
|
|
|
|
SqlSugarRepository<SeIF> Self,
|
|
|
|
SqlSugarRepository<MiniRecharge> rechargeRep,
|
|
|
|
SqlSugarRepository<MiniRecharge> rechargeRep,
|
|
|
|
SqlSugarRepository<MiniPayTake> payTakeRep,
|
|
|
|
SqlSugarRepository<MiniPayTake> payTakeRep,
|
|
|
|
|
|
|
|
SqlSugarRepository<ReFund> refundRep,
|
|
|
|
WechatOAuth wechatOAuth,
|
|
|
|
WechatOAuth wechatOAuth,
|
|
|
|
IHttpContextAccessor _httpContextAccessor,
|
|
|
|
IHttpContextAccessor _httpContextAccessor,
|
|
|
|
IEventPublisher eventPublisher)
|
|
|
|
IEventPublisher eventPublisher)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
this.self = Self;
|
|
|
|
this.self = Self;
|
|
|
|
|
|
|
|
this.refundRep= refundRep;
|
|
|
|
this.balance = balance;
|
|
|
|
this.balance = balance;
|
|
|
|
this.Baseuser = Baseuser;
|
|
|
|
this.Baseuser = Baseuser;
|
|
|
|
this.ComsumeRep = ComsumeRep;
|
|
|
|
this.ComsumeRep = ComsumeRep;
|
|
|
@ -158,6 +160,10 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 小程序支付
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
///微信小程序支付
|
|
|
|
///微信小程序支付
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
@ -218,6 +224,7 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// 微信小程序支付回调
|
|
|
|
/// 微信小程序支付回调
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
@ -226,18 +233,16 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
[Route("/Mini/NotifyUrl")]
|
|
|
|
[Route("/Mini/NotifyUrl")]
|
|
|
|
[UnifyResult(typeof(string))]
|
|
|
|
[UnifyResult(typeof(string))]
|
|
|
|
[AllowAnonymous]
|
|
|
|
[AllowAnonymous]
|
|
|
|
public async Task<string> NotifyUrl()
|
|
|
|
public async Task<ActionResult> NotifyUrl()
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ResponseHandler resHandler = new ResponseHandler(this._httpContextAccessor.HttpContext);
|
|
|
|
ResponseHandler resHandler = new ResponseHandler(this._httpContextAccessor.HttpContext);
|
|
|
|
|
|
|
|
ContentResult content = new ContentResult();
|
|
|
|
string return_code = resHandler.GetParameter("return_code");
|
|
|
|
string return_code = resHandler.GetParameter("return_code");
|
|
|
|
string return_msg = resHandler.GetParameter("return_msg");
|
|
|
|
string return_msg = resHandler.GetParameter("return_msg");
|
|
|
|
|
|
|
|
|
|
|
|
//var res = "";
|
|
|
|
|
|
|
|
resHandler.SetKey(Config.SenparcWeixinSetting.TenPayV3_Key);
|
|
|
|
resHandler.SetKey(Config.SenparcWeixinSetting.TenPayV3_Key);
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
//验证请求是否从微信发过来(安全)
|
|
|
|
//验证请求是否从微信发过来(安全)
|
|
|
|
if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS")
|
|
|
|
if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS")
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -273,15 +278,155 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
content.Content = string.Format(@"<xml>
|
|
|
|
|
|
|
|
<return_code><![CDATA[{0}]]></return_code>
|
|
|
|
|
|
|
|
<return_msg><![CDATA[{1}]]></return_msg>
|
|
|
|
|
|
|
|
</xml>", return_code, return_msg);
|
|
|
|
|
|
|
|
this.SendTemplate(0, return_code, resHandler);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
content.Content = "回调失败";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.LogRecord(resHandler);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
content.Content = ex.Message;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return content;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 小程序退款
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
///微信小程序退款
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
|
|
[HttpPost]
|
|
|
|
|
|
|
|
[Route("Mini/v1/refund")]
|
|
|
|
|
|
|
|
public async Task<dynamic> WxRefund(WxRefundInput wxRefundInput)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//查询订单
|
|
|
|
|
|
|
|
var order = this.payTakeRep.FirstOrDefault(x => x.OrderId == wxRefundInput.OrderID);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (order == null)
|
|
|
|
|
|
|
|
return new Exception("查询无此订单,退款失败");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成退款单
|
|
|
|
|
|
|
|
var res = await this.refundRep.InsertReturnEntityAsync(new ReFund()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
State = RefundStatusEnum.REDIND,
|
|
|
|
|
|
|
|
Amount = order.PaymentMoney,
|
|
|
|
|
|
|
|
Message = "退款审核中",
|
|
|
|
|
|
|
|
PayNo = order.Id.ToString(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
if (res == null)
|
|
|
|
|
|
|
|
return new Exception("生成退款单失败");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string notifyUrl = string.Format(Config.SenparcWeixinSetting.TenPayV3_TenpayNotify, "RefundNotifyUrl");
|
|
|
|
|
|
|
|
string opUserId = Config.SenparcWeixinSetting.TenPayV3_MchId;
|
|
|
|
|
|
|
|
//退款金额
|
|
|
|
|
|
|
|
int refundFee = (int)(order.PaymentMoney * 100);
|
|
|
|
|
|
|
|
//支付时的总金额
|
|
|
|
|
|
|
|
int totalFee = (int)(order.PaymentMoney * 100);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string outRefundNo = res.Id.ToString();//新退款单号
|
|
|
|
|
|
|
|
string outTradeNo = order.OrderId.ToString();
|
|
|
|
|
|
|
|
var nonceStr = TenPayV3Util.GetNoncestr();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var dataInfo = new TenPayV3RefundRequestData(Config.SenparcWeixinSetting.WxOpenAppId, Config.SenparcWeixinSetting.TenPayV3_MchId,
|
|
|
|
|
|
|
|
Config.SenparcWeixinSetting.TenPayV3_Key, null, nonceStr, null, outTradeNo, outRefundNo, totalFee, refundFee, opUserId, null,
|
|
|
|
|
|
|
|
notifyUrl: notifyUrl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
message = "退款请求完成",
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// 退款回调
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
[HttpPost("RefundNotifyUrl")]
|
|
|
|
|
|
|
|
[UnifyResult(typeof(string))]
|
|
|
|
|
|
|
|
public async Task<ActionResult> RefundNotifyUrl()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ResponseHandler resHandler = new ResponseHandler(this._httpContextAccessor.HttpContext);
|
|
|
|
|
|
|
|
ContentResult content = new ContentResult();
|
|
|
|
|
|
|
|
string return_code = resHandler.GetParameter("return_code");
|
|
|
|
|
|
|
|
string return_msg = resHandler.GetParameter("return_msg");
|
|
|
|
|
|
|
|
var mch_key = Senparc.Weixin.Config.SenparcWeixinSetting.TenPayV3_Key;
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (return_code.ToUpper() == "SUCCESS")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
string req_info = resHandler.GetParameter("req_info");
|
|
|
|
|
|
|
|
var decodeReqInfo = TenPayV3Util.DecodeRefundReqInfo(req_info, mch_key);
|
|
|
|
|
|
|
|
var decodeDoc = System.Xml.Linq.XDocument.Parse(decodeReqInfo);
|
|
|
|
|
|
|
|
var refundNotifyXml = decodeDoc.Serialize();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//获取接口中需要用到的信息
|
|
|
|
|
|
|
|
string out_trade_no = decodeDoc.Root.Element("out_trade_no").Value;
|
|
|
|
|
|
|
|
string transaction_id = decodeDoc.Root.Element("transaction_id").Value;
|
|
|
|
|
|
|
|
string refund_id = decodeDoc.Root.Element("refund_id").Value;
|
|
|
|
|
|
|
|
int total_fee = int.Parse(decodeDoc.Root.Element("total_fee").Value);
|
|
|
|
|
|
|
|
int refund_fee = int.Parse(decodeDoc.Root.Element("refund_fee").Value);
|
|
|
|
|
|
|
|
string out_refund_no = decodeDoc.Root.Element("out_refund_no").Value;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var refun = this.refundRep.FirstOrDefault(x => x.PayNo == out_refund_no);
|
|
|
|
|
|
|
|
refun.PayNo = out_refund_no;
|
|
|
|
|
|
|
|
refun.Amount = ((float)refund_fee.ParseToInt() / 100).ParseToDecimal();
|
|
|
|
|
|
|
|
refun.Message = "退款完成";
|
|
|
|
|
|
|
|
refun.RefundID = refund_id;
|
|
|
|
|
|
|
|
refun.refundNo = out_refund_no;
|
|
|
|
|
|
|
|
refun.TransactionNo = transaction_id;
|
|
|
|
|
|
|
|
refun.State = RefundStatusEnum.RESUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.refundRep.Update(refun) > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
content.Content = string.Format(@"<xml>
|
|
|
|
|
|
|
|
<return_code><![CDATA[{0}]]></return_code>
|
|
|
|
|
|
|
|
<return_msg><![CDATA[{1}]]></return_msg>
|
|
|
|
|
|
|
|
</xml>", return_code, return_msg);
|
|
|
|
|
|
|
|
return content;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Console.WriteLine("回调失败");
|
|
|
|
content.Content = "回调处理失败!";
|
|
|
|
//res = "wrong";//错误的订单处理
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
content.Content = e.Message;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return content;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 这里可以进行订单处理的逻辑 */
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 附加服务
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void SendTemplate(int type, string return_code, ResponseHandler resHandler)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
//发送支付成功的模板消息
|
|
|
|
//发送支付成功的模板消息
|
|
|
|
try
|
|
|
|
try
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -297,6 +442,16 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString());
|
|
|
|
Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void LogRecord(ResponseHandler resHandler)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
#region 记录日志
|
|
|
|
#region 记录日志
|
|
|
|
|
|
|
|
|
|
|
@ -317,21 +472,7 @@ namespace GDZZ.Application.Service.WXPay
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string xml = string.Format(@"<xml>
|
|
|
|
|
|
|
|
<return_code><![CDATA[{0}]]></return_code>
|
|
|
|
|
|
|
|
<return_msg><![CDATA[{1}]]></return_msg>
|
|
|
|
|
|
|
|
</xml>", return_code, return_msg);
|
|
|
|
|
|
|
|
return xml;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
|
|
|
|
|
|
|
|
throw;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|