272 lines
9.6 KiB
C#
272 lines
9.6 KiB
C#
|
|
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();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|