|
|
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
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
///
|
|
|
/// </summary>
|
|
|
/// <param name="url"></param>
|
|
|
/// <param name="api"></param>
|
|
|
/// <param name="body"></param>
|
|
|
/// <param name="ak"></param>
|
|
|
/// <param name="sk"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string HttpPost(string url, string api, string body, string ak, string sk)
|
|
|
{
|
|
|
|
|
|
var headers = new Dictionary<string, string> { { "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<string, string> headers,
|
|
|
Dictionary<string, string> querys, string body, List<string> 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<string, string> initialBasicHeader(string method, string path,
|
|
|
Dictionary<string, string> headers, Dictionary<string, string> querys, Dictionary<string, string> bodys,
|
|
|
List<string> signHeaderPrefixList, string appKey, string appSecret) //throws MalformedURLException
|
|
|
{
|
|
|
if (headers == null)
|
|
|
{
|
|
|
headers = new Dictionary<string, string>();
|
|
|
}
|
|
|
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<string, string> 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<string, string> headers,
|
|
|
Dictionary<string, string> querys, Dictionary<string, string> bodys, List<string> 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<string, string> headers,
|
|
|
Dictionary<string, string> querys, Dictionary<string, string> bodys, List<string> 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<string, string> headers, List<string> 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<string, string> sortDictionary = new Dictionary<string, string>();
|
|
|
sortDictionary = headers;
|
|
|
//按key值升序排序
|
|
|
var dicSort = from objDic in sortDictionary orderby objDic.Key ascending select objDic;
|
|
|
|
|
|
StringBuilder signHeadersStringBuilder = new StringBuilder();
|
|
|
|
|
|
foreach (KeyValuePair<string, string> 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<string, string> querys, Dictionary<string, string> bodys)
|
|
|
{
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
if (!string.IsNullOrWhiteSpace(path))
|
|
|
{
|
|
|
sb.Append(path);
|
|
|
}
|
|
|
|
|
|
Dictionary<string, string> sortDictionary = new Dictionary<string, string>();
|
|
|
if (querys != null)
|
|
|
{
|
|
|
//按key值升序排序
|
|
|
var dicSort = from objDic in querys orderby objDic.Key ascending select objDic;
|
|
|
foreach (KeyValuePair<string, string> 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<string, string> 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<string, string> 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<string, object> ConvertMapTimeStyle(Dictionary<string, object> paramMap)
|
|
|
{
|
|
|
Dictionary<string, object> timeMap = new Dictionary<string, object>();
|
|
|
try
|
|
|
{
|
|
|
foreach (string key in paramMap.Keys)
|
|
|
{
|
|
|
|
|
|
object mapValueObj = paramMap[key];
|
|
|
Dictionary<string, object> dic = mapValueObj as Dictionary<string, object>;
|
|
|
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<string, string> Headers { get; set; }
|
|
|
|
|
|
public Dictionary<string, string> Querys { get; set; }
|
|
|
|
|
|
public Dictionary<string, string> Bodys { get; set; }
|
|
|
|
|
|
public string StringBody { get; set; }
|
|
|
|
|
|
public byte[] BytesBody { get; set; }
|
|
|
|
|
|
public List<string> SignHeaderPrefixList { get; set; }
|
|
|
}
|
|
|
}
|
|
|
}
|