This commit is contained in:
PastSaid
2024-04-29 17:57:07 +08:00
parent e1e6cba475
commit 16fbd10312
123 changed files with 5923 additions and 18677 deletions

View File

@@ -0,0 +1,255 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace E_ZKEccTopSdk.Uitl
{
/// <summary>
/// 文件元数据。
/// 可以使用以下几种构造方法:
/// 本地路径new FileItem("C:/temp.jpg");
/// 本地文件new FileItem(new FileInfo("C:/temp.jpg"));
/// 字节数组new FileItem("abc.jpg", bytes);
/// 输入流new FileItem("abc.jpg", stream);
/// </summary>
public class FileItem
{
private Contract contract;
/// <summary>
/// 基于本地文件的构造器。
/// </summary>
/// <param name="fileInfo">本地文件</param>
public FileItem(FileInfo fileInfo)
{
this.contract = new LocalContract(fileInfo);
}
/// <summary>
/// 基于本地文件全路径的构造器。
/// </summary>
/// <param name="filePath">本地文件全路径</param>
public FileItem(string filePath) : this(new FileInfo(filePath))
{
}
/// <summary>
/// 基于文件名和字节数组的构造器。
/// </summary>
/// <param name="fileName">文件名称(服务端持久化字节数组到磁盘时的文件名)</param>
/// <param name="content">文件字节数组</param>
public FileItem(string fileName, byte[] content) : this(fileName, content, null)
{
}
/// <summary>
/// 基于文件名、字节数组和媒体类型的构造器。
/// </summary>
/// <param name="fileName">文件名(服务端持久化字节数组到磁盘时的文件名)</param>
/// <param name="content">文件字字节数组</param>
/// <param name="mimeType">媒体类型</param>
public FileItem(string fileName, byte[] content, string mimeType)
{
this.contract = new ByteArrayContract(fileName, content, mimeType);
}
/// <summary>
/// 基于文件名和输入流的构造器。
/// </summary>
/// <param name="fileName">文件名称(服务端持久化输入流到磁盘时的文件名)</param>
/// <param name="content">文件输入流</param>
public FileItem(string fileName, Stream stream) : this(fileName, stream, null)
{
}
/// <summary>
/// 基于文件名、输入流和媒体类型的构造器。
/// </summary>
/// <param name="fileName">文件名(服务端持久化输入流到磁盘时的文件名)</param>
/// <param name="content">文件输入流</param>
/// <param name="mimeType">媒体类型</param>
public FileItem(string fileName, Stream stream, string mimeType)
{
this.contract = new StreamContract(fileName, stream, mimeType);
}
public bool IsValid()
{
return this.contract.IsValid();
}
public long GetFileLength()
{
return this.contract.GetFileLength();
}
public string GetFileName()
{
return this.contract.GetFileName();
}
public string GetMimeType()
{
return this.contract.GetMimeType();
}
public void Write(Stream output)
{
this.contract.Write(output);
}
}
internal interface Contract
{
bool IsValid();
string GetFileName();
string GetMimeType();
long GetFileLength();
void Write(Stream output);
}
internal class LocalContract : Contract
{
private FileInfo fileInfo;
public LocalContract(FileInfo fileInfo)
{
this.fileInfo = fileInfo;
}
public long GetFileLength()
{
return this.fileInfo.Length;
}
public string GetFileName()
{
return this.fileInfo.Name;
}
public string GetMimeType()
{
return Constants.CTYPE_DEFAULT;
}
public bool IsValid()
{
return this.fileInfo != null && this.fileInfo.Exists;
}
public void Write(Stream output)
{
using (BufferedStream bfs = new BufferedStream(this.fileInfo.OpenRead()))
{
int n = 0;
byte[] buffer = new byte[Constants.READ_BUFFER_SIZE];
while ((n = bfs.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, n);
}
}
}
}
internal class ByteArrayContract : Contract
{
private string fileName;
private byte[] content;
private string mimeType;
public ByteArrayContract(string fileName, byte[] content, string mimeType)
{
this.fileName = fileName;
this.content = content;
this.mimeType = mimeType;
}
public bool IsValid()
{
return this.content != null && this.fileName != null;
}
public long GetFileLength()
{
return this.content.Length;
}
public string GetFileName()
{
return this.fileName;
}
public string GetMimeType()
{
if (string.IsNullOrEmpty(this.mimeType))
{
return Constants.CTYPE_DEFAULT;
}
else
{
return this.mimeType;
}
}
public void Write(Stream output)
{
output.Write(this.content, 0, this.content.Length);
}
}
internal class StreamContract : Contract
{
private string fileName;
private Stream stream;
private string mimeType;
public StreamContract(string fileName, Stream stream, string mimeType)
{
this.fileName = fileName;
this.stream = stream;
this.mimeType = mimeType;
}
public long GetFileLength()
{
return 0L;
}
public string GetFileName()
{
return this.fileName;
}
public string GetMimeType()
{
if (string.IsNullOrEmpty(mimeType))
{
return Constants.CTYPE_DEFAULT;
}
else
{
return this.mimeType;
}
}
public bool IsValid()
{
return this.stream != null && this.fileName != null;
}
public void Write(Stream output)
{
using (this.stream)
{
int n = 0;
byte[] buffer = new byte[Constants.READ_BUFFER_SIZE];
while ((n = this.stream.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, n);
}
}
}
}
}

