using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace Topsdk.Util
{
///
/// TOP系统工具类。
///
public abstract class TopUtils
{
private static JsonSerializerOptions options = new JsonSerializerOptions()
{
WriteIndented = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString,
Converters = { new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss") }
};
///
/// 给TOP请求签名。
///
/// 所有字符型的TOP请求参数
/// 签名密钥
/// 签名方法,可选值:md5, hmac
/// 签名
public static string SignTopRequest(IDictionary parameters, string secret, string signMethod)
{
return SignTopRequestWithBody(parameters, null, secret, signMethod);
}
///
/// 给TOP请求签名。
///
///
///
///
///
///
public static string SignTopRequest(IDictionary publicParam,IDictionary requestParam, string secret, string signMethod)
{
IDictionary parameters = new Dictionary(publicParam);
foreach (KeyValuePair item in requestParam)
{
parameters.Add(item);
}
return SignTopRequest(parameters, secret, signMethod);
}
///
/// 给TOP请求签名。
///
/// 所有字符型的TOP请求参数
/// 请求主体内容
/// 签名密钥
/// 签名方法,可选值:md5, hmac
/// 签名
public static string SignTopRequestWithBody(IDictionary parameters, string body, string secret, string signMethod)
{
// 第一步:把字典按Key的字母顺序排序
IDictionary sortedParams = new SortedDictionary(parameters, StringComparer.Ordinal);
// 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder();
if(Constants.SIGN_METHOD_MD5.Equals(signMethod))
{
query.Append(secret);
}
foreach (KeyValuePair 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();
}
///
/// 清除字典中值为空的项。
///
/// 待清除的字典
/// 清除后的字典
public static IDictionary CleanupDictionary(IDictionary dict)
{
IDictionary newDict = new Dictionary(dict.Count);
foreach (KeyValuePair kv in dict)
{
if (kv.Value != null)
{
newDict.Add(kv.Key, kv.Value);
}
}
return newDict;
}
///
/// 获取从1970年1月1日到现在的毫秒总数。
///
/// 毫秒数
public static long GetCurrentTimeMillis()
{
return (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
}
///
/// 复杂对象列表转json
///
///
///
public static string ConvertStructList(object? list)
{
if (list == null)
{
return "[]";
}
if (list is string)
{
return (string)list;
}
return JsonSerializer.Serialize(list,options);
}
public static string ConvertStruct(object? obj)
{
if (obj == null)
{
return "{}";
}
if (obj is string)
{
return (string)obj;
}
return JsonSerializer.Serialize(obj);
}
public static string ConvertBasicList(IList list)
{
if (list == null)
{
return "";
}
return string.Join(",",list);
}
public static string ConvertBasicType(object? obj)
{
if (obj == null)
{
return "";
}
if (obj is DateTime)
{
return ((DateTime)obj).ToString(Constants.DATE_TIME_FORMAT);
}
if (obj is bool)
{
return ((bool)obj).ToString().ToLower();
}
return obj.ToString();
}
public static T parseResultJson(string jsonStr)
{
try
{
var jsonNode = JsonObject.Parse(jsonStr);
if (jsonNode[Constants.ERROR_RESPONSE] != null)
{
return jsonNode[Constants.ERROR_RESPONSE].Deserialize(options);
}
return jsonNode.Deserialize(options);
}
catch (Exception e)
{
throw new TopException("ApiResult is not json", e);
}
}
}
}