272 lines
9.8 KiB
C#
272 lines
9.8 KiB
C#
|
|
using Hncore.Infrastructure.Common;
|
|||
|
|
using Hncore.Infrastructure.Extension;
|
|||
|
|
using Hncore.Infrastructure.Serializer;
|
|||
|
|
using Hncore.Infrastructure.WebApi;
|
|||
|
|
using Hncore.Pass.PaymentCenter.Domain;
|
|||
|
|
using Hncore.Pass.PaymentCenter.Pay.WxPay;
|
|||
|
|
using Hncore.Pass.PaymentCenter.Response;
|
|||
|
|
using Hncore.Pass.PaymentCenter.Response.PaymentRecord;
|
|||
|
|
using Hncore.Pass.PaymentCenter.Service;
|
|||
|
|
using Hncore.Pass.PaymentCenter.WeiFuTong;
|
|||
|
|
using Hncore.Pass.PaymentCenter.WeiFuTong.Notify;
|
|||
|
|
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
|||
|
|
using Microsoft.AspNetCore.Authorization;
|
|||
|
|
using Microsoft.AspNetCore.Mvc;
|
|||
|
|
using Microsoft.EntityFrameworkCore;
|
|||
|
|
using Microsoft.Extensions.Configuration;
|
|||
|
|
using System;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
|
|||
|
|
namespace Hncore.Pass.PaymentCenter.Controllers
|
|||
|
|
{
|
|||
|
|
[ApiVersion("1.0")]
|
|||
|
|
[Route("api/paymentcenter/v{version:apiVersion}/Payment/[action]")]
|
|||
|
|
public class PaymentController : PaymentControllerBase
|
|||
|
|
{
|
|||
|
|
private PaymentRecordService m_PaymentRecordService;
|
|||
|
|
private WeiFuTongService m_WeiFuTongService;
|
|||
|
|
private InternalNotifySerivce m_InternalNotifySerivce;
|
|||
|
|
|
|||
|
|
private WxPayClient m_WxPayClient { get; set; }
|
|||
|
|
|
|||
|
|
public PaymentController(
|
|||
|
|
PaymentRecordService _PaymentRecordService
|
|||
|
|
, InternalNotifySerivce internalNotifySerivce
|
|||
|
|
, TenantService _TenantService
|
|||
|
|
, WxPayClient _WxPayClient
|
|||
|
|
, WeiFuTongService weiFuTongService
|
|||
|
|
, IConfiguration _Configuration) : base(_TenantService, _Configuration)
|
|||
|
|
{
|
|||
|
|
// m_WeiFuTongService = weiFuTongService;
|
|||
|
|
m_PaymentRecordService = _PaymentRecordService;
|
|||
|
|
m_InternalNotifySerivce = internalNotifySerivce;
|
|||
|
|
m_WxPayClient = _WxPayClient;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private async Task<QueryOrderResponse> QueryOrderByPaymentRecordAsync(PaymentRecord paymentRecord)
|
|||
|
|
{
|
|||
|
|
QueryOrderResponse result = null;
|
|||
|
|
|
|||
|
|
//威富通的订单
|
|||
|
|
if (paymentRecord.PaymentChannel == PaymentChannel.WeiFuTong
|
|||
|
|
|| paymentRecord.PaymentChannel == PaymentChannel.QuanFuTong
|
|||
|
|
&& paymentRecord.FromPos==0)
|
|||
|
|
{
|
|||
|
|
var mchInfo = await GetMchInfoAsync(paymentRecord.TenantId
|
|||
|
|
, paymentRecord.StoreId
|
|||
|
|
, paymentRecord.PaymentChannel);
|
|||
|
|
|
|||
|
|
result = await m_WeiFuTongService.QueryOrderAsync(paymentRecord, mchInfo);
|
|||
|
|
|
|||
|
|
await UofCommitAsync();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 通用订单查询
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="orderNo"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
[HttpGet]
|
|||
|
|
public async Task<ApiResult> QueryOrder(string orderNo = "", int? recordId = 0)
|
|||
|
|
{
|
|||
|
|
PaymentRecord paymentRecord = null;
|
|||
|
|
|
|||
|
|
if (recordId == null || recordId == 0)
|
|||
|
|
{
|
|||
|
|
paymentRecord = await m_PaymentRecordService.Query(false)
|
|||
|
|
.OrderByDescending(t => t.Id)
|
|||
|
|
.FirstOrDefaultAsync(t => t.OrderId == orderNo);
|
|||
|
|
}
|
|||
|
|
else if (recordId > 0)
|
|||
|
|
{
|
|||
|
|
paymentRecord = await m_PaymentRecordService.GetById(recordId.ToInt());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CheckHelper.NotNull(paymentRecord, "支付记录不存在");
|
|||
|
|
|
|||
|
|
var result = await QueryOrderByPaymentRecordAsync(paymentRecord);
|
|||
|
|
|
|||
|
|
if (result == null)
|
|||
|
|
{
|
|||
|
|
return Error("未知的支付渠道");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return Success(result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 根据orderid查询一条支付记录
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="orderId"></param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
[HttpGet]
|
|||
|
|
public async Task<ApiResult> GetDetail([FromQuery] string orderId)
|
|||
|
|
{
|
|||
|
|
return Success(await QueryPaymentRecordByOrderIdResponse.Query(
|
|||
|
|
m_PaymentRecordService.Query(false)
|
|||
|
|
, orderId)
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 威富通、全付通 接收通知
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
[HttpPost]
|
|||
|
|
public async Task<string> HWCNotify()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string xml = "";
|
|||
|
|
|
|||
|
|
if (Request.Body.CanSeek)
|
|||
|
|
{
|
|||
|
|
Request.Body.Position = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
using (System.IO.StreamReader reader = new System.IO.StreamReader(Request.Body))
|
|||
|
|
{
|
|||
|
|
xml = reader.ReadToEnd();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LogHelper.Trace("收到威富通支付通知,原始数据:", $"{xml}");
|
|||
|
|
|
|||
|
|
|
|||
|
|
var notifyEntity = XML.XmlDeserialize<NotifyResponse>(xml);
|
|||
|
|
|
|||
|
|
// 给支付平台的订单号为支付记录id
|
|||
|
|
int paymentRecordId = notifyEntity.OutTradeNo.ToInt();
|
|||
|
|
|
|||
|
|
var paymentRecord = await m_PaymentRecordService.GetById(paymentRecordId);
|
|||
|
|
|
|||
|
|
var mchInfo = await GetMchInfoAsync(paymentRecord.TenantId, paymentRecord.StoreId,
|
|||
|
|
paymentRecord.PaymentChannel);
|
|||
|
|
|
|||
|
|
Util.CheckSignFromXml(xml, mchInfo);
|
|||
|
|
|
|||
|
|
if (notifyEntity.PayResult == 0) //支付成功
|
|||
|
|
{
|
|||
|
|
paymentRecord.SetPaySuccessed(notifyEntity.TransactionId, notifyEntity.GetPaySuccessTime());
|
|||
|
|
paymentRecord.SetPaymentTypeFromTradeType(notifyEntity.TradeType);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
paymentRecord.SetPayFailed();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
await m_PaymentRecordService.Update(paymentRecord);
|
|||
|
|
|
|||
|
|
var status = notifyEntity.PayResult == 0 ? "成功" : "失败";
|
|||
|
|
|
|||
|
|
|
|||
|
|
LogHelper.Info("威富通回调信息:",
|
|||
|
|
$"支付记录Id:{paymentRecord.Id}\n订单号:{paymentRecord.OrderId}\n交易号:{paymentRecord.TransactionId}\n支付状态:{status}\n发起时间:{paymentRecord.RequestTime.Format("yyyy-MM-dd HH:mm:ss")}\n付款成功时间:{notifyEntity.GetPaySuccessTime().Format("yyyy-MM-dd HH:mm:ss")}\n收到通知时间:{DateTime.Now.Format("yyyy-MM-dd HH:mm:ss")}\n总用时:{(DateTime.Now - paymentRecord.RequestTime).TotalSeconds}秒");
|
|||
|
|
|
|||
|
|
if (notifyEntity.PayResult == 0)
|
|||
|
|
{
|
|||
|
|
//发起内部通知
|
|||
|
|
await m_InternalNotifySerivce.Notify(paymentRecord);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception e)
|
|||
|
|
{
|
|||
|
|
LogHelper.Error("威富通通知处理失败", e);
|
|||
|
|
|
|||
|
|
return "fail";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return "success";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 微信支付回调 接收通知
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
[HttpPost, AllowAnonymous]
|
|||
|
|
public async Task<string> Notify()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
string xml = "";
|
|||
|
|
LogHelper.Trace("微信支付回调开始","Notify");
|
|||
|
|
if (Request.Body.CanSeek)
|
|||
|
|
{
|
|||
|
|
Request.Body.Position = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
using (System.IO.StreamReader reader = new System.IO.StreamReader(Request.Body))
|
|||
|
|
{
|
|||
|
|
xml = reader.ReadToEnd();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LogHelper.Trace("微信支付回调,原始数据:", $"{xml}");
|
|||
|
|
|
|||
|
|
WxPayChecker payData = new WxPayChecker();
|
|||
|
|
|
|||
|
|
payData.FromXmlNoCheckSign(xml);
|
|||
|
|
|
|||
|
|
if (!payData.IsSet("out_trade_no"))
|
|||
|
|
{
|
|||
|
|
return FailXml();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 给支付平台的订单号为支付记录id
|
|||
|
|
string orderId = payData["out_trade_no"];
|
|||
|
|
|
|||
|
|
string TransactionId = payData["transaction_id"];
|
|||
|
|
|
|||
|
|
var paymentRecord = await m_PaymentRecordService.GetOneByOrderId(orderId);
|
|||
|
|
if (paymentRecord.TransactionId.NotHas())
|
|||
|
|
{
|
|||
|
|
paymentRecord.TransactionId = TransactionId;
|
|||
|
|
await m_PaymentRecordService.Update(paymentRecord);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var mchInfo = await GetMchInfoAsync(paymentRecord.TenantId, paymentRecord.StoreId,
|
|||
|
|
paymentRecord.PaymentChannel);
|
|||
|
|
payData.MchKey = mchInfo.Key;
|
|||
|
|
|
|||
|
|
var queryRet = await m_WxPayClient.OrderQuery(new WxJsPayOrderQueryRequest()
|
|||
|
|
{
|
|||
|
|
AppId = paymentRecord.Appid,
|
|||
|
|
MchId = mchInfo.MchId,
|
|||
|
|
NonceStr = payData.GenerateNonceStr(),
|
|||
|
|
TransactionId = TransactionId
|
|||
|
|
}, mchInfo);
|
|||
|
|
if (!queryRet) return FailXml();
|
|||
|
|
|
|||
|
|
if (!payData.CheckSign()) return FailXml();
|
|||
|
|
|
|||
|
|
paymentRecord.PaymentStatus = PaymentStatus.OkPay;
|
|||
|
|
paymentRecord.UpdateTime = DateTime.Now;
|
|||
|
|
paymentRecord.PaymentCompletionTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|||
|
|
await m_PaymentRecordService.Update(paymentRecord);
|
|||
|
|
//发起内部通知
|
|||
|
|
await m_InternalNotifySerivce.Notify(paymentRecord);
|
|||
|
|
}
|
|||
|
|
catch (Exception e)
|
|||
|
|
{
|
|||
|
|
LogHelper.Error("微信支付通知处理失败", e);
|
|||
|
|
|
|||
|
|
return FailXml();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return SuccessXml();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public string FailXml()
|
|||
|
|
{
|
|||
|
|
return "<xml><return_code>FAIL</return_code> </xml>";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private string SuccessXml()
|
|||
|
|
{
|
|||
|
|
return "<xml><return_code>SUCCESS</return_code> </xml>";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|