View File

@@ -0,0 +1,200 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace E_ZKEccTopSdk.Uitl
{
/// <summary>
/// 请求验证器
/// </summary>
public sealed class RequestValidator
{
private const string ERR_CODE_PARAM_MISSING = "40";
private const string ERR_CODE_PARAM_INVALID = "41";
private const string ERR_MSG_PARAM_MISSING = "client-error:Missing required arguments:{0}";
private const string ERR_MSG_PARAM_INVALID = "client-error:Invalid arguments:{0}";
/// <summary>
/// 验证参数是否为空。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
public static void ValidateRequired(string name, object value)
{
if (value == null)
{
throw new TopException(ERR_CODE_PARAM_MISSING, string.Format(ERR_MSG_PARAM_MISSING, name));
}
else
{
if (value.GetType() == typeof(string))
{
string strValue = value as string;
if (string.IsNullOrEmpty(strValue))
{
throw new TopException(ERR_CODE_PARAM_MISSING, string.Format(ERR_MSG_PARAM_MISSING, name));
}
}
}
}
/// <summary>
/// 验证字符串参数的最大长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxLength">最大长度</param>
public static void ValidateMaxLength(string name, string value, int maxLength)
{
if (value != null && value.Length > maxLength)
{
throw new TopException(ERR_CODE_PARAM_INVALID, string.Format(ERR_MSG_PARAM_INVALID, name));
}
}
/// <summary>
/// 验证上传文件的最大字节长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxLength">最大长度</param>
public static void ValidateMaxLength(string name, FileItem value, int maxLength)
{
if (value != null && value.GetFileLength() > maxLength)
{
throw new TopException(ERR_CODE_PARAM_INVALID, string.Format(ERR_MSG_PARAM_INVALID, name));
}
}
/// <summary>
/// 验证以逗号分隔的字符串参数的最大列表长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxSize">最大列表长度</param>
public static void ValidateMaxListSize(string name, string value, int maxSize)
{
if (value != null)
{
string[] data = value.Split(',');
if (data != null && data.Length > maxSize)
{
throw new TopException(ERR_CODE_PARAM_INVALID, string.Format(ERR_MSG_PARAM_INVALID, name));
}
}
}
/// <summary>
/// 验证以逗号分隔的字符串参数的最大列表长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxSize">最大列表长度</param>
public static void ValidateMaxListSize(string name, List<string> value, int maxSize)
{
if (value != null)
{
if (value != null && value.Count > maxSize)
{
throw new TopException(ERR_CODE_PARAM_INVALID, ERR_MSG_PARAM_INVALID);
}
}
}
/// <summary>
/// 验证以逗号分隔的字符串参数的最大列表长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxSize">最大列表长度</param>
public static void ValidateMaxListSize(string name, List<long> value, int maxSize)
{
if (value != null)
{
if (value != null && value.Count > maxSize)
{
throw new TopException(ERR_CODE_PARAM_INVALID, ERR_MSG_PARAM_INVALID);
}
}
}
/// <summary>
/// 验证以逗号分隔的字符串参数的最大列表长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxSize">最大列表长度</param>
public static void ValidateMaxListSize(string name, List<bool> value, int maxSize)
{
if (value != null)
{
if (value != null && value.Count > maxSize)
{
throw new TopException(ERR_CODE_PARAM_INVALID, ERR_MSG_PARAM_INVALID);
}
}
}
/// <summary>
/// 验证复杂结构数组参数的最大列表长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxSize">最大列表长度</param>
public static void ValidateObjectMaxListSize(string name, string value, int maxSize)
{
if (value != null)
{
IList list = JSON.Parse(value) as IList;
if (list != null && list.Count > maxSize)
{
throw new TopException(ERR_CODE_PARAM_INVALID, string.Format(ERR_MSG_PARAM_INVALID, name));
}
}
}
/// <summary>
/// 验证字符串参数的最小长度。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="minLength">最小长度</param>
public static void ValidateMinLength(string name, string value, int minLength)
{
if (value != null && value.Length < minLength)
{
throw new TopException(ERR_CODE_PARAM_INVALID, string.Format(ERR_MSG_PARAM_INVALID, name));
}
}
/// <summary>
/// 验证数字参数的最大值。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="maxValue">最大值</param>
public static void ValidateMaxValue(string name, Nullable<long> value, long maxValue)
{
if (value != null && value > maxValue)
{
throw new TopException(ERR_CODE_PARAM_INVALID, string.Format(ERR_MSG_PARAM_INVALID, name));
}
}
/// <summary>
/// 验证数字参数的最小值。
/// </summary>
/// <param name="name">参数名</param>
/// <param name="value">参数值</param>
/// <param name="minValue">最小值</param>
public static void ValidateMinValue(string name, Nullable<long> value, long minValue)
{
if (value != null && value < minValue)
{
throw new TopException(ERR_CODE_PARAM_INVALID, string.Format(ERR_MSG_PARAM_INVALID, name));
}
}
}
}

