mirror of
http://git.coreshop.cn/jianweie/coreshoppro.git
synced 2026-03-22 14:17:21 +08:00
添加项目文件。
This commit is contained in:
68
CoreCms.Net.WeChat.Service/Utilities/CheckSignature.cs
Normal file
68
CoreCms.Net.WeChat.Service/Utilities/CheckSignature.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
/***********************************************************************
|
||||
* Project: CoreCms
|
||||
* ProjectName: 核心内容管理系统
|
||||
* Web: https://www.corecms.net
|
||||
* Author: 大灰灰
|
||||
* Email: jianweie@163.com
|
||||
* CreateTime: 2021/7/29 21:44:44
|
||||
* Description: 暂无
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CoreCms.Net.WeChat.Service.Models;
|
||||
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
/// <summary>签名验证类</summary>
|
||||
public class CheckSignature
|
||||
{
|
||||
/// <summary>在网站没有提供Token(或传入为null)的情况下的默认Token,建议在网站中进行配置。</summary>
|
||||
public const string Token = "weixin";
|
||||
|
||||
/// <summary>检查签名是否正确</summary>
|
||||
/// <param name="signature"></param>
|
||||
/// <param name="postModel">需要提供:Timestamp、Nonce、Token</param>
|
||||
/// <returns></returns>
|
||||
public static bool Check(string signature, PostModel postModel) => CheckSignature.Check(signature, postModel.Timestamp, postModel.Nonce, postModel.Token);
|
||||
|
||||
/// <summary>检查签名是否正确</summary>
|
||||
/// <param name="signature"></param>
|
||||
/// <param name="timestamp"></param>
|
||||
/// <param name="nonce"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Check(string signature, string timestamp, string nonce, string token = null) => signature == CheckSignature.GetSignature(timestamp, nonce, token);
|
||||
|
||||
/// <summary>返回正确的签名</summary>
|
||||
/// <param name="postModel">需要提供:Timestamp、Nonce、Token</param>
|
||||
/// <returns></returns>
|
||||
public static string GetSignature(PostModel postModel) => CheckSignature.GetSignature(postModel.Timestamp, postModel.Nonce, postModel.Token);
|
||||
|
||||
/// <summary>返回正确的签名</summary>
|
||||
/// <param name="timestamp"></param>
|
||||
/// <param name="nonce"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetSignature(string timestamp, string nonce, string token = null)
|
||||
{
|
||||
token = token ?? "weixin";
|
||||
string s = string.Join("", ((IEnumerable<string>)new string[3]
|
||||
{
|
||||
token,
|
||||
timestamp,
|
||||
nonce
|
||||
}).OrderBy<string, string>((Func<string, string>)(z => z)).ToArray<string>());
|
||||
byte[] hash = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(s));
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
foreach (byte num in hash)
|
||||
stringBuilder.AppendFormat("{0:x2}", (object)num);
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
232
CoreCms.Net.WeChat.Service/Utilities/Cryptography.cs
Normal file
232
CoreCms.Net.WeChat.Service/Utilities/Cryptography.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
class Cryptography
|
||||
{
|
||||
public static UInt32 HostToNetworkOrder(UInt32 inval)
|
||||
{
|
||||
UInt32 outval = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
outval = (outval << 8) + ((inval >> (i * 8)) & 255);
|
||||
return outval;
|
||||
}
|
||||
|
||||
public static Int32 HostToNetworkOrder(Int32 inval)
|
||||
{
|
||||
Int32 outval = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
outval = (outval << 8) + ((inval >> (i * 8)) & 255);
|
||||
return outval;
|
||||
}
|
||||
/// <summary>
|
||||
/// 解密方法
|
||||
/// </summary>
|
||||
/// <param name="Input">密文</param>
|
||||
/// <param name="EncodingAESKey"></param>
|
||||
/// <returns></returns>
|
||||
///
|
||||
public static string AES_decrypt(String Input, string EncodingAESKey, ref string appid)
|
||||
{
|
||||
byte[] Key;
|
||||
Key = Convert.FromBase64String(EncodingAESKey + "=");
|
||||
byte[] Iv = new byte[16];
|
||||
Array.Copy(Key, Iv, 16);
|
||||
byte[] btmpMsg = AES_decrypt(Input, Iv, Key);
|
||||
|
||||
int len = BitConverter.ToInt32(btmpMsg, 16);
|
||||
len = IPAddress.NetworkToHostOrder(len);
|
||||
|
||||
|
||||
byte[] bMsg = new byte[len];
|
||||
byte[] bAppid = new byte[btmpMsg.Length - 20 - len];
|
||||
Array.Copy(btmpMsg, 20, bMsg, 0, len);
|
||||
Array.Copy(btmpMsg, 20+len , bAppid, 0, btmpMsg.Length - 20 - len);
|
||||
string oriMsg = Encoding.UTF8.GetString(bMsg);
|
||||
appid = Encoding.UTF8.GetString(bAppid);
|
||||
|
||||
|
||||
return oriMsg;
|
||||
}
|
||||
|
||||
public static String AES_encrypt(String Input, string EncodingAESKey, string appid)
|
||||
{
|
||||
byte[] Key;
|
||||
Key = Convert.FromBase64String(EncodingAESKey + "=");
|
||||
byte[] Iv = new byte[16];
|
||||
Array.Copy(Key, Iv, 16);
|
||||
string Randcode = CreateRandCode(16);
|
||||
byte[] bRand = Encoding.UTF8.GetBytes(Randcode);
|
||||
byte[] bAppid = Encoding.UTF8.GetBytes(appid);
|
||||
byte[] btmpMsg = Encoding.UTF8.GetBytes(Input);
|
||||
byte[] bMsgLen = BitConverter.GetBytes(HostToNetworkOrder(btmpMsg.Length));
|
||||
byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bAppid.Length + btmpMsg.Length];
|
||||
|
||||
Array.Copy(bRand, bMsg, bRand.Length);
|
||||
Array.Copy(bMsgLen, 0, bMsg, bRand.Length, bMsgLen.Length);
|
||||
Array.Copy(btmpMsg, 0, bMsg, bRand.Length + bMsgLen.Length, btmpMsg.Length);
|
||||
Array.Copy(bAppid, 0, bMsg, bRand.Length + bMsgLen.Length + btmpMsg.Length, bAppid.Length);
|
||||
|
||||
return AES_encrypt(bMsg, Iv, Key);
|
||||
|
||||
}
|
||||
private static string CreateRandCode(int codeLen)
|
||||
{
|
||||
string codeSerial = "2,3,4,5,6,7,a,c,d,e,f,h,i,j,k,m,n,p,r,s,t,A,C,D,E,F,G,H,J,K,M,N,P,Q,R,S,U,V,W,X,Y,Z";
|
||||
if (codeLen == 0)
|
||||
{
|
||||
codeLen = 16;
|
||||
}
|
||||
string[] arr = codeSerial.Split(',');
|
||||
string code = "";
|
||||
int randValue = -1;
|
||||
Random rand = new Random(unchecked((int)DateTime.Now.Ticks));
|
||||
for (int i = 0; i < codeLen; i++)
|
||||
{
|
||||
randValue = rand.Next(0, arr.Length - 1);
|
||||
code += arr[randValue];
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
private static String AES_encrypt(String Input, byte[] Iv, byte[] Key)
|
||||
{
|
||||
var aes = new RijndaelManaged();
|
||||
//秘钥的大小,以位为单位
|
||||
aes.KeySize = 256;
|
||||
//支持的块大小
|
||||
aes.BlockSize = 128;
|
||||
//填充模式
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Key = Key;
|
||||
aes.IV = Iv;
|
||||
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
|
||||
byte[] xBuff = null;
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
|
||||
{
|
||||
byte[] xXml = Encoding.UTF8.GetBytes(Input);
|
||||
cs.Write(xXml, 0, xXml.Length);
|
||||
}
|
||||
xBuff = ms.ToArray();
|
||||
}
|
||||
String Output = Convert.ToBase64String(xBuff);
|
||||
return Output;
|
||||
}
|
||||
|
||||
private static String AES_encrypt(byte[] Input, byte[] Iv, byte[] Key)
|
||||
{
|
||||
var aes = new RijndaelManaged();
|
||||
//秘钥的大小,以位为单位
|
||||
aes.KeySize = 256;
|
||||
//支持的块大小
|
||||
aes.BlockSize = 128;
|
||||
//填充模式
|
||||
//aes.Padding = PaddingMode.PKCS7;
|
||||
aes.Padding = PaddingMode.None;
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Key = Key;
|
||||
aes.IV = Iv;
|
||||
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
|
||||
byte[] xBuff = null;
|
||||
|
||||
#region 自己进行PKCS7补位,用系统自己带的不行
|
||||
byte[] msg = new byte[Input.Length + 32 - Input.Length % 32];
|
||||
Array.Copy(Input, msg, Input.Length);
|
||||
byte[] pad = KCS7Encoder(Input.Length);
|
||||
Array.Copy(pad, 0, msg, Input.Length, pad.Length);
|
||||
#endregion
|
||||
|
||||
#region 注释的也是一种方法,效果一样
|
||||
//ICryptoTransform transform = aes.CreateEncryptor();
|
||||
//byte[] xBuff = transform.TransformFinalBlock(msg, 0, msg.Length);
|
||||
#endregion
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
|
||||
{
|
||||
cs.Write(msg, 0, msg.Length);
|
||||
}
|
||||
xBuff = ms.ToArray();
|
||||
}
|
||||
|
||||
String Output = Convert.ToBase64String(xBuff);
|
||||
return Output;
|
||||
}
|
||||
|
||||
private static byte[] KCS7Encoder(int text_length)
|
||||
{
|
||||
int block_size = 32;
|
||||
// 计算需要填充的位数
|
||||
int amount_to_pad = block_size - (text_length % block_size);
|
||||
if (amount_to_pad == 0)
|
||||
{
|
||||
amount_to_pad = block_size;
|
||||
}
|
||||
// 获得补位所用的字符
|
||||
char pad_chr = chr(amount_to_pad);
|
||||
string tmp = "";
|
||||
for (int index = 0; index < amount_to_pad; index++)
|
||||
{
|
||||
tmp += pad_chr;
|
||||
}
|
||||
return Encoding.UTF8.GetBytes(tmp);
|
||||
}
|
||||
/**
|
||||
* 将数字转化成ASCII码对应的字符,用于对明文进行补码
|
||||
*
|
||||
* @param a 需要转化的数字
|
||||
* @return 转化得到的字符
|
||||
*/
|
||||
static char chr(int a)
|
||||
{
|
||||
|
||||
byte target = (byte)(a & 0xFF);
|
||||
return (char)target;
|
||||
}
|
||||
private static byte[] AES_decrypt(String Input, byte[] Iv, byte[] Key)
|
||||
{
|
||||
RijndaelManaged aes = new RijndaelManaged();
|
||||
aes.KeySize = 256;
|
||||
aes.BlockSize = 128;
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Padding = PaddingMode.None;
|
||||
aes.Key = Key;
|
||||
aes.IV = Iv;
|
||||
var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||
byte[] xBuff = null;
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
|
||||
{
|
||||
byte[] xXml = Convert.FromBase64String(Input);
|
||||
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
|
||||
Array.Copy(xXml, msg, xXml.Length);
|
||||
cs.Write(xXml, 0, xXml.Length);
|
||||
}
|
||||
xBuff = decode2(ms.ToArray());
|
||||
}
|
||||
return xBuff;
|
||||
}
|
||||
private static byte[] decode2(byte[] decrypted)
|
||||
{
|
||||
int pad = (int)decrypted[decrypted.Length - 1];
|
||||
if (pad < 1 || pad > 32)
|
||||
{
|
||||
pad = 0;
|
||||
}
|
||||
byte[] res = new byte[decrypted.Length - pad];
|
||||
Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
CoreCms.Net.WeChat.Service/Utilities/DateTimeHelper.cs
Normal file
62
CoreCms.Net.WeChat.Service/Utilities/DateTimeHelper.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
/***********************************************************************
|
||||
* Project: CoreCms
|
||||
* ProjectName: 核心内容管理系统
|
||||
* Web: https://www.corecms.net
|
||||
* Author: 大灰灰
|
||||
* Email: jianweie@163.com
|
||||
* CreateTime: 2021/7/29 11:06:40
|
||||
* Description: 暂无
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
/// <summary>微信日期处理帮助类</summary>
|
||||
public class DateTimeHelper
|
||||
{
|
||||
/// <summary>Unix起始时间</summary>
|
||||
public static readonly DateTimeOffset BaseTime = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
|
||||
/// <summary>转换微信DateTime时间到C#时间</summary>
|
||||
/// <param name="dateTimeFromXml">微信DateTime</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetDateTimeFromXml(long dateTimeFromXml) => DateTimeHelper.GetDateTimeOffsetFromXml(dateTimeFromXml).LocalDateTime;
|
||||
|
||||
/// <summary>转换微信DateTime时间到C#时间</summary>
|
||||
/// <param name="dateTimeFromXml">微信DateTime</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetDateTimeFromXml(string dateTimeFromXml) => DateTimeHelper.GetDateTimeFromXml(long.Parse(dateTimeFromXml));
|
||||
|
||||
/// <summary>转换微信DateTimeOffset时间到C#时间</summary>
|
||||
/// <param name="dateTimeFromXml">微信DateTime</param>
|
||||
/// <returns></returns>
|
||||
public static DateTimeOffset GetDateTimeOffsetFromXml(long dateTimeFromXml) => DateTimeHelper.BaseTime.AddSeconds((double)dateTimeFromXml).ToLocalTime();
|
||||
|
||||
/// <summary>转换微信DateTimeOffset时间到C#时间</summary>
|
||||
/// <param name="dateTimeFromXml">微信DateTime</param>
|
||||
/// <returns></returns>
|
||||
public static DateTimeOffset GetDateTimeOffsetFromXml(string dateTimeFromXml) => (DateTimeOffset)DateTimeHelper.GetDateTimeFromXml(long.Parse(dateTimeFromXml));
|
||||
|
||||
/// <summary>获取微信DateTime(UNIX时间戳)</summary>
|
||||
/// <param name="dateTime">时间</param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("请使用 GetUnixDateTime(dateTime) 方法")]
|
||||
public static long GetWeixinDateTime(DateTime dateTime) => DateTimeHelper.GetUnixDateTime(dateTime);
|
||||
|
||||
/// <summary>获取Unix时间戳</summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <returns></returns>
|
||||
public static long GetUnixDateTime(DateTimeOffset dateTime) => (long)(dateTime - DateTimeHelper.BaseTime).TotalSeconds;
|
||||
|
||||
/// <summary>获取Unix时间戳</summary>
|
||||
/// <param name="dateTime"></param>
|
||||
/// <returns></returns>
|
||||
public static long GetUnixDateTime(DateTime dateTime) => (long)((DateTimeOffset)dateTime.ToUniversalTime() - DateTimeHelper.BaseTime).TotalSeconds;
|
||||
}
|
||||
}
|
||||
44
CoreCms.Net.WeChat.Service/Utilities/DocumentExtensions.cs
Normal file
44
CoreCms.Net.WeChat.Service/Utilities/DocumentExtensions.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
/***********************************************************************
|
||||
* Project: CoreCms
|
||||
* ProjectName: 核心内容管理系统
|
||||
* Web: https://www.corecms.net
|
||||
* Author: 大灰灰
|
||||
* Email: jianweie@163.com
|
||||
* CreateTime: 2021/7/29 23:53:54
|
||||
* Description: 暂无
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
public static class DocumentExtensions
|
||||
{
|
||||
public static XmlDocument ToXmlDocument(this XDocument xDocument)
|
||||
{
|
||||
var xmlDocument = new XmlDocument();
|
||||
using (var xmlReader = xDocument.CreateReader())
|
||||
{
|
||||
xmlDocument.Load(xmlReader);
|
||||
}
|
||||
return xmlDocument;
|
||||
}
|
||||
|
||||
public static XDocument ToXDocument(this XmlDocument xmlDocument)
|
||||
{
|
||||
using (var nodeReader = new XmlNodeReader(xmlDocument))
|
||||
{
|
||||
nodeReader.MoveToContent();
|
||||
return XDocument.Load(nodeReader);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
329
CoreCms.Net.WeChat.Service/Utilities/EncryptHelper.cs
Normal file
329
CoreCms.Net.WeChat.Service/Utilities/EncryptHelper.cs
Normal file
@@ -0,0 +1,329 @@
|
||||
/***********************************************************************
|
||||
* Project: CoreCms
|
||||
* ProjectName: 核心内容管理系统
|
||||
* Web: https://www.corecms.net
|
||||
* Author: 大灰灰
|
||||
* Email: jianweie@163.com
|
||||
* CreateTime: 2021/7/29 1:06:57
|
||||
* Description: 暂无
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CoreCms.Net.WeChat.Service.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 签名及加密帮助类
|
||||
/// </summary>
|
||||
public static class EncryptHelper
|
||||
{
|
||||
///// <summary>
|
||||
///// SHA1加密
|
||||
///// </summary>
|
||||
///// <param name="str"></param>
|
||||
///// <returns></returns>
|
||||
//public static string EncryptToSHA1(string str)
|
||||
//{
|
||||
// SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
|
||||
// byte[] str1 = Encoding.UTF8.GetBytes(str);
|
||||
// byte[] str2 = sha1.ComputeHash(str1);
|
||||
// sha1.Clear();
|
||||
// (sha1 as IDisposable).Dispose();
|
||||
// return Convert.ToBase64String(str2);
|
||||
//}
|
||||
|
||||
#region 签名
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获得签名
|
||||
/// </summary>
|
||||
/// <param name="rawData"></param>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetSignature(string rawData, string sessionKey)
|
||||
{
|
||||
var signature = GetSha1(rawData + sessionKey);
|
||||
//Senparc.Weixin.Helpers.EncryptHelper.SHA1_Encrypt(rawData + sessionKey);
|
||||
return signature;
|
||||
}
|
||||
|
||||
/// <summary>采用SHA-1算法加密字符串(小写)</summary>
|
||||
/// <param name="encypStr">需要加密的字符串</param>
|
||||
/// <returns></returns>
|
||||
public static string GetSha1(string encypStr)
|
||||
{
|
||||
byte[] hash = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(encypStr));
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
foreach (byte num in hash)
|
||||
stringBuilder.AppendFormat("{0:x2}", (object)num);
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 比较签名是否正确
|
||||
/// </summary>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <param name="rawData"></param>
|
||||
/// <param name="compareSignature"></param>
|
||||
/// <exception cref="WxOpenException">当SessionId或SessionKey无效时抛出异常</exception>
|
||||
/// <returns></returns>
|
||||
public static bool CheckSignature(string sessionKey, string rawData, string compareSignature)
|
||||
{
|
||||
var signature = GetSignature(rawData, sessionKey);
|
||||
return signature == compareSignature;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 解密
|
||||
|
||||
#region 私有方法
|
||||
|
||||
private static byte[] AES_Decrypt(String Input, byte[] Iv, byte[] Key)
|
||||
{
|
||||
#if NET45
|
||||
RijndaelManaged aes = new RijndaelManaged();
|
||||
#else
|
||||
SymmetricAlgorithm aes = Aes.Create();
|
||||
#endif
|
||||
aes.KeySize = 128;//原始:256
|
||||
aes.BlockSize = 128;
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
aes.Key = Key;
|
||||
aes.IV = Iv;
|
||||
var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||
byte[] xBuff = null;
|
||||
|
||||
//using (ICryptoTransform decrypt = aes.CreateDecryptor(aes.Key, aes.IV) /*aes.CreateDecryptor()*/)
|
||||
//{
|
||||
// var src = Convert.FromBase64String(Input);
|
||||
// byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
|
||||
// return dest;
|
||||
// //return Encoding.UTF8.GetString(dest);
|
||||
//}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
|
||||
{
|
||||
//cs.Read(decryptBytes, 0, decryptBytes.Length);
|
||||
//cs.Close();
|
||||
//ms.Close();
|
||||
|
||||
//cs.FlushFinalBlock();//用于解决第二次获取小程序Session解密出错的情况
|
||||
|
||||
|
||||
byte[] xXml = Convert.FromBase64String(Input);
|
||||
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
|
||||
Array.Copy(xXml, msg, xXml.Length);
|
||||
cs.Write(xXml, 0, xXml.Length);
|
||||
}
|
||||
//cs.Dispose();
|
||||
xBuff = decode2(ms.ToArray());
|
||||
}
|
||||
}
|
||||
catch (System.Security.Cryptography.CryptographicException)
|
||||
{
|
||||
//Padding is invalid and cannot be removed.
|
||||
Console.WriteLine("===== CryptographicException =====");
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
//cs 不自动释放,用于避免“Padding is invalid and cannot be removed”的错误 —— 2019.07.27 Jeffrey
|
||||
var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write);
|
||||
{
|
||||
//cs.Read(decryptBytes, 0, decryptBytes.Length);
|
||||
//cs.Close();
|
||||
//ms.Close();
|
||||
|
||||
//cs.FlushFinalBlock();//用于解决第二次获取小程序Session解密出错的情况
|
||||
|
||||
byte[] xXml = Convert.FromBase64String(Input);
|
||||
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
|
||||
Array.Copy(xXml, msg, xXml.Length);
|
||||
cs.Write(xXml, 0, xXml.Length);
|
||||
}
|
||||
//cs.Dispose();
|
||||
xBuff = decode2(ms.ToArray());
|
||||
}
|
||||
}
|
||||
return xBuff;
|
||||
}
|
||||
|
||||
private static byte[] decode2(byte[] decrypted)
|
||||
{
|
||||
int pad = (int)decrypted[decrypted.Length - 1];
|
||||
if (pad < 1 || pad > 32)
|
||||
{
|
||||
pad = 0;
|
||||
}
|
||||
byte[] res = new byte[decrypted.Length - pad];
|
||||
Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 解密所有消息的基础方法
|
||||
/// </summary>
|
||||
/// <param name="sessionKey">储存在 SessionBag 中的当前用户 会话 SessionKey</param>
|
||||
/// <param name="encryptedData">接口返回数据中的 encryptedData 参数</param>
|
||||
/// <param name="iv">接口返回数据中的 iv 参数,对称解密算法初始向量</param>
|
||||
/// <returns></returns>
|
||||
public static string DecodeEncryptedData(string sessionKey, string encryptedData, string iv)
|
||||
{
|
||||
//var aesCipher = Convert.FromBase64String(encryptedData);
|
||||
var aesKey = Convert.FromBase64String(sessionKey);
|
||||
var aesIV = Convert.FromBase64String(iv);
|
||||
|
||||
var result = AES_Decrypt(encryptedData, aesIV, aesKey);
|
||||
var resultStr = Encoding.UTF8.GetString(result);
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解密消息(通过SessionId获取)
|
||||
/// </summary>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <param name="encryptedData"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <exception cref="WxOpenException">当SessionId或SessionKey无效时抛出异常</exception>
|
||||
/// <returns></returns>
|
||||
public static string DecodeEncryptedDataBySessionId(string sessionKey, string encryptedData, string iv)
|
||||
{
|
||||
var resultStr = DecodeEncryptedData(sessionKey, encryptedData, iv);
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查解密消息水印
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="appId"></param>
|
||||
/// <returns>entity为null时也会返回false</returns>
|
||||
public static bool CheckWatermark(this DecodeEntityBase entity, string appId)
|
||||
{
|
||||
if (entity == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return entity.watermark.appid == appId;
|
||||
}
|
||||
|
||||
#region 解密实例信息
|
||||
|
||||
/// <summary>
|
||||
/// 解密到实例信息
|
||||
/// </summary>
|
||||
/// <typeparam name="T">DecodeEntityBase</typeparam>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <param name="encryptedData"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <returns></returns>
|
||||
public static T DecodeEncryptedDataToEntity<T>(string sessionKey, string encryptedData, string iv)
|
||||
{
|
||||
var jsonStr = DecodeEncryptedDataBySessionId(sessionKey, encryptedData, iv);
|
||||
|
||||
//Console.WriteLine("===== jsonStr =====");
|
||||
//Console.WriteLine(jsonStr);
|
||||
//Console.WriteLine();
|
||||
|
||||
var entity = JsonConvert.DeserializeObject<T>(jsonStr);
|
||||
return entity;
|
||||
}
|
||||
/// <summary>
|
||||
/// 解密到实例信息
|
||||
/// </summary>
|
||||
/// <typeparam name="T">DecodeEntityBase</typeparam>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <param name="encryptedData"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <returns></returns>
|
||||
public static T DecodeEncryptedDataToEntityEasy<T>(string sessionKey, string encryptedData, string iv)
|
||||
{
|
||||
var jsonStr = DecodeEncryptedData(sessionKey, encryptedData, iv);
|
||||
var entity = JsonConvert.DeserializeObject<T>(jsonStr);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解密UserInfo消息(通过SessionId获取)
|
||||
/// </summary>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <param name="encryptedData"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <exception cref="WxOpenException">当SessionId或SessionKey无效时抛出异常</exception>
|
||||
/// <returns></returns>
|
||||
public static DecodedUserInfo DecodeUserInfoBySessionId(string sessionKey, string encryptedData, string iv)
|
||||
{
|
||||
return DecodeEncryptedDataToEntity<DecodedUserInfo>(sessionKey, encryptedData, iv);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解密手机号
|
||||
/// </summary>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <param name="encryptedData"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <returns></returns>
|
||||
public static DecodedPhoneNumber DecryptPhoneNumber(string sessionKey, string encryptedData, string iv)
|
||||
{
|
||||
return DecodeEncryptedDataToEntity<DecodedPhoneNumber>(sessionKey, encryptedData, iv);
|
||||
}
|
||||
/// <summary>
|
||||
/// 解密手机号(根据sessionKey解密)
|
||||
/// </summary>
|
||||
/// <param name="sessionKey"></param>
|
||||
/// <param name="encryptedData"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <returns></returns>
|
||||
public static DecodedPhoneNumber DecryptPhoneNumberBySessionKey(string sessionKey, string encryptedData, string iv)
|
||||
{
|
||||
//var resultStr = DecodeEncryptedData(sessionKey, encryptedData, iv);
|
||||
|
||||
//var entity = SerializerHelper.GetObject<DecodedPhoneNumber>(resultStr);
|
||||
//return entity;
|
||||
|
||||
return DecodeEncryptedDataToEntityEasy<DecodedPhoneNumber>(sessionKey, encryptedData, iv);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解密微信小程序运动步数
|
||||
/// 2019-04-02
|
||||
/// </summary>
|
||||
/// <param name="sessionId"></param>
|
||||
/// <param name="encryptedData"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <returns></returns>
|
||||
public static DecodedRunData DecryptRunData(string sessionId, string encryptedData, string iv)
|
||||
{
|
||||
return DecodeEncryptedDataToEntity<DecodedRunData>(sessionId, encryptedData, iv);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
76
CoreCms.Net.WeChat.Service/Utilities/RequestUtility.cs
Normal file
76
CoreCms.Net.WeChat.Service/Utilities/RequestUtility.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
/***********************************************************************
|
||||
* Project: CoreCms
|
||||
* ProjectName: 核心内容管理系统
|
||||
* Web: https://www.corecms.net
|
||||
* Author: 大灰灰
|
||||
* Email: jianweie@163.com
|
||||
* CreateTime: 2021/7/29 23:24:45
|
||||
* Description: 暂无
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
/// <summary>HTTP 请求工具类</summary>
|
||||
public static class RequestUtility
|
||||
{
|
||||
/// <summary>【异步方法】从 Request.Body 中读取流,并复制到一个独立的 MemoryStream 对象中</summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="allowSynchronousIO"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<Stream> GetRequestMemoryStreamAsync(
|
||||
this HttpRequest request,
|
||||
bool? allowSynchronousIO = true)
|
||||
{
|
||||
IHttpBodyControlFeature bodyControlFeature = request.HttpContext.Features.Get<IHttpBodyControlFeature>();
|
||||
if (bodyControlFeature != null && allowSynchronousIO.HasValue)
|
||||
bodyControlFeature.AllowSynchronousIO = allowSynchronousIO.Value;
|
||||
return (Stream)new MemoryStream(Encoding.UTF8.GetBytes(await new StreamReader(request.Body).ReadToEndAsync()));
|
||||
}
|
||||
|
||||
/// <summary>从 Request.Body 中读取流,并复制到一个独立的 MemoryStream 对象中</summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="allowSynchronousIO"></param>
|
||||
/// <returns></returns>
|
||||
public static Stream GetRequestStream(
|
||||
this HttpRequest request,
|
||||
bool? allowSynchronousIO = true)
|
||||
{
|
||||
IHttpBodyControlFeature bodyControlFeature = request.HttpContext.Features.Get<IHttpBodyControlFeature>();
|
||||
if (bodyControlFeature != null && allowSynchronousIO.HasValue)
|
||||
bodyControlFeature.AllowSynchronousIO = allowSynchronousIO.Value;
|
||||
return (Stream)new MemoryStream(Encoding.UTF8.GetBytes(new StreamReader(request.Body).ReadToEnd()));
|
||||
}
|
||||
|
||||
/// <summary>从 Request.Body 中读取流,并复制到一个独立的 MemoryStream 对象中</summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="allowSynchronousIO"></param>
|
||||
/// <returns></returns>
|
||||
public static MemoryStream GetRequestMemoryStream(
|
||||
this HttpRequest request,
|
||||
bool? allowSynchronousIO = true)
|
||||
{
|
||||
IHttpBodyControlFeature bodyControlFeature = request.HttpContext.Features.Get<IHttpBodyControlFeature>();
|
||||
if (bodyControlFeature != null && allowSynchronousIO.HasValue)
|
||||
bodyControlFeature.AllowSynchronousIO = allowSynchronousIO.Value;
|
||||
return new MemoryStream(Encoding.UTF8.GetBytes(new StreamReader(request.Body).ReadToEnd()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
221
CoreCms.Net.WeChat.Service/Utilities/WXBizMsgCrypt.cs
Normal file
221
CoreCms.Net.WeChat.Service/Utilities/WXBizMsgCrypt.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Collections;
|
||||
//using System.Web;
|
||||
using System.Security.Cryptography;
|
||||
//-40001 : 签名验证错误
|
||||
//-40002 : xml解析失败
|
||||
//-40003 : sha加密生成签名失败
|
||||
//-40004 : AESKey 非法
|
||||
//-40005 : appid 校验错误
|
||||
//-40006 : AES 加密失败
|
||||
//-40007 : AES 解密失败
|
||||
//-40008 : 解密后得到的buffer非法
|
||||
//-40009 : base64加密异常
|
||||
//-40010 : base64解密异常
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
public class WXBizMsgCrypt
|
||||
{
|
||||
string m_sToken;
|
||||
string m_sEncodingAESKey;
|
||||
string m_sAppID;
|
||||
enum WXBizMsgCryptErrorCode
|
||||
{
|
||||
WXBizMsgCrypt_OK = 0,
|
||||
WXBizMsgCrypt_ValidateSignature_Error = -40001,
|
||||
WXBizMsgCrypt_ParseXml_Error = -40002,
|
||||
WXBizMsgCrypt_ComputeSignature_Error = -40003,
|
||||
WXBizMsgCrypt_IllegalAesKey = -40004,
|
||||
WXBizMsgCrypt_ValidateAppid_Error = -40005,
|
||||
WXBizMsgCrypt_EncryptAES_Error = -40006,
|
||||
WXBizMsgCrypt_DecryptAES_Error = -40007,
|
||||
WXBizMsgCrypt_IllegalBuffer = -40008,
|
||||
WXBizMsgCrypt_EncodeBase64_Error = -40009,
|
||||
WXBizMsgCrypt_DecodeBase64_Error = -40010
|
||||
};
|
||||
|
||||
//构造函数
|
||||
// @param sToken: 公众平台上,开发者设置的Token
|
||||
// @param sEncodingAESKey: 公众平台上,开发者设置的EncodingAESKey
|
||||
// @param sAppID: 公众帐号的appid
|
||||
public WXBizMsgCrypt(string sToken, string sEncodingAESKey, string sAppID)
|
||||
{
|
||||
m_sToken = sToken;
|
||||
m_sAppID = sAppID;
|
||||
m_sEncodingAESKey = sEncodingAESKey;
|
||||
}
|
||||
|
||||
|
||||
// 检验消息的真实性,并且获取解密后的明文
|
||||
// @param sMsgSignature: 签名串,对应URL参数的msg_signature
|
||||
// @param sTimeStamp: 时间戳,对应URL参数的timestamp
|
||||
// @param sNonce: 随机串,对应URL参数的nonce
|
||||
// @param sPostData: 密文,对应POST请求的数据
|
||||
// @param sMsg: 解密后的原文,当return返回0时有效
|
||||
// @return: 成功0,失败返回对应的错误码
|
||||
public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
|
||||
{
|
||||
if (m_sEncodingAESKey.Length != 43)
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
|
||||
}
|
||||
XmlDocument doc = new XmlDocument();
|
||||
XmlNode root;
|
||||
string sEncryptMsg;
|
||||
try
|
||||
{
|
||||
doc.LoadXml(sPostData);
|
||||
root = doc.FirstChild;
|
||||
sEncryptMsg = root["Encrypt"].InnerText;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ParseXml_Error;
|
||||
}
|
||||
//verify signature
|
||||
int ret = 0;
|
||||
ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
//decrypt
|
||||
string cpid = "";
|
||||
try
|
||||
{
|
||||
sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error;
|
||||
}
|
||||
if (cpid != m_sAppID)
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateAppid_Error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//将企业号回复用户的消息加密打包
|
||||
// @param sReplyMsg: 企业号待回复用户的消息,xml格式的字符串
|
||||
// @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp
|
||||
// @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce
|
||||
// @param sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
|
||||
// 当return返回0时有效
|
||||
// return:成功0,失败返回对应的错误码
|
||||
public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg)
|
||||
{
|
||||
if (m_sEncodingAESKey.Length != 43)
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
|
||||
}
|
||||
string raw = "";
|
||||
try
|
||||
{
|
||||
raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sAppID);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_EncryptAES_Error;
|
||||
}
|
||||
string MsgSigature = "";
|
||||
int ret = 0;
|
||||
ret = GenarateSinature(m_sToken, sTimeStamp, sNonce, raw, ref MsgSigature);
|
||||
if (0 != ret)
|
||||
return ret;
|
||||
sEncryptMsg = "";
|
||||
|
||||
string EncryptLabelHead = "<Encrypt><![CDATA[";
|
||||
string EncryptLabelTail = "]]></Encrypt>";
|
||||
string MsgSigLabelHead = "<MsgSignature><![CDATA[";
|
||||
string MsgSigLabelTail = "]]></MsgSignature>";
|
||||
string TimeStampLabelHead = "<TimeStamp><![CDATA[";
|
||||
string TimeStampLabelTail = "]]></TimeStamp>";
|
||||
string NonceLabelHead = "<Nonce><![CDATA[";
|
||||
string NonceLabelTail = "]]></Nonce>";
|
||||
sEncryptMsg = sEncryptMsg + "<xml>" + EncryptLabelHead + raw + EncryptLabelTail;
|
||||
sEncryptMsg = sEncryptMsg + MsgSigLabelHead + MsgSigature + MsgSigLabelTail;
|
||||
sEncryptMsg = sEncryptMsg + TimeStampLabelHead + sTimeStamp + TimeStampLabelTail;
|
||||
sEncryptMsg = sEncryptMsg + NonceLabelHead + sNonce + NonceLabelTail;
|
||||
sEncryptMsg += "</xml>";
|
||||
return 0;
|
||||
}
|
||||
|
||||
public class DictionarySort : System.Collections.IComparer
|
||||
{
|
||||
public int Compare(object oLeft, object oRight)
|
||||
{
|
||||
string sLeft = oLeft as string;
|
||||
string sRight = oRight as string;
|
||||
int iLeftLength = sLeft.Length;
|
||||
int iRightLength = sRight.Length;
|
||||
int index = 0;
|
||||
while (index < iLeftLength && index < iRightLength)
|
||||
{
|
||||
if (sLeft[index] < sRight[index])
|
||||
return -1;
|
||||
else if (sLeft[index] > sRight[index])
|
||||
return 1;
|
||||
else
|
||||
index++;
|
||||
}
|
||||
return iLeftLength - iRightLength;
|
||||
|
||||
}
|
||||
}
|
||||
//Verify Signature
|
||||
private static int VerifySignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, string sSigture)
|
||||
{
|
||||
string hash = "";
|
||||
int ret = 0;
|
||||
ret = GenarateSinature(sToken, sTimeStamp, sNonce, sMsgEncrypt, ref hash);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
//System.Console.WriteLine(hash);
|
||||
if (hash == sSigture)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateSignature_Error;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GenarateSinature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, ref string sMsgSignature)
|
||||
{
|
||||
ArrayList AL = new ArrayList();
|
||||
AL.Add(sToken);
|
||||
AL.Add(sTimeStamp);
|
||||
AL.Add(sNonce);
|
||||
AL.Add(sMsgEncrypt);
|
||||
AL.Sort(new DictionarySort());
|
||||
string raw = "";
|
||||
for (int i = 0; i < AL.Count; ++i)
|
||||
{
|
||||
raw += AL[i];
|
||||
}
|
||||
|
||||
SHA1 sha;
|
||||
ASCIIEncoding enc;
|
||||
string hash = "";
|
||||
try
|
||||
{
|
||||
sha = new SHA1CryptoServiceProvider();
|
||||
enc = new ASCIIEncoding();
|
||||
byte[] dataToHash = enc.GetBytes(raw);
|
||||
byte[] dataHashed = sha.ComputeHash(dataToHash);
|
||||
hash = BitConverter.ToString(dataHashed).Replace("-", "");
|
||||
hash = hash.ToLower();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ComputeSignature_Error;
|
||||
}
|
||||
sMsgSignature = hash;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
CoreCms.Net.WeChat.Service/Utilities/WxOfficialHelper.cs
Normal file
33
CoreCms.Net.WeChat.Service/Utilities/WxOfficialHelper.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
/***********************************************************************
|
||||
* Project: CoreCms
|
||||
* ProjectName: 核心内容管理系统
|
||||
* Web: https://www.corecms.net
|
||||
* Author: 大灰灰
|
||||
* Email: jianweie@163.com
|
||||
* CreateTime: 2021/7/29 12:25:49
|
||||
* Description: 暂无
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信公众号帮助类
|
||||
/// </summary>
|
||||
public static class WxOfficialHelper
|
||||
{
|
||||
|
||||
public static string geturl(string url, string weXinAppId, int scope = 1)
|
||||
{
|
||||
|
||||
return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + weXinAppId + "&redirect_uri=" + url + "&response_type=code&scope=" + scope + "&state=jshop#wechat_redirect";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
97
CoreCms.Net.WeChat.Service/Utilities/XmlUtility.cs
Normal file
97
CoreCms.Net.WeChat.Service/Utilities/XmlUtility.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
/***********************************************************************
|
||||
* Project: CoreCms
|
||||
* ProjectName: 核心内容管理系统
|
||||
* Web: https://www.corecms.net
|
||||
* Author: 大灰灰
|
||||
* Email: jianweie@163.com
|
||||
* CreateTime: 2021/7/29 23:21:06
|
||||
* Description: 暂无
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace CoreCms.Net.WeChat.Service.Utilities
|
||||
{
|
||||
/// <summary>XML 工具类</summary>
|
||||
public static class XmlUtility
|
||||
{
|
||||
/// <summary>反序列化</summary>
|
||||
/// <param name="xml">XML字符串</param>
|
||||
/// <returns></returns>
|
||||
public static object Deserialize<T>(string xml)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (StringReader stringReader = new StringReader(xml))
|
||||
return new XmlSerializer(typeof(T)).Deserialize((TextReader)stringReader);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine((object)ex);
|
||||
return (object)null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>反序列化</summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <returns></returns>
|
||||
public static object Deserialize<T>(Stream stream) => new XmlSerializer(typeof(T)).Deserialize(stream);
|
||||
|
||||
/// <summary>
|
||||
/// 序列化
|
||||
/// 说明:此方法序列化复杂类,如果没有声明XmlInclude等特性,可能会引发“使用 XmlInclude 或 SoapInclude 特性静态指定非已知的类型。”的错误。
|
||||
/// </summary>
|
||||
/// <param name="obj">对象</param>
|
||||
/// <returns></returns>
|
||||
public static string Serializer<T>(T obj)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
|
||||
try
|
||||
{
|
||||
xmlSerializer.Serialize((Stream)memoryStream, (object)obj);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
memoryStream.Position = 0L;
|
||||
StreamReader streamReader = new StreamReader((Stream)memoryStream);
|
||||
string end = streamReader.ReadToEnd();
|
||||
streamReader.Dispose();
|
||||
memoryStream.Dispose();
|
||||
return end;
|
||||
}
|
||||
|
||||
/// <summary>序列化将流转成XML字符串</summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <returns></returns>
|
||||
public static XDocument Convert(Stream stream)
|
||||
{
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
using (XmlReader reader = XmlReader.Create(stream))
|
||||
return XDocument.Load(reader);
|
||||
}
|
||||
|
||||
/// <summary>序列化将流转成XML字符串</summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <returns></returns>
|
||||
public static string ConvertToString(Stream stream)
|
||||
{
|
||||
StreamReader reader = new StreamReader(stream);
|
||||
string sHtml = reader.ReadToEnd();
|
||||
return sHtml;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user