忽略dll文件git
This commit is contained in:
@@ -1,66 +1,66 @@
|
||||
using Alipay.AopSdk.Core;
|
||||
using Alipay.AopSdk.Core.Domain;
|
||||
using Alipay.AopSdk.Core.Request;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.AliPay
|
||||
{
|
||||
public class AliPayClient
|
||||
{
|
||||
public static readonly string url = "https://api.mch.weixin.qq.com";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AliPayClient(IHttpClientFactory _HttpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = _HttpClientFactory;
|
||||
}
|
||||
|
||||
public async Task<string> PcPayCreateOrderAsync(WxJsPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
|
||||
var APP_ID = "";
|
||||
var APP_PRIVATE_KEY = "";
|
||||
var CHARSET = "";
|
||||
var ALIPAY_PUBLIC_KEY = "";
|
||||
|
||||
// 组装业务参数model
|
||||
|
||||
|
||||
AlipayTradePagePayModel model = new AlipayTradePagePayModel
|
||||
{
|
||||
Body = request.Body,
|
||||
Subject = request.Body,
|
||||
TotalAmount = request.TotalFee.ToString(),
|
||||
OutTradeNo = "",
|
||||
ProductCode = "FAST_INSTANT_TRADE_PAY"//QUICK_WAP_PAY
|
||||
};
|
||||
|
||||
AlipayTradePagePayRequest aliRequest = new AlipayTradePagePayRequest();
|
||||
// 设置同步回调地址
|
||||
// aliRequest.SetReturnUrl($"http://{Request.Host}/Pay/Callback");
|
||||
// 设置异步通知接收地址
|
||||
aliRequest.SetNotifyUrl("");
|
||||
// 将业务model载入到request
|
||||
aliRequest.SetBizModel(model);
|
||||
|
||||
var _aopClient = new DefaultAopClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY);
|
||||
|
||||
var response = _aopClient.PageExecute(aliRequest);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> H5PayCreateOrderAsync(WxH5PayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
//AlipayTradeWapPayModel
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
using Alipay.AopSdk.Core;
|
||||
using Alipay.AopSdk.Core.Domain;
|
||||
using Alipay.AopSdk.Core.Request;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.AliPay
|
||||
{
|
||||
public class AliPayClient
|
||||
{
|
||||
public static readonly string url = "https://api.mch.weixin.qq.com";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AliPayClient(IHttpClientFactory _HttpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = _HttpClientFactory;
|
||||
}
|
||||
|
||||
public async Task<string> PcPayCreateOrderAsync(WxJsPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
|
||||
var APP_ID = "";
|
||||
var APP_PRIVATE_KEY = "";
|
||||
var CHARSET = "";
|
||||
var ALIPAY_PUBLIC_KEY = "";
|
||||
|
||||
// 组装业务参数model
|
||||
|
||||
|
||||
AlipayTradePagePayModel model = new AlipayTradePagePayModel
|
||||
{
|
||||
Body = request.Body,
|
||||
Subject = request.Body,
|
||||
TotalAmount = request.TotalFee.ToString(),
|
||||
OutTradeNo = "",
|
||||
ProductCode = "FAST_INSTANT_TRADE_PAY"//QUICK_WAP_PAY
|
||||
};
|
||||
|
||||
AlipayTradePagePayRequest aliRequest = new AlipayTradePagePayRequest();
|
||||
// 设置同步回调地址
|
||||
// aliRequest.SetReturnUrl($"http://{Request.Host}/Pay/Callback");
|
||||
// 设置异步通知接收地址
|
||||
aliRequest.SetNotifyUrl("");
|
||||
// 将业务model载入到request
|
||||
aliRequest.SetBizModel(model);
|
||||
|
||||
var _aopClient = new DefaultAopClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY);
|
||||
|
||||
var response = _aopClient.PageExecute(aliRequest);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> H5PayCreateOrderAsync(WxH5PayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
//AlipayTradeWapPayModel
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.AliJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 支付宝支付窗支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class AliJsPayRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 买家支付宝账号,和buger_id不能同时为空
|
||||
/// </summary>
|
||||
[XmlElement("buyer_logon_id")]
|
||||
public string BuyerLogonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 买家支付宝用户ID,和buyer_logon_id不能同时
|
||||
/// </summary>
|
||||
[XmlElement("buyer_id")]
|
||||
public string BuyerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
[XmlElement("notify_url")] public string NotifyUrl { get; set; }
|
||||
|
||||
public AliJsPayRequest() : base("pay.alipay.jspay")
|
||||
{
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.AliJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 支付宝支付窗支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class AliJsPayRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 买家支付宝账号,和buger_id不能同时为空
|
||||
/// </summary>
|
||||
[XmlElement("buyer_logon_id")]
|
||||
public string BuyerLogonId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 买家支付宝用户ID,和buyer_logon_id不能同时
|
||||
/// </summary>
|
||||
[XmlElement("buyer_id")]
|
||||
public string BuyerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
[XmlElement("notify_url")] public string NotifyUrl { get; set; }
|
||||
|
||||
public AliJsPayRequest() : base("pay.alipay.jspay")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.AliJsPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class AliJsPayResponse: WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// JSON字符串,自行唤起支付宝钱包支付
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.AliJsPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class AliJsPayResponse: WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// JSON字符串,自行唤起支付宝钱包支付
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,45 @@
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.AliJsPay;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class AliJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 支付宝支付窗支付下单
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<AliJsPayResponse> AliJsPayCreateOrderAsync(this WeiFuTongClient weiFuTongClient
|
||||
, AliJsPayRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
LogHelper.Trace($"威富通-支付宝支付窗支付下单", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<AliJsPayResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.AliJsPay;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class AliJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 支付宝支付窗支付下单
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<AliJsPayResponse> AliJsPayCreateOrderAsync(this WeiFuTongClient weiFuTongClient
|
||||
, AliJsPayRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
LogHelper.Trace($"威富通-支付宝支付窗支付下单", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<AliJsPayResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,56 @@
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.QrPay;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class QrPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 扫码支付下单
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<QrPayCreateOrderResponse> QrPayCreateOrderAsync(this WeiFuTongClient weiFuTongClient
|
||||
, QrPayCreateOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
string target = "";
|
||||
|
||||
if (request.Service == "pay.weixin.native")
|
||||
{
|
||||
target = "微信";
|
||||
}
|
||||
else if (request.Service == "pay.alipay.native")
|
||||
{
|
||||
target = "支付宝";
|
||||
}
|
||||
|
||||
LogHelper.Trace($"威富通-{target}扫码支付下单", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<QrPayCreateOrderResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.QrPay;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class QrPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 扫码支付下单
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<QrPayCreateOrderResponse> QrPayCreateOrderAsync(this WeiFuTongClient weiFuTongClient
|
||||
, QrPayCreateOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
string target = "";
|
||||
|
||||
if (request.Service == "pay.weixin.native")
|
||||
{
|
||||
target = "微信";
|
||||
}
|
||||
else if (request.Service == "pay.alipay.native")
|
||||
{
|
||||
target = "支付宝";
|
||||
}
|
||||
|
||||
LogHelper.Trace($"威富通-{target}扫码支付下单", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<QrPayCreateOrderResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.QueryOrder;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class QueryOrderExt
|
||||
{
|
||||
/// <summary>
|
||||
/// 支付订单查询
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WeiFuTongQueryOrderResponse> QueryOrderAsync(this WeiFuTongClient weiFuTongClient
|
||||
, WeiFuTongQueryOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
//LogHelper.Trace("威富通支付订单查询", log.ToString());
|
||||
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new HttpException(response.StatusCode) {Content = resText};
|
||||
}
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
return XML.XmlDeserialize<WeiFuTongQueryOrderResponse>(resText);
|
||||
}
|
||||
}
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.QueryOrder;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class QueryOrderExt
|
||||
{
|
||||
/// <summary>
|
||||
/// 支付订单查询
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WeiFuTongQueryOrderResponse> QueryOrderAsync(this WeiFuTongClient weiFuTongClient
|
||||
, WeiFuTongQueryOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
//LogHelper.Trace("威富通支付订单查询", log.ToString());
|
||||
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new HttpException(response.StatusCode) {Content = resText};
|
||||
}
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
return XML.XmlDeserialize<WeiFuTongQueryOrderResponse>(resText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +1,81 @@
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.Refund;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class RefundExt
|
||||
{
|
||||
/// <summary>
|
||||
/// 退款请求
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WeiFuTongRefundResponse> RefundAsync(this WeiFuTongClient weiFuTongClient,
|
||||
WeiFuTongRefundRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
LogHelper.Trace($"威富通发起退款", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<WeiFuTongRefundResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退款查询
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WeiFuTongRefundQueryResponse> QueryRefundAsync(this WeiFuTongClient weiFuTongClient,
|
||||
WeiFuTongRefundQueryRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
//LogHelper.Trace($"威富通-退款查询", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<WeiFuTongRefundQueryResponse>(resText).ParseItemsFromXml(resText);
|
||||
|
||||
if (!(res.IsCancel() || res.IsNotExists()) && res.HasError())
|
||||
{
|
||||
res.HandleError();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.Refund;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class RefundExt
|
||||
{
|
||||
/// <summary>
|
||||
/// 退款请求
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WeiFuTongRefundResponse> RefundAsync(this WeiFuTongClient weiFuTongClient,
|
||||
WeiFuTongRefundRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
LogHelper.Trace($"威富通发起退款", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<WeiFuTongRefundResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退款查询
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WeiFuTongRefundQueryResponse> QueryRefundAsync(this WeiFuTongClient weiFuTongClient,
|
||||
WeiFuTongRefundQueryRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
//LogHelper.Trace($"威富通-退款查询", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<WeiFuTongRefundQueryResponse>(resText).ParseItemsFromXml(resText);
|
||||
|
||||
if (!(res.IsCancel() || res.IsNotExists()) && res.HasError())
|
||||
{
|
||||
res.HandleError();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,56 @@
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付下单
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>need_query为Y时需要轮询查询支付状态,不为Y则支付成功</returns>
|
||||
public static async Task<SwipeCardCreateOrderResponse> SwipeCardCreateOrderAsync(
|
||||
this WeiFuTongClient weiFuTongClient
|
||||
, SwipeCardCreateOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
LogHelper.Trace("威富通-刷卡支付下单", log.ToString());
|
||||
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new HttpException(response.StatusCode) {Content = resText};
|
||||
}
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<SwipeCardCreateOrderResponse>(resText);
|
||||
|
||||
if (res.HasError() && res.NeedQuery != "Y" && res.NeedQuery != "")
|
||||
{
|
||||
res.HandleError();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付下单
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns>need_query为Y时需要轮询查询支付状态,不为Y则支付成功</returns>
|
||||
public static async Task<SwipeCardCreateOrderResponse> SwipeCardCreateOrderAsync(
|
||||
this WeiFuTongClient weiFuTongClient
|
||||
, SwipeCardCreateOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
LogHelper.Trace("威富通-刷卡支付下单", log.ToString());
|
||||
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new HttpException(response.StatusCode) {Content = resText};
|
||||
}
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<SwipeCardCreateOrderResponse>(resText);
|
||||
|
||||
if (res.HasError() && res.NeedQuery != "Y" && res.NeedQuery != "")
|
||||
{
|
||||
res.HandleError();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,57 @@
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.WechatJsPay;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序或公众号支付
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WechatJsPayCreateOrderResponse> WechatJsPayCreateOrderAsync(
|
||||
this WeiFuTongClient weiFuTongClient
|
||||
, WechatJsPayCreateOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
string appEnv = "";
|
||||
|
||||
if (request.IsMinipg == "1")
|
||||
{
|
||||
appEnv = "小程序";
|
||||
}
|
||||
else
|
||||
{
|
||||
appEnv = "公众号";
|
||||
}
|
||||
|
||||
LogHelper.Trace($"威富通-微信{appEnv}支付下单", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<WechatJsPayCreateOrderResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.WeiFuTong.WechatJsPay;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.ClientExtension
|
||||
{
|
||||
public static class WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序或公众号支付
|
||||
/// </summary>
|
||||
/// <param name="weiFuTongClient"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<WechatJsPayCreateOrderResponse> WechatJsPayCreateOrderAsync(
|
||||
this WeiFuTongClient weiFuTongClient
|
||||
, WechatJsPayCreateOrderRequest request)
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
var body = request.ToXml();
|
||||
|
||||
log.Append("请求:\r\n" + body);
|
||||
|
||||
var response = await weiFuTongClient.CreateHttpClient()
|
||||
.PostAsync(request.PaymentChannel.GetUrl(), new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
log.Append("\r\n响应:" + resText);
|
||||
|
||||
string appEnv = "";
|
||||
|
||||
if (request.IsMinipg == "1")
|
||||
{
|
||||
appEnv = "小程序";
|
||||
}
|
||||
else
|
||||
{
|
||||
appEnv = "公众号";
|
||||
}
|
||||
|
||||
LogHelper.Trace($"威富通-微信{appEnv}支付下单", log.ToString());
|
||||
|
||||
Util.CheckSignFromXml(resText, request.MchInfo);
|
||||
|
||||
var res = XML.XmlDeserialize<WechatJsPayCreateOrderResponse>(resText);
|
||||
|
||||
res.HandleError();
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,141 +1,141 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Notify
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class NotifyResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户在服务商 appid 下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string OpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 交易类型
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注服务商公众账号,Y-关注,N-未关注
|
||||
/// </summary>
|
||||
[XmlElement("is_subscribe")]
|
||||
public string IsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果:0—成功;其它—失败
|
||||
/// </summary>
|
||||
[XmlElement("pay_result")]
|
||||
public int PayResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果信息,支付成功时为空
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_transaction_id")]
|
||||
public string OutTransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方商户单号,可在支持的商户扫码退款
|
||||
/// </summary>
|
||||
[XmlElement("third_order_no")]
|
||||
public string ThirdOrderNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注子公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("sub_is_subscribe")]
|
||||
public string SubIsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子商户appid
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string SubAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在子商户appid下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string SubOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的定单号,32个字符内、可包含字母
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金支付金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("cash_fee")]
|
||||
public int CashFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金券金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("coupon_fee")]
|
||||
public string CouponFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
/// </summary>
|
||||
[XmlElement("fee_type")]
|
||||
public string FeeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家数据包,原样返回
|
||||
/// </summary>
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 付款银行
|
||||
/// </summary>
|
||||
[XmlElement("bank_type")]
|
||||
public string BankType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 银行订单号,若为微信支付则为空
|
||||
/// </summary>
|
||||
[XmlElement("bank_billno")]
|
||||
public string BankBillno { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自平台服务器
|
||||
/// </summary>
|
||||
[XmlElement("time_end")]
|
||||
public string TimeEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取支付成功时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public DateTime GetPaySuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(TimeEnd, "yyyyMMddHHmmss", null, DateTimeStyles.None, out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Notify
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class NotifyResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户在服务商 appid 下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string OpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 交易类型
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注服务商公众账号,Y-关注,N-未关注
|
||||
/// </summary>
|
||||
[XmlElement("is_subscribe")]
|
||||
public string IsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果:0—成功;其它—失败
|
||||
/// </summary>
|
||||
[XmlElement("pay_result")]
|
||||
public int PayResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果信息,支付成功时为空
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_transaction_id")]
|
||||
public string OutTransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方商户单号,可在支持的商户扫码退款
|
||||
/// </summary>
|
||||
[XmlElement("third_order_no")]
|
||||
public string ThirdOrderNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注子公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("sub_is_subscribe")]
|
||||
public string SubIsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子商户appid
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string SubAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在子商户appid下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string SubOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的定单号,32个字符内、可包含字母
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金支付金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("cash_fee")]
|
||||
public int CashFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金券金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("coupon_fee")]
|
||||
public string CouponFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
/// </summary>
|
||||
[XmlElement("fee_type")]
|
||||
public string FeeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家数据包,原样返回
|
||||
/// </summary>
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 付款银行
|
||||
/// </summary>
|
||||
[XmlElement("bank_type")]
|
||||
public string BankType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 银行订单号,若为微信支付则为空
|
||||
/// </summary>
|
||||
[XmlElement("bank_billno")]
|
||||
public string BankBillno { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自平台服务器
|
||||
/// </summary>
|
||||
[XmlElement("time_end")]
|
||||
public string TimeEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取支付成功时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public DateTime GetPaySuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(TimeEnd, "yyyyMMddHHmmss", null, DateTimeStyles.None, out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,40 @@
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.QrPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class QrPayCreateOrderRequest: WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
public QrPayCreateOrderRequest(string service) : base(service)
|
||||
{
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.QrPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class QrPayCreateOrderRequest: WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
public QrPayCreateOrderRequest(string service) : base(service)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.QrPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class QrPayCreateOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户可用此参数自定义去生成二维码后展示出来进行扫码支付
|
||||
/// </summary>
|
||||
[XmlElement("code_url")]
|
||||
public string CodeUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 此参数的值即是根据code_url生成的可以扫码支付的二维码图片地址
|
||||
/// </summary>
|
||||
[XmlElement("code_img_url")]
|
||||
public string CodeImgUrl { get; set; }
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.QrPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class QrPayCreateOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户可用此参数自定义去生成二维码后展示出来进行扫码支付
|
||||
/// </summary>
|
||||
[XmlElement("code_url")]
|
||||
public string CodeUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 此参数的值即是根据code_url生成的可以扫码支付的二维码图片地址
|
||||
/// </summary>
|
||||
[XmlElement("code_img_url")]
|
||||
public string CodeImgUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.QueryOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通查询订单请求
|
||||
/// </summary>
|
||||
public class WeiFuTongQueryOrderRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先。
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
public WeiFuTongQueryOrderRequest()
|
||||
: base("unified.trade.query")
|
||||
{
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.QueryOrder
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通查询订单请求
|
||||
/// </summary>
|
||||
public class WeiFuTongQueryOrderRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先。
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
public WeiFuTongQueryOrderRequest()
|
||||
: base("unified.trade.query")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,221 +1,221 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付查询订单响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongQueryOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
// 以下字段在 status 为 0的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// 门店编号,由平台分配
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终端设备号
|
||||
/// </summary>
|
||||
[XmlElement("device_info")]
|
||||
public string DeviceInfo { get; set; }
|
||||
|
||||
// 以下字段在 status 和 result_code 都为 0的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// SUCCESS—支付成功
|
||||
/// REFUND—转入退款
|
||||
/// NOTPAY—未支付
|
||||
/// CLOSED—已关闭
|
||||
/// REVOKED/REVERSE—已撤销
|
||||
/// USERPAYING—用户支付中
|
||||
/// PAYERROR—支付失败(其他原因,如银行返回失败)
|
||||
/// </summary>
|
||||
[XmlElement("trade_state")]
|
||||
public string TradeState { get; set; }
|
||||
|
||||
// 以下字段在 trade_state为 SUCCESS的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// pay.wechat.micropay——微信刷卡支付
|
||||
/// pay.alipay.micropay——支付宝刷卡支付
|
||||
/// pay.jdpay.micropay——京东刷卡支付
|
||||
/// pay.qq.micropay——QQ钱包刷卡支付
|
||||
/// pay.shiming.micropay——会员卡支付
|
||||
/// pay.unionpay.micropay——银联支付
|
||||
/// pay.bestpay.micropay——翼支付
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 受理商户appid
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子商户appid
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string SubAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在受理商户 appid 下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string OpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在子商户appid下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string SubOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("is_subscribe")]
|
||||
public string IsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注子公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("sub_is_subscribe")]
|
||||
public string SubIsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_transaction_id")]
|
||||
public string OutTransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方商户单号,可在支持的商户扫码退款
|
||||
/// </summary>
|
||||
[XmlElement("third_order_no")]
|
||||
public string ThirdOrderNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的定单号,32个字符内、可包含字母
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金支付金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("cash_fee")]
|
||||
public int CashFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开票金额 【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("invoice_amount")]
|
||||
public string InvoiceAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实收金额【支付宝】实收金额,单位为元,两位小数。该金额为本笔交易,商户账户能够实际收到的金额
|
||||
/// </summary>
|
||||
[XmlElement("receipt_amount")]
|
||||
public string ReceiptAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 买家实付金额【支付宝】买家实付金额,单位为元,两位小数。该金额代表该笔交易买家实际支付的金额,不包含商户折扣等金额
|
||||
/// </summary>
|
||||
[XmlElement("buyer_pay_amount")]
|
||||
public string BuyerPayAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 集分宝付款金额【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("point_amount")]
|
||||
public string PointAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金券金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("coupon_fee")]
|
||||
public string CouponFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
/// </summary>
|
||||
[XmlElement("fee_type")]
|
||||
public string FeeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家数据包,原样返回
|
||||
/// </summary>
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 付款银行
|
||||
/// </summary>
|
||||
[XmlElement("bank_type")]
|
||||
public string BankType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 银行订单号,若为微信支付则为空
|
||||
/// </summary>
|
||||
[XmlElement("bank_billno")]
|
||||
public string BankBillno { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自平台服务器
|
||||
/// </summary>
|
||||
[XmlElement("time_end")]
|
||||
public string TimeEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否支付成功
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsPaySuccess()
|
||||
{
|
||||
return !HasError() && (TradeState == "SUCCESS" || TradeState == "REFUND");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为支付失败,未支付和支付中不认定为失败
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsPayFailed()
|
||||
{
|
||||
return !HasError()
|
||||
&& TradeState != "SUCCESS"
|
||||
&& TradeState != "NOTPAY"
|
||||
&& TradeState != "USERPAYING"
|
||||
&& TradeState != "REFUND";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取支付成功时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public DateTime GetPaySuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(TimeEnd, "yyyyMMddHHmmss", null, DateTimeStyles.None, out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付查询订单响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongQueryOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
// 以下字段在 status 为 0的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// 门店编号,由平台分配
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终端设备号
|
||||
/// </summary>
|
||||
[XmlElement("device_info")]
|
||||
public string DeviceInfo { get; set; }
|
||||
|
||||
// 以下字段在 status 和 result_code 都为 0的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// SUCCESS—支付成功
|
||||
/// REFUND—转入退款
|
||||
/// NOTPAY—未支付
|
||||
/// CLOSED—已关闭
|
||||
/// REVOKED/REVERSE—已撤销
|
||||
/// USERPAYING—用户支付中
|
||||
/// PAYERROR—支付失败(其他原因,如银行返回失败)
|
||||
/// </summary>
|
||||
[XmlElement("trade_state")]
|
||||
public string TradeState { get; set; }
|
||||
|
||||
// 以下字段在 trade_state为 SUCCESS的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// pay.wechat.micropay——微信刷卡支付
|
||||
/// pay.alipay.micropay——支付宝刷卡支付
|
||||
/// pay.jdpay.micropay——京东刷卡支付
|
||||
/// pay.qq.micropay——QQ钱包刷卡支付
|
||||
/// pay.shiming.micropay——会员卡支付
|
||||
/// pay.unionpay.micropay——银联支付
|
||||
/// pay.bestpay.micropay——翼支付
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 受理商户appid
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子商户appid
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string SubAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在受理商户 appid 下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string OpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在子商户appid下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string SubOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("is_subscribe")]
|
||||
public string IsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注子公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("sub_is_subscribe")]
|
||||
public string SubIsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_transaction_id")]
|
||||
public string OutTransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方商户单号,可在支持的商户扫码退款
|
||||
/// </summary>
|
||||
[XmlElement("third_order_no")]
|
||||
public string ThirdOrderNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的定单号,32个字符内、可包含字母
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金支付金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("cash_fee")]
|
||||
public int CashFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开票金额 【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("invoice_amount")]
|
||||
public string InvoiceAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实收金额【支付宝】实收金额,单位为元,两位小数。该金额为本笔交易,商户账户能够实际收到的金额
|
||||
/// </summary>
|
||||
[XmlElement("receipt_amount")]
|
||||
public string ReceiptAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 买家实付金额【支付宝】买家实付金额,单位为元,两位小数。该金额代表该笔交易买家实际支付的金额,不包含商户折扣等金额
|
||||
/// </summary>
|
||||
[XmlElement("buyer_pay_amount")]
|
||||
public string BuyerPayAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 集分宝付款金额【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("point_amount")]
|
||||
public string PointAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金券金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("coupon_fee")]
|
||||
public string CouponFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
/// </summary>
|
||||
[XmlElement("fee_type")]
|
||||
public string FeeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家数据包,原样返回
|
||||
/// </summary>
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 付款银行
|
||||
/// </summary>
|
||||
[XmlElement("bank_type")]
|
||||
public string BankType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 银行订单号,若为微信支付则为空
|
||||
/// </summary>
|
||||
[XmlElement("bank_billno")]
|
||||
public string BankBillno { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自平台服务器
|
||||
/// </summary>
|
||||
[XmlElement("time_end")]
|
||||
public string TimeEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否支付成功
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsPaySuccess()
|
||||
{
|
||||
return !HasError() && (TradeState == "SUCCESS" || TradeState == "REFUND");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为支付失败,未支付和支付中不认定为失败
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsPayFailed()
|
||||
{
|
||||
return !HasError()
|
||||
&& TradeState != "SUCCESS"
|
||||
&& TradeState != "NOTPAY"
|
||||
&& TradeState != "USERPAYING"
|
||||
&& TradeState != "REFUND";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取支付成功时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public DateTime GetPaySuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(TimeEnd, "yyyyMMddHHmmss", null, DateTimeStyles.None, out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,39 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款查询请求
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRefundQueryRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可传入平台订单号或第三方商户单号(third_order_no), out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户退款单号,32个字符内、可包含字母,确保在商户系统唯一。
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台退款单号refund_id、out_refund_no、out_trade_no 、transaction_id 四个参数必填一个, 如果同时存在优先级为:refund_id>out_refund_no>transaction_id>out_trade_no
|
||||
/// </summary>
|
||||
[XmlElement("refund_id")]
|
||||
public string RefundId { get; set; }
|
||||
|
||||
public WeiFuTongRefundQueryRequest() : base("unified.trade.refundquery")
|
||||
{
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款查询请求
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRefundQueryRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可传入平台订单号或第三方商户单号(third_order_no), out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户退款单号,32个字符内、可包含字母,确保在商户系统唯一。
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台退款单号refund_id、out_refund_no、out_trade_no 、transaction_id 四个参数必填一个, 如果同时存在优先级为:refund_id>out_refund_no>transaction_id>out_trade_no
|
||||
/// </summary>
|
||||
[XmlElement("refund_id")]
|
||||
public string RefundId { get; set; }
|
||||
|
||||
public WeiFuTongRefundQueryRequest() : base("unified.trade.refundquery")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,168 +1,168 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款查询响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRefundQueryResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款记录数
|
||||
/// </summary>
|
||||
[XmlElement("refund_count")]
|
||||
public int RefundCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 多笔退款详情
|
||||
/// </summary>
|
||||
public List<RefundQueryItem> RefundQueryItems { get; set; } = new List<RefundQueryItem>();
|
||||
|
||||
public WeiFuTongRefundQueryResponse ParseItemsFromXml(string xmlText)
|
||||
{
|
||||
if (RefundCount <= 0)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.XmlResolver = null;
|
||||
xmlDoc.LoadXml(xmlText);
|
||||
XmlNode root = xmlDoc.SelectSingleNode("xml");
|
||||
|
||||
for (int i = 0; i < RefundCount; i++)
|
||||
{
|
||||
RefundQueryItems.Add(new RefundQueryItem()
|
||||
{
|
||||
OutRefundNo = root.SelectSingleNode("out_refund_no_" + i).InnerText,
|
||||
RefundId = root.SelectSingleNode("refund_id_" + i).InnerText,
|
||||
RefundChannel = root.SelectSingleNode("refund_channel_" + i).InnerText,
|
||||
RefundFee = root.SelectSingleNode("refund_fee_" + i).InnerText.ToInt(),
|
||||
RefundTime = root.SelectSingleNode("refund_time_" + i).InnerText,
|
||||
RefundStatus = root.SelectSingleNode("refund_status_" + i).InnerText
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是退款成功
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsRefundSuccess()
|
||||
{
|
||||
return !HasError()
|
||||
&& RefundQueryItems.Any()
|
||||
&& RefundQueryItems.First().RefundStatus == "SUCCESS";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是退款失败
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsRefundFail()
|
||||
{
|
||||
return !HasError()
|
||||
&& RefundQueryItems.Any()
|
||||
&& RefundQueryItems.First().RefundStatus == "FAIL";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是已撤销
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsCancel()
|
||||
{
|
||||
return RefundCount == 0
|
||||
&& ErrCode == "REFUND_FAIL"
|
||||
&& ErrMsg.Contains("已撤销");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退款不存在
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsNotExists()
|
||||
{
|
||||
return HasError() &&
|
||||
(
|
||||
ErrCode.ToLower().Contains("refund not exists")
|
||||
|| ErrCode.ToLower().Contains("order not exists")
|
||||
|| ErrMsg.Contains("退款不存在")
|
||||
|| ErrMsg.Contains("订单不存在")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public DateTime GetRefundSuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(RefundQueryItems.First().RefundTime, "yyyyMMddHHmmss", null, DateTimeStyles.None,
|
||||
out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
}
|
||||
|
||||
public class RefundQueryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户退款单号
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台退款单号
|
||||
/// </summary>
|
||||
[XmlElement("refund_id")]
|
||||
public string RefundId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款渠道 ORIGINAL—原路退款,默认
|
||||
/// </summary>
|
||||
[XmlElement("refund_channel")]
|
||||
public string RefundChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款总金额,单位为分,可以做部分退款
|
||||
/// </summary>
|
||||
[XmlElement("refund_fee")]
|
||||
public int RefundFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("refund_time")]
|
||||
public string RefundTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SUCCESS—退款成功
|
||||
/// FAIL—退款失败
|
||||
/// PROCESSING—退款处理中
|
||||
/// NOTSURE—未确定, 需要商户原退款单号重新发起
|
||||
/// CHANGE—转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者平台转账的方式进行退款。
|
||||
/// </summary>
|
||||
[XmlElement("refund_status")]
|
||||
public string RefundStatus { get; set; }
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款查询响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRefundQueryResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款记录数
|
||||
/// </summary>
|
||||
[XmlElement("refund_count")]
|
||||
public int RefundCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 多笔退款详情
|
||||
/// </summary>
|
||||
public List<RefundQueryItem> RefundQueryItems { get; set; } = new List<RefundQueryItem>();
|
||||
|
||||
public WeiFuTongRefundQueryResponse ParseItemsFromXml(string xmlText)
|
||||
{
|
||||
if (RefundCount <= 0)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.XmlResolver = null;
|
||||
xmlDoc.LoadXml(xmlText);
|
||||
XmlNode root = xmlDoc.SelectSingleNode("xml");
|
||||
|
||||
for (int i = 0; i < RefundCount; i++)
|
||||
{
|
||||
RefundQueryItems.Add(new RefundQueryItem()
|
||||
{
|
||||
OutRefundNo = root.SelectSingleNode("out_refund_no_" + i).InnerText,
|
||||
RefundId = root.SelectSingleNode("refund_id_" + i).InnerText,
|
||||
RefundChannel = root.SelectSingleNode("refund_channel_" + i).InnerText,
|
||||
RefundFee = root.SelectSingleNode("refund_fee_" + i).InnerText.ToInt(),
|
||||
RefundTime = root.SelectSingleNode("refund_time_" + i).InnerText,
|
||||
RefundStatus = root.SelectSingleNode("refund_status_" + i).InnerText
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是退款成功
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsRefundSuccess()
|
||||
{
|
||||
return !HasError()
|
||||
&& RefundQueryItems.Any()
|
||||
&& RefundQueryItems.First().RefundStatus == "SUCCESS";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是退款失败
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsRefundFail()
|
||||
{
|
||||
return !HasError()
|
||||
&& RefundQueryItems.Any()
|
||||
&& RefundQueryItems.First().RefundStatus == "FAIL";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是已撤销
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsCancel()
|
||||
{
|
||||
return RefundCount == 0
|
||||
&& ErrCode == "REFUND_FAIL"
|
||||
&& ErrMsg.Contains("已撤销");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退款不存在
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsNotExists()
|
||||
{
|
||||
return HasError() &&
|
||||
(
|
||||
ErrCode.ToLower().Contains("refund not exists")
|
||||
|| ErrCode.ToLower().Contains("order not exists")
|
||||
|| ErrMsg.Contains("退款不存在")
|
||||
|| ErrMsg.Contains("订单不存在")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public DateTime GetRefundSuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(RefundQueryItems.First().RefundTime, "yyyyMMddHHmmss", null, DateTimeStyles.None,
|
||||
out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
}
|
||||
|
||||
public class RefundQueryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户退款单号
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台退款单号
|
||||
/// </summary>
|
||||
[XmlElement("refund_id")]
|
||||
public string RefundId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款渠道 ORIGINAL—原路退款,默认
|
||||
/// </summary>
|
||||
[XmlElement("refund_channel")]
|
||||
public string RefundChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款总金额,单位为分,可以做部分退款
|
||||
/// </summary>
|
||||
[XmlElement("refund_fee")]
|
||||
public int RefundFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("refund_time")]
|
||||
public string RefundTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SUCCESS—退款成功
|
||||
/// FAIL—退款失败
|
||||
/// PROCESSING—退款处理中
|
||||
/// NOTSURE—未确定, 需要商户原退款单号重新发起
|
||||
/// CHANGE—转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者平台转账的方式进行退款。
|
||||
/// </summary>
|
||||
[XmlElement("refund_status")]
|
||||
public string RefundStatus { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,56 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款请求
|
||||
/// </summary>
|
||||
public class WeiFuTongRefundRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可传入平台订单号或第三方商户单号(third_order_no), out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户退款单号,32个字符内、可包含字母,确保在商户系统唯一。同个退款单号多次请求,平台当一个单处理,只会退一次款。如果出现退款不成功,请采用原退款单号重新发起,避免出现重复退款。
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单总金额,单位为分
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int OrderTotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款总金额,单位为分,可以做部分退款
|
||||
/// </summary>
|
||||
[XmlElement("refund_fee")]
|
||||
public int RefundFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员帐号,默认为商户号
|
||||
/// </summary>
|
||||
[XmlElement("op_user_id")]
|
||||
public string OpUserId => MchId;
|
||||
|
||||
/// <summary>
|
||||
/// 退款渠道ORIGINAL-原路退款,默认
|
||||
/// </summary>
|
||||
[XmlElement("refund_channel")]
|
||||
public string RefundChannel => "ORIGINAL";
|
||||
|
||||
public WeiFuTongRefundRequest() : base("unified.trade.refund")
|
||||
{
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款请求
|
||||
/// </summary>
|
||||
public class WeiFuTongRefundRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号, out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可传入平台订单号或第三方商户单号(third_order_no), out_trade_no和transaction_id至少一个必填,同时存在时transaction_id优先
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户退款单号,32个字符内、可包含字母,确保在商户系统唯一。同个退款单号多次请求,平台当一个单处理,只会退一次款。如果出现退款不成功,请采用原退款单号重新发起,避免出现重复退款。
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单总金额,单位为分
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int OrderTotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款总金额,单位为分,可以做部分退款
|
||||
/// </summary>
|
||||
[XmlElement("refund_fee")]
|
||||
public int RefundFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作员帐号,默认为商户号
|
||||
/// </summary>
|
||||
[XmlElement("op_user_id")]
|
||||
public string OpUserId => MchId;
|
||||
|
||||
/// <summary>
|
||||
/// 退款渠道ORIGINAL-原路退款,默认
|
||||
/// </summary>
|
||||
[XmlElement("refund_channel")]
|
||||
public string RefundChannel => "ORIGINAL";
|
||||
|
||||
public WeiFuTongRefundRequest() : base("unified.trade.refund")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,47 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRefundResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户退款单号
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台退款单号
|
||||
/// </summary>
|
||||
[XmlElement("refund_id")]
|
||||
public string RefundId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款渠道 ORIGINAL—原路退款,默认
|
||||
/// </summary>
|
||||
[XmlElement("refund_channel")]
|
||||
public string RefundChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款总金额,单位为分,可以做部分退款
|
||||
/// </summary>
|
||||
[XmlElement("refund_fee")]
|
||||
public int RefundFee { get; set; }
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.Refund
|
||||
{
|
||||
/// <summary>
|
||||
/// 威富通退款响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRefundResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户退款单号
|
||||
/// </summary>
|
||||
[XmlElement("out_refund_no")]
|
||||
public string OutRefundNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台退款单号
|
||||
/// </summary>
|
||||
[XmlElement("refund_id")]
|
||||
public string RefundId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款渠道 ORIGINAL—原路退款,默认
|
||||
/// </summary>
|
||||
[XmlElement("refund_channel")]
|
||||
public string RefundChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 退款总金额,单位为分,可以做部分退款
|
||||
/// </summary>
|
||||
[XmlElement("refund_fee")]
|
||||
public int RefundFee { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,55 +1,55 @@
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付下单请求
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class SwipeCardCreateOrderRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终端设备号,商户自定义。特别说明:对于QQ钱包支付,此参数必传,否则会报错。
|
||||
/// </summary>
|
||||
[XmlElement("device_info")]
|
||||
public string DeviceInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
/// <summary>
|
||||
/// 扫码支付授权码, 设备读取用户展示的条码或者二维码信息
|
||||
/// </summary>
|
||||
[XmlElement("auth_code")]
|
||||
public string AuthCode { get; set; }
|
||||
|
||||
|
||||
public SwipeCardCreateOrderRequest()
|
||||
: base("unified.trade.micropay")
|
||||
{
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付下单请求
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class SwipeCardCreateOrderRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终端设备号,商户自定义。特别说明:对于QQ钱包支付,此参数必传,否则会报错。
|
||||
/// </summary>
|
||||
[XmlElement("device_info")]
|
||||
public string DeviceInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
/// <summary>
|
||||
/// 扫码支付授权码, 设备读取用户展示的条码或者二维码信息
|
||||
/// </summary>
|
||||
[XmlElement("auth_code")]
|
||||
public string AuthCode { get; set; }
|
||||
|
||||
|
||||
public SwipeCardCreateOrderRequest()
|
||||
: base("unified.trade.micropay")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,206 +1,206 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付下单响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class SwipeCardCreateOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 用来判断是否需要调用查询接口,值为Y时需要,值为N时不需要
|
||||
/// </summary>
|
||||
[XmlElement("need_query")]
|
||||
public string NeedQuery { get; set; }
|
||||
|
||||
//以下字段在 status 为 0的时候有返回
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 门店编号,由平台分配
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终端设备号
|
||||
/// </summary>
|
||||
[XmlElement("device_info")]
|
||||
public string DeviceInfo { get; set; }
|
||||
|
||||
|
||||
//以下字段在 status 和 result_code 都为 0的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// 用户在受理商户 appid 下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string OpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在子商户appid下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string SubOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// pay.wechat.micropay——微信刷卡支付
|
||||
/// pay.alipay.micropay——支付宝刷卡支付
|
||||
/// pay.jdpay.micropay——京东刷卡支付
|
||||
/// pay.qq.micropay——QQ钱包刷卡支付
|
||||
/// pay.shiming.micropay——会员卡支付
|
||||
/// pay.unionpay.micropay——银联支付
|
||||
/// pay.bestpay.micropay——翼支付
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("is_subscribe")]
|
||||
public string IsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果:0—成功;其它—失败
|
||||
/// </summary>
|
||||
[XmlElement("pay_result")]
|
||||
public int PayResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果信息,支付成功时为空
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_transaction_id")]
|
||||
public string OutTransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方商户单号,可在支持的商户扫码退款
|
||||
/// </summary>
|
||||
[XmlElement("third_order_no")]
|
||||
public string ThirdOrderNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注子公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("sub_is_subscribe")]
|
||||
public string SubIsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子商户appid
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string SubAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的定单号,32个字符内、可包含字母
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金支付金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("cash_fee")]
|
||||
public int CashFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开票金额 【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("invoice_amount")]
|
||||
public string InvoiceAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 集分宝付款金额【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("point_amount")]
|
||||
public string PointAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金券金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("coupon_fee")]
|
||||
public string CouponFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 交易支付使用的资金渠道 【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("fund_bill_list")]
|
||||
public string FundChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实收金额【支付宝】实收金额,单位为元,两位小数。该金额为本笔交易,商户账户能够实际收到的金额
|
||||
/// </summary>
|
||||
[XmlElement("receipt_amount")]
|
||||
public string ReceiptAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 买家实付金额【支付宝】买家实付金额,单位为元,两位小数。该金额代表该笔交易买家实际支付的金额,不包含商户折扣等金额
|
||||
/// </summary>
|
||||
[XmlElement("buyer_pay_amount")]
|
||||
public string BuyerPayAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
/// </summary>
|
||||
[XmlElement("fee_type")]
|
||||
public string FeeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家数据包,原样返回
|
||||
/// </summary>
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 付款银行
|
||||
/// </summary>
|
||||
[XmlElement("bank_type")]
|
||||
public string BankType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 银行订单号,若为微信支付则为空
|
||||
/// </summary>
|
||||
[XmlElement("bank_billno")]
|
||||
public string BankBillno { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自平台服务器
|
||||
/// </summary>
|
||||
[XmlElement("time_end")]
|
||||
public string TimeEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取支付成功时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public DateTime GetPaySuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(TimeEnd, "yyyyMMddHHmmss", null, DateTimeStyles.None, out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
|
||||
}
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.SwipeCard
|
||||
{
|
||||
/// <summary>
|
||||
/// 刷卡支付下单响应
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class SwipeCardCreateOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 用来判断是否需要调用查询接口,值为Y时需要,值为N时不需要
|
||||
/// </summary>
|
||||
[XmlElement("need_query")]
|
||||
public string NeedQuery { get; set; }
|
||||
|
||||
//以下字段在 status 为 0的时候有返回
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 门店编号,由平台分配
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 终端设备号
|
||||
/// </summary>
|
||||
[XmlElement("device_info")]
|
||||
public string DeviceInfo { get; set; }
|
||||
|
||||
|
||||
//以下字段在 status 和 result_code 都为 0的时候有返回
|
||||
|
||||
/// <summary>
|
||||
/// 用户在受理商户 appid 下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string OpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户在子商户appid下的唯一标识
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string SubOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// pay.wechat.micropay——微信刷卡支付
|
||||
/// pay.alipay.micropay——支付宝刷卡支付
|
||||
/// pay.jdpay.micropay——京东刷卡支付
|
||||
/// pay.qq.micropay——QQ钱包刷卡支付
|
||||
/// pay.shiming.micropay——会员卡支付
|
||||
/// pay.unionpay.micropay——银联支付
|
||||
/// pay.bestpay.micropay——翼支付
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("is_subscribe")]
|
||||
public string IsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果:0—成功;其它—失败
|
||||
/// </summary>
|
||||
[XmlElement("pay_result")]
|
||||
public int PayResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付结果信息,支付成功时为空
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 平台交易号
|
||||
/// </summary>
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方订单号
|
||||
/// </summary>
|
||||
[XmlElement("out_transaction_id")]
|
||||
public string OutTransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 第三方商户单号,可在支持的商户扫码退款
|
||||
/// </summary>
|
||||
[XmlElement("third_order_no")]
|
||||
public string ThirdOrderNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户是否关注子公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
|
||||
/// </summary>
|
||||
[XmlElement("sub_is_subscribe")]
|
||||
public string SubIsSubscribe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子商户appid
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string SubAppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的定单号,32个字符内、可包含字母
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金支付金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("cash_fee")]
|
||||
public int CashFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 开票金额 【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("invoice_amount")]
|
||||
public string InvoiceAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 集分宝付款金额【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("point_amount")]
|
||||
public string PointAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 现金券金额【微信】
|
||||
/// </summary>
|
||||
[XmlElement("coupon_fee")]
|
||||
public string CouponFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 交易支付使用的资金渠道 【支付宝】
|
||||
/// </summary>
|
||||
[XmlElement("fund_bill_list")]
|
||||
public string FundChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 实收金额【支付宝】实收金额,单位为元,两位小数。该金额为本笔交易,商户账户能够实际收到的金额
|
||||
/// </summary>
|
||||
[XmlElement("receipt_amount")]
|
||||
public string ReceiptAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 买家实付金额【支付宝】买家实付金额,单位为元,两位小数。该金额代表该笔交易买家实际支付的金额,不包含商户折扣等金额
|
||||
/// </summary>
|
||||
[XmlElement("buyer_pay_amount")]
|
||||
public string BuyerPayAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY
|
||||
/// </summary>
|
||||
[XmlElement("fee_type")]
|
||||
public string FeeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商家数据包,原样返回
|
||||
/// </summary>
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 付款银行
|
||||
/// </summary>
|
||||
[XmlElement("bank_type")]
|
||||
public string BankType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 银行订单号,若为微信支付则为空
|
||||
/// </summary>
|
||||
[XmlElement("bank_billno")]
|
||||
public string BankBillno { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自平台服务器
|
||||
/// </summary>
|
||||
[XmlElement("time_end")]
|
||||
public string TimeEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取支付成功时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public DateTime GetPaySuccessTime()
|
||||
{
|
||||
DateTime.TryParseExact(TimeEnd, "yyyyMMddHHmmss", null, DateTimeStyles.None, out var paySuccessTime);
|
||||
|
||||
return paySuccessTime;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,100 +1,100 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using XC.RSAUtil;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
public class Util
|
||||
{
|
||||
public static void CheckSignFromXml(string xmlText, MchInfo mchInfo)
|
||||
{
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.XmlResolver = null;
|
||||
xmlDoc.LoadXml(xmlText);
|
||||
XmlNode root = xmlDoc.SelectSingleNode("xml");
|
||||
XmlNodeList xnl = root.ChildNodes;
|
||||
|
||||
if (root.SelectSingleNode("status") == null || root.SelectSingleNode("status").InnerText != "0")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SortedDictionary<string, string> dic = new SortedDictionary<string, string>();
|
||||
string responseSign = "";
|
||||
string signType = "MD5";
|
||||
|
||||
|
||||
foreach (XmlNode xnf in xnl)
|
||||
{
|
||||
var parameter = xnf.Name;
|
||||
var parameterValue = xnf.InnerText;
|
||||
|
||||
if (parameter == "sign")
|
||||
{
|
||||
responseSign = parameterValue;
|
||||
}
|
||||
|
||||
if (parameter == "sign_type")
|
||||
{
|
||||
signType = parameterValue;
|
||||
}
|
||||
|
||||
if (parameter.Has() && parameterValue.Has() && parameter != "sign")
|
||||
{
|
||||
if (dic.Keys.Contains(parameter))
|
||||
{
|
||||
dic.Remove(parameter);
|
||||
}
|
||||
|
||||
dic.Add(parameter, parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
string sign = "";
|
||||
|
||||
foreach (var item in dic)
|
||||
{
|
||||
sign += item.Key + "=" + item.Value + "&";
|
||||
}
|
||||
|
||||
|
||||
if (signType == "MD5" || string.IsNullOrEmpty(signType))
|
||||
{
|
||||
sign += "key=" + mchInfo.Key;
|
||||
sign = SecurityHelper.GetMd5Hash(sign).ToUpper();
|
||||
|
||||
if (responseSign.ToUpper() != sign)
|
||||
{
|
||||
BusinessException.Throw("验签失败");
|
||||
}
|
||||
}
|
||||
else if (signType == "RSA_1_1")
|
||||
{
|
||||
sign = sign.Substring(0, sign.Length - 1);
|
||||
|
||||
var verify = new RsaPkcs8Util(Encoding.UTF8
|
||||
, mchInfo.RSAPublicKey
|
||||
, mchInfo.RSAPrivateKey)
|
||||
.VerifyData(sign, responseSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
|
||||
|
||||
if (!verify)
|
||||
{
|
||||
BusinessException.Throw("验签失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BusinessException.Throw("未知签名方式");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using XC.RSAUtil;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
public class Util
|
||||
{
|
||||
public static void CheckSignFromXml(string xmlText, MchInfo mchInfo)
|
||||
{
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.XmlResolver = null;
|
||||
xmlDoc.LoadXml(xmlText);
|
||||
XmlNode root = xmlDoc.SelectSingleNode("xml");
|
||||
XmlNodeList xnl = root.ChildNodes;
|
||||
|
||||
if (root.SelectSingleNode("status") == null || root.SelectSingleNode("status").InnerText != "0")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SortedDictionary<string, string> dic = new SortedDictionary<string, string>();
|
||||
string responseSign = "";
|
||||
string signType = "MD5";
|
||||
|
||||
|
||||
foreach (XmlNode xnf in xnl)
|
||||
{
|
||||
var parameter = xnf.Name;
|
||||
var parameterValue = xnf.InnerText;
|
||||
|
||||
if (parameter == "sign")
|
||||
{
|
||||
responseSign = parameterValue;
|
||||
}
|
||||
|
||||
if (parameter == "sign_type")
|
||||
{
|
||||
signType = parameterValue;
|
||||
}
|
||||
|
||||
if (parameter.Has() && parameterValue.Has() && parameter != "sign")
|
||||
{
|
||||
if (dic.Keys.Contains(parameter))
|
||||
{
|
||||
dic.Remove(parameter);
|
||||
}
|
||||
|
||||
dic.Add(parameter, parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
string sign = "";
|
||||
|
||||
foreach (var item in dic)
|
||||
{
|
||||
sign += item.Key + "=" + item.Value + "&";
|
||||
}
|
||||
|
||||
|
||||
if (signType == "MD5" || string.IsNullOrEmpty(signType))
|
||||
{
|
||||
sign += "key=" + mchInfo.Key;
|
||||
sign = SecurityHelper.GetMd5Hash(sign).ToUpper();
|
||||
|
||||
if (responseSign.ToUpper() != sign)
|
||||
{
|
||||
BusinessException.Throw("验签失败");
|
||||
}
|
||||
}
|
||||
else if (signType == "RSA_1_1")
|
||||
{
|
||||
sign = sign.Substring(0, sign.Length - 1);
|
||||
|
||||
var verify = new RsaPkcs8Util(Encoding.UTF8
|
||||
, mchInfo.RSAPublicKey
|
||||
, mchInfo.RSAPrivateKey)
|
||||
.VerifyData(sign, responseSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
|
||||
|
||||
if (!verify)
|
||||
{
|
||||
BusinessException.Throw("验签失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BusinessException.Throw("未知签名方式");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,67 +1,67 @@
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WechatJsPayCreateOrderRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 原生JS
|
||||
/// </summary>
|
||||
[XmlElement("is_raw")]
|
||||
public string IsRaw { get; set; } = "1";
|
||||
|
||||
/// <summary>
|
||||
/// 值为1,表示小程序支付;不传或值不为1,表示公众账号内支付
|
||||
/// </summary>
|
||||
[XmlElement("is_minipg")]
|
||||
public string IsMinipg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 微信用户关注商家公众号的openid
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string UserOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
public WechatJsPayCreateOrderRequest() : base("pay.weixin.jspay")
|
||||
{
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WechatJsPayCreateOrderRequest : WeiFuTongRequestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 原生JS
|
||||
/// </summary>
|
||||
[XmlElement("is_raw")]
|
||||
public string IsRaw { get; set; } = "1";
|
||||
|
||||
/// <summary>
|
||||
/// 值为1,表示小程序支付;不传或值不为1,表示公众账号内支付
|
||||
/// </summary>
|
||||
[XmlElement("is_minipg")]
|
||||
public string IsMinipg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 微信用户关注商家公众号的openid
|
||||
/// </summary>
|
||||
[XmlElement("sub_openid")]
|
||||
public string UserOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("sub_appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("mch_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
public WechatJsPayCreateOrderRequest() : base("pay.weixin.jspay")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.WechatJsPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WechatJsPayCreateOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 原生态js支付信息或小程序支付信息
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong.WechatJsPay
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WechatJsPayCreateOrderResponse : WeiFuTongResponseBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 原生态js支付信息或小程序支付信息
|
||||
/// </summary>
|
||||
[XmlElement("pay_info")]
|
||||
public string PayInfo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,26 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
public class WeiFuTongClient
|
||||
{
|
||||
private IHttpClientFactory _httpClientFactory;
|
||||
|
||||
public WeiFuTongClient(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public HttpClient CreateHttpClient()
|
||||
{
|
||||
var httpClient = _httpClientFactory.CreateClient();
|
||||
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
}
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
public class WeiFuTongClient
|
||||
{
|
||||
private IHttpClientFactory _httpClientFactory;
|
||||
|
||||
public WeiFuTongClient(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public HttpClient CreateHttpClient()
|
||||
{
|
||||
var httpClient = _httpClientFactory.CreateClient();
|
||||
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,32 @@
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
public class WeiFuTongConfig
|
||||
{
|
||||
public const string WeiFuTongUrl = "https://pay.hstypay.com/v2/pay/gateway";
|
||||
|
||||
public const string QuanFuTongUrl = "https://pay.swiftpass.cn/pay/gateway";
|
||||
}
|
||||
|
||||
public static class Extension
|
||||
{
|
||||
public static string GetUrl(this PaymentChannel paymentChannel)
|
||||
{
|
||||
if (paymentChannel == PaymentChannel.WeiFuTong)
|
||||
{
|
||||
return WeiFuTongConfig.WeiFuTongUrl;
|
||||
}
|
||||
|
||||
if (paymentChannel == PaymentChannel.QuanFuTong)
|
||||
{
|
||||
return WeiFuTongConfig.QuanFuTongUrl;
|
||||
}
|
||||
|
||||
BusinessException.Throw("未知支付渠道");
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
public class WeiFuTongConfig
|
||||
{
|
||||
public const string WeiFuTongUrl = "https://pay.hstypay.com/v2/pay/gateway";
|
||||
|
||||
public const string QuanFuTongUrl = "https://pay.swiftpass.cn/pay/gateway";
|
||||
}
|
||||
|
||||
public static class Extension
|
||||
{
|
||||
public static string GetUrl(this PaymentChannel paymentChannel)
|
||||
{
|
||||
if (paymentChannel == PaymentChannel.WeiFuTong)
|
||||
{
|
||||
return WeiFuTongConfig.WeiFuTongUrl;
|
||||
}
|
||||
|
||||
if (paymentChannel == PaymentChannel.QuanFuTong)
|
||||
{
|
||||
return WeiFuTongConfig.QuanFuTongUrl;
|
||||
}
|
||||
|
||||
BusinessException.Throw("未知支付渠道");
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using XC.RSAUtil;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongDTOBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 随机字符串,不长于 32 位
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; } = Guid.NewGuid().ToString().Replace("-", "");
|
||||
|
||||
/// <summary>
|
||||
/// 签名类型,取值:MD5默认:MD5
|
||||
/// </summary>
|
||||
[XmlElement("sign_type")]
|
||||
public string SignType { get; set; } = "MD5";
|
||||
|
||||
/// <summary>
|
||||
/// MD5签名结果
|
||||
/// </summary>
|
||||
[XmlElement("sign")]
|
||||
public string Sign { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本号,version默认值是2.0
|
||||
/// </summary>
|
||||
[XmlElement("version")]
|
||||
public string Version { get; set; } = "2.0";
|
||||
|
||||
|
||||
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using XC.RSAUtil;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongDTOBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 随机字符串,不长于 32 位
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; } = Guid.NewGuid().ToString().Replace("-", "");
|
||||
|
||||
/// <summary>
|
||||
/// 签名类型,取值:MD5默认:MD5
|
||||
/// </summary>
|
||||
[XmlElement("sign_type")]
|
||||
public string SignType { get; set; } = "MD5";
|
||||
|
||||
/// <summary>
|
||||
/// MD5签名结果
|
||||
/// </summary>
|
||||
[XmlElement("sign")]
|
||||
public string Sign { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 版本号,version默认值是2.0
|
||||
/// </summary>
|
||||
[XmlElement("version")]
|
||||
public string Version { get; set; } = "2.0";
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,156 +1,156 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using XC.RSAUtil;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRequestBase : WeiFuTongDTOBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 接口类型
|
||||
/// </summary>
|
||||
[XmlElement("service")]
|
||||
public string Service { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店编号,由平台分配
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连锁商户号
|
||||
/// </summary>
|
||||
[XmlElement("groupno")]
|
||||
public string GroupNo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可选值 UTF-8 ,默认为 UTF-8
|
||||
/// </summary>
|
||||
[XmlElement("charset")]
|
||||
public string Charset { get; set; } = "UTF-8";
|
||||
|
||||
private MchInfo _mchInfo;
|
||||
|
||||
public MchInfo MchInfo
|
||||
{
|
||||
get => _mchInfo;
|
||||
set
|
||||
{
|
||||
_mchInfo = value;
|
||||
MchId = value.MchId;
|
||||
GroupNo = value.GroupNo;
|
||||
}
|
||||
}
|
||||
|
||||
private PaymentChannel _paymentChannel;
|
||||
|
||||
|
||||
public PaymentChannel PaymentChannel
|
||||
{
|
||||
get => _paymentChannel;
|
||||
set
|
||||
{
|
||||
_paymentChannel = value;
|
||||
|
||||
if (value == PaymentChannel.QuanFuTong)
|
||||
{
|
||||
SignType = "RSA_1_1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WeiFuTongRequestBase(string service)
|
||||
{
|
||||
Service = service;
|
||||
}
|
||||
|
||||
protected virtual SortedDictionary<string, string> ToSortDic()
|
||||
{
|
||||
var type = GetType();
|
||||
var properties = type.GetProperties();
|
||||
|
||||
SortedDictionary<string, string> dic = new SortedDictionary<string, string>();
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var xmlAttr = property.GetCustomAttributes(typeof(XmlElementAttribute), false);
|
||||
|
||||
if (!xmlAttr.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = ((XmlElementAttribute) xmlAttr[0]).ElementName;
|
||||
|
||||
object valueObj = property.GetValue(this, null);
|
||||
|
||||
if (valueObj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = valueObj.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
dic[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
protected virtual void CreateSign(MchInfo mchInfo)
|
||||
{
|
||||
Sign = "";
|
||||
string sign = "";
|
||||
|
||||
foreach (var item in ToSortDic())
|
||||
{
|
||||
sign += item.Key + "=" + item.Value + "&";
|
||||
}
|
||||
|
||||
if (SignType == "MD5")
|
||||
{
|
||||
sign += "key=" + mchInfo.Key;
|
||||
sign = SecurityHelper.GetMd5Hash(sign).ToUpper();
|
||||
}
|
||||
else if (SignType == "RSA_1_1")
|
||||
{
|
||||
sign = sign.Substring(0, sign.Length - 1);
|
||||
|
||||
sign = new RsaPkcs8Util(Encoding.UTF8
|
||||
, mchInfo.RSAPublicKey
|
||||
, mchInfo.RSAPrivateKey)
|
||||
.SignData(sign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
|
||||
}
|
||||
|
||||
|
||||
Sign = sign;
|
||||
}
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
CreateSign(MchInfo);
|
||||
|
||||
StringBuilder sb = new StringBuilder("<xml>\n");
|
||||
|
||||
foreach (var item in ToSortDic())
|
||||
{
|
||||
string key = item.Key;
|
||||
sb.Append("\t<").Append(key).Append("><![CDATA[").Append(item.Value).Append("]]></").Append(key)
|
||||
.Append(">\n");
|
||||
}
|
||||
|
||||
return sb.Append("</xml>").ToString();
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Pass.PaymentCenter.Domain;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using XC.RSAUtil;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongRequestBase : WeiFuTongDTOBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 接口类型
|
||||
/// </summary>
|
||||
[XmlElement("service")]
|
||||
public string Service { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店编号,由平台分配
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连锁商户号
|
||||
/// </summary>
|
||||
[XmlElement("groupno")]
|
||||
public string GroupNo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可选值 UTF-8 ,默认为 UTF-8
|
||||
/// </summary>
|
||||
[XmlElement("charset")]
|
||||
public string Charset { get; set; } = "UTF-8";
|
||||
|
||||
private MchInfo _mchInfo;
|
||||
|
||||
public MchInfo MchInfo
|
||||
{
|
||||
get => _mchInfo;
|
||||
set
|
||||
{
|
||||
_mchInfo = value;
|
||||
MchId = value.MchId;
|
||||
GroupNo = value.GroupNo;
|
||||
}
|
||||
}
|
||||
|
||||
private PaymentChannel _paymentChannel;
|
||||
|
||||
|
||||
public PaymentChannel PaymentChannel
|
||||
{
|
||||
get => _paymentChannel;
|
||||
set
|
||||
{
|
||||
_paymentChannel = value;
|
||||
|
||||
if (value == PaymentChannel.QuanFuTong)
|
||||
{
|
||||
SignType = "RSA_1_1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WeiFuTongRequestBase(string service)
|
||||
{
|
||||
Service = service;
|
||||
}
|
||||
|
||||
protected virtual SortedDictionary<string, string> ToSortDic()
|
||||
{
|
||||
var type = GetType();
|
||||
var properties = type.GetProperties();
|
||||
|
||||
SortedDictionary<string, string> dic = new SortedDictionary<string, string>();
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var xmlAttr = property.GetCustomAttributes(typeof(XmlElementAttribute), false);
|
||||
|
||||
if (!xmlAttr.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = ((XmlElementAttribute) xmlAttr[0]).ElementName;
|
||||
|
||||
object valueObj = property.GetValue(this, null);
|
||||
|
||||
if (valueObj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = valueObj.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
dic[name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
protected virtual void CreateSign(MchInfo mchInfo)
|
||||
{
|
||||
Sign = "";
|
||||
string sign = "";
|
||||
|
||||
foreach (var item in ToSortDic())
|
||||
{
|
||||
sign += item.Key + "=" + item.Value + "&";
|
||||
}
|
||||
|
||||
if (SignType == "MD5")
|
||||
{
|
||||
sign += "key=" + mchInfo.Key;
|
||||
sign = SecurityHelper.GetMd5Hash(sign).ToUpper();
|
||||
}
|
||||
else if (SignType == "RSA_1_1")
|
||||
{
|
||||
sign = sign.Substring(0, sign.Length - 1);
|
||||
|
||||
sign = new RsaPkcs8Util(Encoding.UTF8
|
||||
, mchInfo.RSAPublicKey
|
||||
, mchInfo.RSAPrivateKey)
|
||||
.SignData(sign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
|
||||
}
|
||||
|
||||
|
||||
Sign = sign;
|
||||
}
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
CreateSign(MchInfo);
|
||||
|
||||
StringBuilder sb = new StringBuilder("<xml>\n");
|
||||
|
||||
foreach (var item in ToSortDic())
|
||||
{
|
||||
string key = item.Key;
|
||||
sb.Append("\t<").Append(key).Append("><![CDATA[").Append(item.Value).Append("]]></").Append(key)
|
||||
.Append(">\n");
|
||||
}
|
||||
|
||||
return sb.Append("</xml>").ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +1,66 @@
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongResponseBase : WeiFuTongDTOBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 0表示成功,非0表示失败此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断
|
||||
/// </summary>
|
||||
[XmlElement("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回信息,如非空,为错误原因签名失败参数格式校验错误
|
||||
/// </summary>
|
||||
[XmlElement("message")]
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 业务结果 0表示成功,非0表示失败
|
||||
/// </summary>
|
||||
[XmlElement("result_code")]
|
||||
public string ResultCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误代码
|
||||
/// </summary>
|
||||
[XmlElement("err_code")]
|
||||
public string ErrCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误代码描述
|
||||
/// </summary>
|
||||
[XmlElement("err_msg")]
|
||||
public string ErrMsg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可选值 UTF-8 ,默认为 UTF-8
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[XmlElement("charset")]
|
||||
public string Charset { get; set; }
|
||||
|
||||
public virtual bool HasError()
|
||||
{
|
||||
return Status != "0" || ResultCode != "0";
|
||||
}
|
||||
|
||||
public virtual void HandleError()
|
||||
{
|
||||
if (Status != "0")
|
||||
{
|
||||
BusinessException.Throw($"支付平台通讯失败,status:{Status},message:{Message}");
|
||||
}
|
||||
|
||||
if (ResultCode != "0")
|
||||
{
|
||||
BusinessException.Throw($"支付平台业务处理失败,result_code:{ResultCode},err_msg:{ErrMsg }");
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WeiFuTong
|
||||
{
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WeiFuTongResponseBase : WeiFuTongDTOBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 0表示成功,非0表示失败此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断
|
||||
/// </summary>
|
||||
[XmlElement("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回信息,如非空,为错误原因签名失败参数格式校验错误
|
||||
/// </summary>
|
||||
[XmlElement("message")]
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 业务结果 0表示成功,非0表示失败
|
||||
/// </summary>
|
||||
[XmlElement("result_code")]
|
||||
public string ResultCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误代码
|
||||
/// </summary>
|
||||
[XmlElement("err_code")]
|
||||
public string ErrCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误代码描述
|
||||
/// </summary>
|
||||
[XmlElement("err_msg")]
|
||||
public string ErrMsg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 可选值 UTF-8 ,默认为 UTF-8
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[XmlElement("charset")]
|
||||
public string Charset { get; set; }
|
||||
|
||||
public virtual bool HasError()
|
||||
{
|
||||
return Status != "0" || ResultCode != "0";
|
||||
}
|
||||
|
||||
public virtual void HandleError()
|
||||
{
|
||||
if (Status != "0")
|
||||
{
|
||||
BusinessException.Throw($"支付平台通讯失败,status:{Status},message:{Message}");
|
||||
}
|
||||
|
||||
if (ResultCode != "0")
|
||||
{
|
||||
BusinessException.Throw($"支付平台业务处理失败,result_code:{ResultCode},err_msg:{ErrMsg }");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +1,91 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信扫码付款
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxH5PayCreateOrderRequest : WxJsPayDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// H5支付
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; } = "MWEB";
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("spbill_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
/// <summary>
|
||||
/// 商品Id
|
||||
/// </summary>
|
||||
[XmlElement("product_id")]
|
||||
public string ProductId { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("time_expire")]
|
||||
public string TimeExpire { get; set; }
|
||||
|
||||
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public int StoreId { get; set; }
|
||||
|
||||
|
||||
public WxH5PayCreateOrderRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信扫码付款
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxH5PayCreateOrderRequest : WxJsPayDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// H5支付
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; } = "MWEB";
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("spbill_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
/// <summary>
|
||||
/// 商品Id
|
||||
/// </summary>
|
||||
[XmlElement("product_id")]
|
||||
public string ProductId { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("time_expire")]
|
||||
public string TimeExpire { get; set; }
|
||||
|
||||
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public int StoreId { get; set; }
|
||||
|
||||
|
||||
public WxH5PayCreateOrderRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +1,88 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxJsPayCreateOrderRequest: WxJsPayDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原生JS
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; } = "JSAPI";//NATIVE
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
/// <summary>
|
||||
/// 微信用户关注商家公众号的openid
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string UserOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("spbill_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("time_expire")]
|
||||
public string TimeExpire { get; set; }
|
||||
|
||||
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public int StoreId { get; set; }
|
||||
|
||||
public WxJsPayCreateOrderRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxJsPayCreateOrderRequest: WxJsPayDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原生JS
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; } = "JSAPI";//NATIVE
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
/// <summary>
|
||||
/// 微信用户关注商家公众号的openid
|
||||
/// </summary>
|
||||
[XmlElement("openid")]
|
||||
public string UserOpenId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("spbill_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("time_expire")]
|
||||
public string TimeExpire { get; set; }
|
||||
|
||||
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public int StoreId { get; set; }
|
||||
|
||||
public WxJsPayCreateOrderRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using Newtonsoft.Json;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.WxPay
|
||||
{
|
||||
public class WxJsPayCreateOrderResponse: WxJsPayDataBase
|
||||
{
|
||||
[XmlElement("appId")]
|
||||
public string appId { get; set; }
|
||||
[XmlElement("timeStamp")]
|
||||
public string timeStamp { get; set; }
|
||||
public string nonceStr { get; set; }
|
||||
public string prepay_id { get; set; }
|
||||
public string signType { get; set; }
|
||||
public string paySign { get; set; }
|
||||
[JsonIgnore]
|
||||
public string package => $"prepay_id={this.prepay_id}";
|
||||
}
|
||||
}
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using Newtonsoft.Json;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.WxPay
|
||||
{
|
||||
public class WxJsPayCreateOrderResponse: WxJsPayDataBase
|
||||
{
|
||||
[XmlElement("appId")]
|
||||
public string appId { get; set; }
|
||||
[XmlElement("timeStamp")]
|
||||
public string timeStamp { get; set; }
|
||||
public string nonceStr { get; set; }
|
||||
public string prepay_id { get; set; }
|
||||
public string signType { get; set; }
|
||||
public string paySign { get; set; }
|
||||
[JsonIgnore]
|
||||
public string package => $"prepay_id={this.prepay_id}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,166 +1,166 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付,H5支付 数据签名校验
|
||||
/// </summary>
|
||||
public class WxPayChecker: SortedDictionary<string, string>
|
||||
{
|
||||
public string SignType { get; set; } = "MD5";// "HMAC-SHA256";
|
||||
public string MchKey { get; set; }
|
||||
|
||||
/**
|
||||
* 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
|
||||
* @return 时间戳
|
||||
*/
|
||||
public string GenerateTimeStamp()
|
||||
{
|
||||
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
return Convert.ToInt64(ts.TotalSeconds).ToString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机串,随机串包含字母或数字
|
||||
* @return 随机串
|
||||
*/
|
||||
public string GenerateNonceStr()
|
||||
{
|
||||
return Guid.NewGuid().ToString("N");
|
||||
}
|
||||
|
||||
public virtual string CreateSign()
|
||||
{
|
||||
string sign = "";
|
||||
foreach (var item in this)
|
||||
{
|
||||
if (item.Key == "sign"|| item.Key == "paySign") continue;
|
||||
sign += item.Key + "=" + item.Value + "&";
|
||||
}
|
||||
if(this.MchKey.Has())
|
||||
sign += "key=" + this.MchKey;
|
||||
LogHelper.Trace("CreateSign Str", sign);
|
||||
if (SignType == "MD5")
|
||||
{
|
||||
sign = SecurityHelper.GetMd5Hash(sign);
|
||||
}
|
||||
else if (SignType == "HMAC-SHA256")
|
||||
{
|
||||
sign = CalcHMACSHA256Hash(sign, this.MchKey);
|
||||
}
|
||||
this["sign"] = sign;
|
||||
return sign;
|
||||
}
|
||||
|
||||
public bool IsSet(string key)
|
||||
{
|
||||
if (!this.ContainsKey(key)) return false;
|
||||
return this[key].Has();
|
||||
}
|
||||
|
||||
public virtual bool CheckSign()
|
||||
{
|
||||
//如果没有设置签名,则跳过检测
|
||||
if (!this.IsSet("sign"))
|
||||
{
|
||||
LogHelper.Error("CheckSign", "签名不存在!");
|
||||
return false;
|
||||
}
|
||||
//获取接收到的签名
|
||||
string return_sign = this["sign"];
|
||||
|
||||
//在本地计算新的签名
|
||||
string cal_sign = CreateSign();
|
||||
|
||||
if (cal_sign == return_sign)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private string CalcHMACSHA256Hash(string plaintext, string salt)
|
||||
{
|
||||
string result = "";
|
||||
var enc = Encoding.Default;
|
||||
byte[]
|
||||
baText2BeHashed = enc.GetBytes(plaintext),
|
||||
baSalt = enc.GetBytes(salt);
|
||||
System.Security.Cryptography.HMACSHA256 hasher = new HMACSHA256(baSalt);
|
||||
byte[] baHashedText = hasher.ComputeHash(baText2BeHashed);
|
||||
result = string.Join("", baHashedText.ToList().Select(b => b.ToString("x2")).ToArray());
|
||||
return result;
|
||||
}
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
CreateSign();
|
||||
StringBuilder sb = new StringBuilder("<xml>\n");
|
||||
foreach (var item in this)
|
||||
{
|
||||
string key = item.Key;
|
||||
sb.Append("\t<").Append(key).Append("><![CDATA[").Append(item.Value).Append("]]></").Append(key)
|
||||
.Append(">\n");
|
||||
}
|
||||
|
||||
return sb.Append("</xml>").ToString();
|
||||
}
|
||||
|
||||
public WxPayChecker FromXml(string xml)
|
||||
{
|
||||
if (string.IsNullOrEmpty(xml))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
LogHelper.Info("FromXml", xml);
|
||||
|
||||
this.Clear();
|
||||
XmlDocument xmlDoc = new XmlDocument() { XmlResolver = null };
|
||||
xmlDoc.LoadXml(xml);
|
||||
XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
|
||||
XmlNodeList nodes = xmlNode.ChildNodes;
|
||||
foreach (XmlNode xn in nodes)
|
||||
{
|
||||
XmlElement xe = (XmlElement)xn;
|
||||
this[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
|
||||
}
|
||||
if (!CheckSign())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WxPayChecker FromXmlNoCheckSign(string xml)
|
||||
{
|
||||
if (string.IsNullOrEmpty(xml))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
LogHelper.Info("FromXml", xml);
|
||||
|
||||
this.Clear();
|
||||
XmlDocument xmlDoc = new XmlDocument() { XmlResolver = null };
|
||||
xmlDoc.LoadXml(xml);
|
||||
XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
|
||||
XmlNodeList nodes = xmlNode.ChildNodes;
|
||||
foreach (XmlNode xn in nodes)
|
||||
{
|
||||
XmlElement xe = (XmlElement)xn;
|
||||
this[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付,H5支付 数据签名校验
|
||||
/// </summary>
|
||||
public class WxPayChecker: SortedDictionary<string, string>
|
||||
{
|
||||
public string SignType { get; set; } = "MD5";// "HMAC-SHA256";
|
||||
public string MchKey { get; set; }
|
||||
|
||||
/**
|
||||
* 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
|
||||
* @return 时间戳
|
||||
*/
|
||||
public string GenerateTimeStamp()
|
||||
{
|
||||
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
return Convert.ToInt64(ts.TotalSeconds).ToString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机串,随机串包含字母或数字
|
||||
* @return 随机串
|
||||
*/
|
||||
public string GenerateNonceStr()
|
||||
{
|
||||
return Guid.NewGuid().ToString("N");
|
||||
}
|
||||
|
||||
public virtual string CreateSign()
|
||||
{
|
||||
string sign = "";
|
||||
foreach (var item in this)
|
||||
{
|
||||
if (item.Key == "sign"|| item.Key == "paySign") continue;
|
||||
sign += item.Key + "=" + item.Value + "&";
|
||||
}
|
||||
if(this.MchKey.Has())
|
||||
sign += "key=" + this.MchKey;
|
||||
LogHelper.Trace("CreateSign Str", sign);
|
||||
if (SignType == "MD5")
|
||||
{
|
||||
sign = SecurityHelper.GetMd5Hash(sign);
|
||||
}
|
||||
else if (SignType == "HMAC-SHA256")
|
||||
{
|
||||
sign = CalcHMACSHA256Hash(sign, this.MchKey);
|
||||
}
|
||||
this["sign"] = sign;
|
||||
return sign;
|
||||
}
|
||||
|
||||
public bool IsSet(string key)
|
||||
{
|
||||
if (!this.ContainsKey(key)) return false;
|
||||
return this[key].Has();
|
||||
}
|
||||
|
||||
public virtual bool CheckSign()
|
||||
{
|
||||
//如果没有设置签名,则跳过检测
|
||||
if (!this.IsSet("sign"))
|
||||
{
|
||||
LogHelper.Error("CheckSign", "签名不存在!");
|
||||
return false;
|
||||
}
|
||||
//获取接收到的签名
|
||||
string return_sign = this["sign"];
|
||||
|
||||
//在本地计算新的签名
|
||||
string cal_sign = CreateSign();
|
||||
|
||||
if (cal_sign == return_sign)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private string CalcHMACSHA256Hash(string plaintext, string salt)
|
||||
{
|
||||
string result = "";
|
||||
var enc = Encoding.Default;
|
||||
byte[]
|
||||
baText2BeHashed = enc.GetBytes(plaintext),
|
||||
baSalt = enc.GetBytes(salt);
|
||||
System.Security.Cryptography.HMACSHA256 hasher = new HMACSHA256(baSalt);
|
||||
byte[] baHashedText = hasher.ComputeHash(baText2BeHashed);
|
||||
result = string.Join("", baHashedText.ToList().Select(b => b.ToString("x2")).ToArray());
|
||||
return result;
|
||||
}
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
CreateSign();
|
||||
StringBuilder sb = new StringBuilder("<xml>\n");
|
||||
foreach (var item in this)
|
||||
{
|
||||
string key = item.Key;
|
||||
sb.Append("\t<").Append(key).Append("><![CDATA[").Append(item.Value).Append("]]></").Append(key)
|
||||
.Append(">\n");
|
||||
}
|
||||
|
||||
return sb.Append("</xml>").ToString();
|
||||
}
|
||||
|
||||
public WxPayChecker FromXml(string xml)
|
||||
{
|
||||
if (string.IsNullOrEmpty(xml))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
LogHelper.Info("FromXml", xml);
|
||||
|
||||
this.Clear();
|
||||
XmlDocument xmlDoc = new XmlDocument() { XmlResolver = null };
|
||||
xmlDoc.LoadXml(xml);
|
||||
XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
|
||||
XmlNodeList nodes = xmlNode.ChildNodes;
|
||||
foreach (XmlNode xn in nodes)
|
||||
{
|
||||
XmlElement xe = (XmlElement)xn;
|
||||
this[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
|
||||
}
|
||||
if (!CheckSign())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WxPayChecker FromXmlNoCheckSign(string xml)
|
||||
{
|
||||
if (string.IsNullOrEmpty(xml))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
LogHelper.Info("FromXml", xml);
|
||||
|
||||
this.Clear();
|
||||
XmlDocument xmlDoc = new XmlDocument() { XmlResolver = null };
|
||||
xmlDoc.LoadXml(xml);
|
||||
XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
|
||||
XmlNodeList nodes = xmlNode.ChildNodes;
|
||||
foreach (XmlNode xn in nodes)
|
||||
{
|
||||
XmlElement xe = (XmlElement)xn;
|
||||
this[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,51 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付 数据签名校验
|
||||
/// </summary>
|
||||
public class WxJsPayDataBase
|
||||
{
|
||||
public string GenerateNonceStr()
|
||||
{
|
||||
return Guid.NewGuid().ToString("N");
|
||||
}
|
||||
public WxPayChecker ToPayData()
|
||||
{
|
||||
var type = GetType();
|
||||
var properties = type.GetProperties();
|
||||
|
||||
var data = new WxPayChecker();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var xmlAttr = property.GetCustomAttributes(typeof(XmlElementAttribute), false);
|
||||
|
||||
if (!xmlAttr.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = ((XmlElementAttribute)xmlAttr[0]).ElementName;
|
||||
|
||||
object valueObj = property.GetValue(this, null);
|
||||
|
||||
if (valueObj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = valueObj.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
data[name] = value;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付 数据签名校验
|
||||
/// </summary>
|
||||
public class WxJsPayDataBase
|
||||
{
|
||||
public string GenerateNonceStr()
|
||||
{
|
||||
return Guid.NewGuid().ToString("N");
|
||||
}
|
||||
public WxPayChecker ToPayData()
|
||||
{
|
||||
var type = GetType();
|
||||
var properties = type.GetProperties();
|
||||
|
||||
var data = new WxPayChecker();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var xmlAttr = property.GetCustomAttributes(typeof(XmlElementAttribute), false);
|
||||
|
||||
if (!xmlAttr.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = ((XmlElementAttribute)xmlAttr[0]).ElementName;
|
||||
|
||||
object valueObj = property.GetValue(this, null);
|
||||
|
||||
if (valueObj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = valueObj.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
data[name] = value;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,50 @@
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付 数据签名校验
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxJsPayInfo: WxJsPayDataBase
|
||||
{
|
||||
public WxJsPayInfo(string appId,string signType,string package,string key)
|
||||
{
|
||||
this.appId = appId;
|
||||
this.signType = signType;
|
||||
this.package = package;
|
||||
this.nonceStr = this.GenerateNonceStr();
|
||||
this.timeStamp = DateTime.Now.GetUnixTimeStamp().ToString();
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
[XmlElement("appId")]
|
||||
public string appId { get; set; }
|
||||
|
||||
[XmlElement("timeStamp")]
|
||||
public string timeStamp { get; set; }
|
||||
|
||||
[XmlElement("nonceStr")]
|
||||
public string nonceStr { get; set; }
|
||||
|
||||
[XmlElement("signType")]
|
||||
public string signType { get; set; }
|
||||
|
||||
[XmlElement("package")]
|
||||
public string package { get; set; }
|
||||
|
||||
private string key;
|
||||
public string paySign => getSign();
|
||||
|
||||
private string getSign()
|
||||
{
|
||||
var data = this.ToPayData();
|
||||
data.SignType = this.signType;
|
||||
data.MchKey = this.key;
|
||||
return data.CreateSign();
|
||||
}
|
||||
}
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付 数据签名校验
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxJsPayInfo: WxJsPayDataBase
|
||||
{
|
||||
public WxJsPayInfo(string appId,string signType,string package,string key)
|
||||
{
|
||||
this.appId = appId;
|
||||
this.signType = signType;
|
||||
this.package = package;
|
||||
this.nonceStr = this.GenerateNonceStr();
|
||||
this.timeStamp = DateTime.Now.GetUnixTimeStamp().ToString();
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
[XmlElement("appId")]
|
||||
public string appId { get; set; }
|
||||
|
||||
[XmlElement("timeStamp")]
|
||||
public string timeStamp { get; set; }
|
||||
|
||||
[XmlElement("nonceStr")]
|
||||
public string nonceStr { get; set; }
|
||||
|
||||
[XmlElement("signType")]
|
||||
public string signType { get; set; }
|
||||
|
||||
[XmlElement("package")]
|
||||
public string package { get; set; }
|
||||
|
||||
private string key;
|
||||
public string paySign => getSign();
|
||||
|
||||
private string getSign()
|
||||
{
|
||||
var data = this.ToPayData();
|
||||
data.SignType = this.signType;
|
||||
data.MchKey = this.key;
|
||||
return data.CreateSign();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,39 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxJsPayOrderQueryRequest : WxJsPayDataBase
|
||||
{
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
public WxJsPayOrderQueryRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信小程序、公众号支付
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxJsPayOrderQueryRequest : WxJsPayDataBase
|
||||
{
|
||||
[XmlElement("transaction_id")]
|
||||
public string TransactionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
public WxJsPayOrderQueryRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +1,161 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.WxPay
|
||||
{
|
||||
public class WxPayClient
|
||||
{
|
||||
public static readonly string url = "https://api.mch.weixin.qq.com";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public WxPayClient(IHttpClientFactory _HttpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = _HttpClientFactory;
|
||||
}
|
||||
|
||||
public async Task<string> CreatePayOrderAsync(WxJsPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("ScanPayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!payData.IsSet("prepay_id"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var appId = payData["appid"];
|
||||
var package = $"prepay_id={payData["prepay_id"]}";
|
||||
var resp = new WxJsPayInfo(appId, payData.SignType, package, mchInfo.Key);
|
||||
return resp.ToJson();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task<string> JsPayCreateOrderAsync(WxJsPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("ScanPayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!payData.IsSet("prepay_id"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var appId = payData["appid"];
|
||||
var package = $"prepay_id={payData["prepay_id"]}";
|
||||
var resp = new WxJsPayInfo(appId, payData.SignType, package, mchInfo.Key);
|
||||
return resp.ToJson();
|
||||
}
|
||||
|
||||
public async Task<string> ScanPayCreateOrderAsync(WxScanPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
LogHelper.Info("ScanPayCreateOrderAsync body", body);
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("ScanPayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
if (!payData.IsSet("code_url"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var code_url = payData["code_url"];
|
||||
return code_url;
|
||||
}
|
||||
|
||||
public async Task<string> H5PayCreateOrderAsync(WxH5PayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("H5PayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
if (!payData.IsSet("mweb_url"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var code_url = payData["mweb_url"];
|
||||
return code_url;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> OrderQuery(WxJsPayOrderQueryRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
request.MchId = mchInfo.MchId;
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/orderquery", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
|
||||
if (payData["return_code"].ToString() == "SUCCESS" &&
|
||||
payData["result_code"].ToString() == "SUCCESS")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Pass.PaymentCenter.Model;
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.WxPay
|
||||
{
|
||||
public class WxPayClient
|
||||
{
|
||||
public static readonly string url = "https://api.mch.weixin.qq.com";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public WxPayClient(IHttpClientFactory _HttpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = _HttpClientFactory;
|
||||
}
|
||||
|
||||
public async Task<string> CreatePayOrderAsync(WxJsPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("ScanPayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!payData.IsSet("prepay_id"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var appId = payData["appid"];
|
||||
var package = $"prepay_id={payData["prepay_id"]}";
|
||||
var resp = new WxJsPayInfo(appId, payData.SignType, package, mchInfo.Key);
|
||||
return resp.ToJson();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task<string> JsPayCreateOrderAsync(WxJsPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("ScanPayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!payData.IsSet("prepay_id"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var appId = payData["appid"];
|
||||
var package = $"prepay_id={payData["prepay_id"]}";
|
||||
var resp = new WxJsPayInfo(appId, payData.SignType, package, mchInfo.Key);
|
||||
return resp.ToJson();
|
||||
}
|
||||
|
||||
public async Task<string> ScanPayCreateOrderAsync(WxScanPayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
LogHelper.Info("ScanPayCreateOrderAsync body", body);
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("ScanPayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
if (!payData.IsSet("code_url"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var code_url = payData["code_url"];
|
||||
return code_url;
|
||||
}
|
||||
|
||||
public async Task<string> H5PayCreateOrderAsync(WxH5PayCreateOrderRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/unifiedorder", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
if (payData.IsSet("err_code_des"))
|
||||
{
|
||||
LogHelper.Error("H5PayCreateOrderAsync Error", payData["err_code_des"]);
|
||||
return "";
|
||||
}
|
||||
if (!payData.IsSet("mweb_url"))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var code_url = payData["mweb_url"];
|
||||
return code_url;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> OrderQuery(WxJsPayOrderQueryRequest request, MchInfo mchInfo)
|
||||
{
|
||||
var httpClient = m_HttpClientFactory.CreateClient();
|
||||
request.MchId = mchInfo.MchId;
|
||||
var payData = request.ToPayData();
|
||||
payData.MchKey = mchInfo.Key;
|
||||
var body = payData.ToXml();
|
||||
httpClient.Timeout = TimeSpan.FromMinutes(5);
|
||||
var response = await httpClient
|
||||
.PostAsync($"{url}/pay/orderquery", new StringContent(body));
|
||||
|
||||
var resText = await response.Content.ReadAsStringAsync();
|
||||
payData.FromXml(resText);
|
||||
|
||||
if (payData["return_code"].ToString() == "SUCCESS" &&
|
||||
payData["result_code"].ToString() == "SUCCESS")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,91 +1,91 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信扫码付款
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxScanPayCreateOrderRequest : WxJsPayDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原生JS
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; } = "NATIVE";
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("spbill_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
/// <summary>
|
||||
/// 商品Id
|
||||
/// </summary>
|
||||
[XmlElement("product_id")]
|
||||
public string ProductId { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("time_expire")]
|
||||
public string TimeExpire { get; set; }
|
||||
|
||||
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public int StoreId { get; set; }
|
||||
|
||||
|
||||
public WxScanPayCreateOrderRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.WxPay.WechatJsPay
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信扫码付款
|
||||
/// </summary>
|
||||
[XmlRoot("xml", Namespace = "")]
|
||||
public class WxScanPayCreateOrderRequest : WxJsPayDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户系统内部的订单号 ,5到32个字符、 只能包含字母数字或者下划线,区分大小写,每次下单请求确保在商户系统唯一
|
||||
/// </summary>
|
||||
[XmlElement("out_trade_no")]
|
||||
public string OutTradeNo { get; set; }
|
||||
|
||||
[XmlElement("attach")]
|
||||
public string Attach { get; set; }
|
||||
/// <summary>
|
||||
/// 商品描述
|
||||
/// </summary>
|
||||
[XmlElement("body")]
|
||||
public string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总金额,以分为单位,不允许包含任何字、符号
|
||||
/// </summary>
|
||||
[XmlElement("total_fee")]
|
||||
public int TotalFee { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原生JS
|
||||
/// </summary>
|
||||
[XmlElement("trade_type")]
|
||||
public string TradeType { get; set; } = "NATIVE";
|
||||
|
||||
[XmlElement("notify_url")]
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 公众账号或小程序ID
|
||||
/// </summary>
|
||||
[XmlElement("mch_id")]
|
||||
public string MchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单生成的机器 IP
|
||||
/// </summary>
|
||||
[XmlElement("spbill_create_ip")]
|
||||
public string MchCreateIp { get; set; } = NetworkHelper.GetPublicIp();
|
||||
|
||||
/// <summary>
|
||||
/// 商品Id
|
||||
/// </summary>
|
||||
[XmlElement("product_id")]
|
||||
public string ProductId { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 随机字符串
|
||||
/// </summary>
|
||||
[XmlElement("nonce_str")]
|
||||
public string NonceStr { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 绝对过期时间 yyyyMMddHHmmss
|
||||
/// </summary>
|
||||
[XmlElement("time_expire")]
|
||||
public string TimeExpire { get; set; }
|
||||
|
||||
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public int StoreId { get; set; }
|
||||
|
||||
|
||||
public WxScanPayCreateOrderRequest()
|
||||
{
|
||||
this.NonceStr =this.GenerateNonceStr();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using Newtonsoft.Json;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.WxPay
|
||||
{
|
||||
public class WxScanPayCreateOrderResponse : WxJsPayDataBase
|
||||
{
|
||||
[XmlElement("appId")]
|
||||
public string appId { get; set; }
|
||||
[XmlElement("timeStamp")]
|
||||
public string timeStamp { get; set; }
|
||||
public string nonceStr { get; set; }
|
||||
public string prepay_id { get; set; }
|
||||
public string signType { get; set; }
|
||||
public string paySign { get; set; }
|
||||
[JsonIgnore]
|
||||
public string package => $"prepay_id={this.prepay_id}";
|
||||
}
|
||||
}
|
||||
using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay;
|
||||
using Newtonsoft.Json;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Hncore.Pass.PaymentCenter.Pay.WxPay
|
||||
{
|
||||
public class WxScanPayCreateOrderResponse : WxJsPayDataBase
|
||||
{
|
||||
[XmlElement("appId")]
|
||||
public string appId { get; set; }
|
||||
[XmlElement("timeStamp")]
|
||||
public string timeStamp { get; set; }
|
||||
public string nonceStr { get; set; }
|
||||
public string prepay_id { get; set; }
|
||||
public string signType { get; set; }
|
||||
public string paySign { get; set; }
|
||||
[JsonIgnore]
|
||||
public string package => $"prepay_id={this.prepay_id}";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user