初始提交
This commit is contained in:
166
Services/Hncore.Pass.PaymentCenter/Pay/WxPay/WxJsPayData.cs
Normal file
166
Services/Hncore.Pass.PaymentCenter/Pay/WxPay/WxJsPayData.cs
Normal file
@@ -0,0 +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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user