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); } } } }