using System; using System.Collections.Generic; using System.Linq; using System.Net.Security; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Web; namespace Infrastructure.Helpers { public class HIKOpenAPI { /// /// /// /// /// /// /// /// /// public static string HttpPost(string url, string api, string body, string ak, string sk) { var headers = new Dictionary { { "Accept", "*/*" }, { "Content-Type", "application/json" } }; var request = new Request(Method.POST_STRING, url, api, ak, sk, 10000) { Headers = headers, SignHeaderPrefixList = null, Querys = null, StringBody = body }; var result = DoPoststring(request.Host, request.Path, request.Timeout, request.Headers, request.Querys, request.StringBody, request.SignHeaderPrefixList, request.AppKey, request.AppSecret, false); return result; } //Post请求方法 public static string DoPoststring(string host, string path, int connectTimeout, Dictionary headers, Dictionary querys, string body, List signHeaderPrefixList, string appKey, string appSecret, bool autoDown) { try { headers = initialBasicHeader("POST", path, headers, querys, null, signHeaderPrefixList, appKey, appSecret); ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidate; //验证服务器证书回调自动验证 //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | // SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(initUrl(host, path, querys)); request.KeepAlive = false; request.ProtocolVersion = HttpVersion.Version10; //设置HTTP协议的并发连接数 //ServicePointManager.DefaultConnectionLimit = 512; //关闭重定向 request.AllowAutoRedirect = true; request.Method = "POST"; request.Timeout = connectTimeout; string accept = headers["Accept"]; request.Accept = accept; string contentType = headers["Content-Type"]; request.ContentType = contentType; foreach (string headerKey in headers.Keys) { if (headerKey.Contains("x-ca-")) { request.Headers.Add(headerKey + ":" + (string.IsNullOrWhiteSpace(headers[headerKey]) ? "" : headers[headerKey])); } if (headerKey.Equals("tagId")) { request.Headers.Add(headerKey + ":" + (string.IsNullOrWhiteSpace(headers[headerKey]) ? "" : headers[headerKey])); } } if (!string.IsNullOrWhiteSpace(body)) { byte[] postBytes = Encoding.UTF8.GetBytes(body); request.ContentLength = postBytes.Length; Stream requestStream = request.GetRequestStream(); requestStream.Write(postBytes, 0, postBytes.Length); requestStream.Close(); } var response = (HttpWebResponse)request.GetResponse(); var result = ""; if (response.StatusCode != HttpStatusCode.OK) return result; using (StreamReader rdr = new StreamReader(response.GetResponseStream())) { result = rdr.ReadToEnd(); } return result; } catch (Exception ex) { return Newtonsoft.Json.JsonConvert.SerializeObject(new { code = "404", msg = ex.Message }); } } //获取当时时间戳 public static long GetTimestamp(DateTime time) { System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0)); long t = (time.Ticks - startTime.Ticks) / 10000; //除10000调整为13位 return t; } private static bool RemoteCertificateValidate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error) { //为了通过证书验证,总是返回true return true; } public static Dictionary initialBasicHeader(string method, string path, Dictionary headers, Dictionary querys, Dictionary bodys, List signHeaderPrefixList, string appKey, string appSecret) //throws MalformedURLException { if (headers == null) { headers = new Dictionary(); } headers["x-ca-timestamp"] = GetTimestamp(DateTime.Now).ToString(); headers["x-ca-nonce"] = System.Guid.NewGuid().ToString(); headers["x-ca-key"] = appKey; headers["x-ca-signature"] = sign(appSecret, method, path, headers, querys, bodys, signHeaderPrefixList); return headers; //https://223.99.16.253:6114/pic? //5d00=a202l94-do7b18*35d69188-64fbf0ebc**561===sp**715=7t7662209067=1l3*1513o6*720-=46fe44pi1e9o=0-9e00b0 //&AccessKeyId=Qrq2LsyWF6GSM0zm&Expires=1677046120&Signature=Bw7dKuV6CX7w3ev56u6jBwRuGwU= } public static string initUrl(string host, string path, Dictionary querys) //throws UnsupportedEncodingException { StringBuilder sbUrl = new StringBuilder(); sbUrl.Append(host); if (!string.IsNullOrWhiteSpace(path)) { sbUrl.Append(path); } if (null != querys) { StringBuilder sbQuery = new StringBuilder(); foreach (string queryKey in querys.Keys) { if (0 < sbQuery.Length) { sbQuery.Append("&"); } if (string.IsNullOrWhiteSpace(queryKey) && !string.IsNullOrWhiteSpace(querys[queryKey])) { sbQuery.Append(querys[queryKey]); } if (!string.IsNullOrWhiteSpace(queryKey)) { sbQuery.Append(queryKey); if (!string.IsNullOrWhiteSpace(querys[queryKey])) { sbQuery.Append("=").Append(HttpUtility.UrlEncode(querys[queryKey], Encoding.UTF8)); } } } if (0 < sbQuery.Length) { sbUrl.Append("?").Append(sbQuery); } } return sbUrl.ToString(); } public static string sign(string secret, string method, string path, Dictionary headers, Dictionary querys, Dictionary bodys, List signHeaderPrefixList) { try { //return HmacSHA256(buildstringToSign(method, path, headers, querys, bodys, signHeaderPrefixList), secret); /*---message里的内容---*/ //POST //*/* //application/json //x-ca-key:23125513 //x-ca-nonce:12d28d90-a7c3-45cc-ae6a-0cc8d5e22118 //x-ca-timestamp:1544495633599 //artemis/api/resource/v1/org/advance/orgList string message = buildstringToSign(method, path, headers, querys, bodys, signHeaderPrefixList); return HmacSHA256(message, secret); } catch (Exception ex) { return ex.Message; } } public static string buildstringToSign(string method, string path, Dictionary headers, Dictionary querys, Dictionary bodys, List signHeaderPrefixList) { StringBuilder sb = new StringBuilder(); sb.Append(method.ToUpper()).Append("\n"); if (null != headers) { if (null != headers["Accept"]) { sb.Append((string)headers["Accept"]); sb.Append("\n"); } if (headers.Keys.Contains("Content-MD5") && null != headers["Content-MD5"]) { sb.Append((string)headers["Content-MD5"]); sb.Append("\n"); } if (null != headers["Content-Type"]) { sb.Append((string)headers["Content-Type"]); sb.Append("\n"); } if (headers.Keys.Contains("Date") && null != headers["Date"]) { sb.Append((string)headers["Date"]); sb.Append("\n"); } } sb.Append(buildHeaders(headers, signHeaderPrefixList)); sb.Append(buildResource(path, querys, bodys)); return sb.ToString(); } public static string buildHeaders(Dictionary headers, List signHeaderPrefixList) { StringBuilder sb = new StringBuilder(); if (null != signHeaderPrefixList) { signHeaderPrefixList.Remove("x-ca-signature"); signHeaderPrefixList.Remove("Accept"); signHeaderPrefixList.Remove("Content-MD5"); signHeaderPrefixList.Remove("Content-Type"); signHeaderPrefixList.Remove("Date"); signHeaderPrefixList.Sort(); } if (null != headers) { Dictionary sortDictionary = new Dictionary(); sortDictionary = headers; //按key值升序排序 var dicSort = from objDic in sortDictionary orderby objDic.Key ascending select objDic; StringBuilder signHeadersStringBuilder = new StringBuilder(); foreach (KeyValuePair kvp in dicSort) { if (kvp.Key.Replace(" ", "").Contains("x-ca-")) { sb.Append(kvp.Key + ":"); if (!string.IsNullOrWhiteSpace(kvp.Value)) { sb.Append(kvp.Value); } sb.Append("\n"); if (signHeadersStringBuilder.Length > 0) { signHeadersStringBuilder.Append(","); } signHeadersStringBuilder.Append(kvp.Key); } } headers.Add("x-ca-signature-headers", signHeadersStringBuilder.ToString()); } //x-ca-key:23125513 //x-ca-nonce:12d28d90-a7c3-45cc-ae6a-0cc8d5e22118 //x-ca-timestamp:1544495633599 return sb.ToString(); } public static string buildResource(string path, Dictionary querys, Dictionary bodys) { StringBuilder sb = new StringBuilder(); if (!string.IsNullOrWhiteSpace(path)) { sb.Append(path); } Dictionary sortDictionary = new Dictionary(); if (querys != null) { //按key值升序排序 var dicSort = from objDic in querys orderby objDic.Key ascending select objDic; foreach (KeyValuePair kvp in dicSort) { if (!string.IsNullOrWhiteSpace(kvp.Key)) { sortDictionary[kvp.Key] = kvp.Value; } } } if (bodys != null) { //按key值升序排序 var dicSort = from objDic in bodys orderby objDic.Key ascending select objDic; foreach (KeyValuePair kvp in dicSort) { if (!string.IsNullOrWhiteSpace(kvp.Key)) { sortDictionary[kvp.Key] = kvp.Value; } } } StringBuilder sbParam = new StringBuilder(); //按key值升序排序 var dicSortDictionary = from objDic in sortDictionary orderby objDic.Key ascending select objDic; foreach (KeyValuePair kvp in dicSortDictionary) { if (!string.IsNullOrWhiteSpace(kvp.Key)) { if (sbParam.Length > 0) { sbParam.Append("&"); } sbParam.Append(kvp.Key); if (!string.IsNullOrWhiteSpace(kvp.Value)) { sbParam.Append("=").Append(kvp.Value); } } } if (0 < sbParam.Length) { sb.Append("?"); sb.Append(sbParam); } //artemis/api/resource/v1/org/advance/orgList return sb.ToString(); } public static string HmacSHA256(string message, string secret) { secret = secret ?? ""; var encoding = new System.Text.UTF8Encoding(); byte[] keyByte = encoding.GetBytes(secret); byte[] messageBytes = encoding.GetBytes(message); using (var hmacsha256 = new HMACSHA256(keyByte)) { byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); return Convert.ToBase64String(hashmessage); } } public static Dictionary ConvertMapTimeStyle(Dictionary paramMap) { Dictionary timeMap = new Dictionary(); try { foreach (string key in paramMap.Keys) { object mapValueObj = paramMap[key]; Dictionary dic = mapValueObj as Dictionary; if (dic != null) { ConvertMapTimeStyle(dic); } //时间格式参数转为ISO8601 DateTime mapDate; if (DateTime.TryParse(paramMap[key].ToString(), out mapDate)) { string ISO8601time = mapDate.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz"); timeMap.Add(key, ISO8601time); } } if (timeMap.Count > 0) { foreach (string key in timeMap.Keys) { paramMap[key] = timeMap[key]; } } return paramMap; } catch (Exception ex) { return paramMap; } } public enum Method { GET, POST_FORM, POST_STRING, POST_BYTES, PUT_FORM, PUT_STRING, PUT_BYTES, DELETE } public class Request { public Request() { } public Request(Method method, string host, string path, string appKey, string appSecret, int timeout) { this.Method = method; this.Host = host; this.Path = path; this.AppKey = appKey; this.AppSecret = appSecret; this.Timeout = timeout; } public Method Method { get; set; } public string Host { get; set; } public string Path { get; set; } public string AppKey { get; set; } public string AppSecret { get; set; } public int Timeout { get; set; } public Dictionary Headers { get; set; } public Dictionary Querys { get; set; } public Dictionary Bodys { get; set; } public string StringBody { get; set; } public byte[] BytesBody { get; set; } public List SignHeaderPrefixList { get; set; } } } }