View File

@@ -0,0 +1,271 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
namespace E_ZKEccTopSdk.Uitl
{
/// <summary>
/// TOP系统工具类。
/// </summary>
public abstract class TopUtils
{
private static readonly JSONParameters jp = new JSONParameters();
private static string intranetIp;
static TopUtils()
{
jp.UseApiNamingStyle = true;
jp.UseExtensions = false;
jp.SerializeNullValues = false;
}
/// <summary>
/// 给TOP请求签名。
/// </summary>
/// <param name="parameters">所有字符型的TOP请求参数</param>
/// <param name="secret">签名密钥</param>
/// <param name="signMethod">签名方法可选值md5, hmac</param>
/// <returns>签名</returns>
public static string SignTopRequest(IDictionary<string, string> parameters, string secret, string signMethod)
{
return SignTopRequest(parameters, null, secret, signMethod);
}
/// <summary>
/// 给TOP请求签名。
/// </summary>
/// <param name="parameters">所有字符型的TOP请求参数</param>
/// <param name="body">请求主体内容</param>
/// <param name="secret">签名密钥</param>
/// <param name="signMethod">签名方法可选值md5, hmac</param>
/// <returns>签名</returns>
public static string SignTopRequest(IDictionary<string, string> parameters, string body, string secret, string signMethod)
{
// 第一步把字典按Key的字母顺序排序
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
// 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder();
if (Constants.SIGN_METHOD_MD5.Equals(signMethod))
{
query.Append(secret);
}
foreach (KeyValuePair<string, string> kv in sortedParams)
{
if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value))
{
query.Append(kv.Key).Append(kv.Value);
}
}
// 第三步:把请求主体拼接在参数后面
if (!string.IsNullOrEmpty(body))
{
query.Append(body);
}
// 第四步使用MD5/HMAC加密
byte[] bytes;
if (Constants.SIGN_METHOD_HMAC.Equals(signMethod))
{
HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret));
bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
}
else if (Constants.SIGN_METHOD_HMAC_SHA256.Equals(signMethod))
{
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
}
else
{
query.Append(secret);
MD5 md5 = MD5.Create();
bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
}
// 第五步:把二进制转化为大写的十六进制
StringBuilder result = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
result.Append(bytes[i].ToString("X2"));
}
return result.ToString();
}
/// <summary>
/// 清除字典中值为空的项。
/// </summary>
/// <param name="dict">待清除的字典</param>
/// <returns>清除后的字典</returns>
public static IDictionary<string, T> CleanupDictionary<T>(IDictionary<string, T> dict)
{
IDictionary<string, T> newDict = new Dictionary<string, T>(dict.Count);
foreach (KeyValuePair<string, T> kv in dict)
{
if (kv.Value != null)
{
newDict.Add(kv.Key, kv.Value);
}
}
return newDict;
}
/// <summary>
/// 把对象转换为JSON字符串。
/// </summary>
public static string ObjectToJson(object obj)
{
return JSON.ToJSON(obj, jp);
}
/// <summary>
/// 把对象转换为JSON字符串。
/// </summary>
public static string ObjectToJson(object obj, JSONParameters newjp)
{
return JSON.ToJSON(obj, newjp);
}
/// <summary>
/// 把JSON字符串转换为对象。
/// </summary>
public static object JsonToObject(string json)
{
return JSON.Parse(json);
}
/// <summary>
/// 把JSON解释为API响应对象。
/// </summary>
/// <typeparam name="T">API响应类型</typeparam>
/// <param name="json">JSON字符串</param>
/// <returns>API响应对象</returns>
public static T ParseResponse<T>(string json) where T : TopResponse
{
TopJsonParser<T> parser = new TopJsonParser<T>();
return parser.Parse(json);
}
/// <summary>
/// 获取从1970年1月1日到现在的毫秒总数。
/// </summary>
/// <returns>毫秒数</returns>
public static long GetCurrentTimeMillis()
{
return (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
}
/// <summary>
/// 获取本机的局域网IP。
/// </summary>
public static string GetIntranetIp()
{
if (intranetIp == null)
{
NetworkInterface[] nis = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface ni in nis)
{
if (OperationalStatus.Up == ni.OperationalStatus && (NetworkInterfaceType.Ethernet == ni.NetworkInterfaceType || NetworkInterfaceType.Wireless80211 == ni.NetworkInterfaceType))
{
foreach (UnicastIPAddressInformation info in ni.GetIPProperties().UnicastAddresses)
{
if (AddressFamily.InterNetwork == info.Address.AddressFamily)
{
intranetIp = info.Address.ToString();
break;
}
}
if (intranetIp != null) break;
}
}
}
if (intranetIp == null)
{
intranetIp = "127.0.0.1";
}
return intranetIp;
}
public const string CHARSET_UTF8 = "UTF-8";
public const string SIGN_METHOD_SHA256 = "sha256";
public const string SIGN_METHOD_HMAC_SHA256 = "HmacSHA256";
public static string SignApiRequest(IDictionary<string, string> aparams, string appSecret, string signMethod, string apiName)
{
// 如果是调用原平台迁移方法请将方法名作为请求参数放入params中参与排序
// 第一步:检查参数是否已经排序
string[]
keys = aparams.Keys.ToArray();
Array.Sort(keys);
// 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder();
// 如果是调用新平台注册方法,请执行第三步,直接拼接方法名
// 第三步将API名拼接在字符串开头
query.Append(apiName);
foreach (string key in keys)
{
string value = aparams[key];
if (aparams.ContainsKey(key))
{
query.Append(key).Append(value);
}
}
// 第四步:使用加密算法
byte[] bytes = null;
//var ttt = query.ToString();
if (signMethod.Equals(SIGN_METHOD_SHA256))
{
bytes = encryptHMACSHA256(query.ToString(), appSecret);
}
// 第五步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串此方法需要时使用)
return byte2hex(bytes);
}
private static byte[] encryptHMACSHA256(string data, string secret)
{
byte[] bytes = null;
try
{
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
//SecretKey secretKey = new SecretKeySpec(secret.(CHARSET_UTF8), SIGN_METHOD_HMAC_SHA256);
//Mac mac = Mac.getInstance(hmac.getAlgorithm());
//mac.init(secretKey);
//bytes = Encoding.UTF8.GetBytes(secret);
}
catch (Exception ex)
{
throw;
}
return bytes;
}
/**
* Transfer binary array to HEX string.
*/
public static String byte2hex(byte[] bytes)
{
// 第五步:把二进制转化为大写的十六进制
StringBuilder result = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
result.Append(bytes[i].ToString("X2"));
}
return result.ToString();
}
}
}