mirror of
https://github.com/zxbit2011/hikvisionOpenAPIGo.git
synced 2025-09-27 03:46:03 +08:00
227 lines
5.6 KiB
Go
227 lines
5.6 KiB
Go
package hikvisionOpenAPIGo
|
||
|
||
import (
|
||
"bytes"
|
||
"crypto/hmac"
|
||
"crypto/md5"
|
||
"crypto/sha256"
|
||
"crypto/tls"
|
||
"encoding/base64"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/gofrs/uuid"
|
||
"io/ioutil"
|
||
"net/http"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// HKConfig 海康OpenAPI配置参数
|
||
type HKConfig struct {
|
||
Ip string //平台ip
|
||
Port int //平台端口
|
||
AppKey string //平台APPKey
|
||
Secret string //平台APPSecret
|
||
IsHttps bool //是否使用HTTPS协议
|
||
}
|
||
|
||
// 返回结果
|
||
type Result struct {
|
||
Code string `json:"code"`
|
||
Msg string `json:"msg"`
|
||
Data interface{} `json:"data"`
|
||
}
|
||
|
||
// 返回值data
|
||
type Data struct {
|
||
Total int `json:"total"`
|
||
PageSize int `json:"pageSize"`
|
||
PageNo int `json:"pageNo"`
|
||
List []map[string]interface{} `json:"list"`
|
||
}
|
||
|
||
// @title HTTP Post请求
|
||
// @url HTTP接口Url string HTTP接口Url,不带协议和端口,如/artemis/api/resource/v1/org/advance/orgList
|
||
// @body 请求参数 map[string]string
|
||
// @return 请求结果 参数类型
|
||
func (hk HKConfig) HttpPost(url string, body map[string]string, timeout int) (result Result, err error) {
|
||
var header = make(map[string]string)
|
||
bodyJson, err := json.Marshal(body)
|
||
if err != nil {
|
||
return result, err
|
||
}
|
||
err = hk.initRequest(header, url, string(bodyJson), true)
|
||
if err != nil {
|
||
return Result{}, err
|
||
}
|
||
var sb []string
|
||
if hk.IsHttps {
|
||
sb = append(sb, "https://")
|
||
} else {
|
||
sb = append(sb, "http://")
|
||
}
|
||
sb = append(sb, fmt.Sprintf("%s:%d", hk.Ip, hk.Port))
|
||
sb = append(sb, url)
|
||
|
||
client := &http.Client{}
|
||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||
return http.ErrUseLastResponse
|
||
}
|
||
client.Timeout = time.Duration(timeout) * time.Second
|
||
if hk.IsHttps {
|
||
tr := &http.Transport{
|
||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||
}
|
||
client.Transport = tr
|
||
}
|
||
req, err := http.NewRequest("POST", strings.Join(sb, ""), bytes.NewReader(bodyJson))
|
||
if err != nil {
|
||
return
|
||
}
|
||
|
||
req.Header.Set("Accept", header["Accept"])
|
||
req.Header.Set("Content-Type", header["Content-Type"])
|
||
for k, v := range header {
|
||
if strings.Contains(k, "x-ca-") {
|
||
req.Header.Set(k, v)
|
||
}
|
||
}
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
return
|
||
}
|
||
defer resp.Body.Close()
|
||
if resp.StatusCode == http.StatusOK {
|
||
var resBody []byte
|
||
resBody, err = ioutil.ReadAll(resp.Body)
|
||
if err != nil {
|
||
return
|
||
}
|
||
err = json.Unmarshal(resBody, &result)
|
||
} else if resp.StatusCode == http.StatusFound || resp.StatusCode == http.StatusMovedPermanently {
|
||
reqUrl := resp.Header.Get("Location")
|
||
err = fmt.Errorf("HttpPost Response StatusCode:%d,Location:%s", resp.StatusCode, reqUrl)
|
||
} else {
|
||
err = fmt.Errorf("HttpPost Response StatusCode:%d", resp.StatusCode)
|
||
}
|
||
return
|
||
}
|
||
|
||
// initRequest 初始化请求头
|
||
func (hk HKConfig) initRequest(header map[string]string, url, body string, isPost bool) error {
|
||
header["Accept"] = "application/json"
|
||
header["Content-Type"] = "application/json"
|
||
if isPost {
|
||
var err error
|
||
header["content-md5"], err = computeContentMd5(body)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
header["x-ca-timestamp"] = strconv.FormatInt(time.Now().UnixMilli(), 10)
|
||
uid, err := uuid.NewV4()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
header["x-ca-nonce"] = uid.String()
|
||
header["x-ca-key"] = hk.AppKey
|
||
|
||
var strToSign string
|
||
if isPost {
|
||
strToSign = buildSignString(header, url, "POST")
|
||
} else {
|
||
strToSign = buildSignString(header, url, "GET")
|
||
}
|
||
signedStr, err := computeForHMACSHA256(strToSign, hk.Secret)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
header["x-ca-signature"] = signedStr
|
||
return nil
|
||
}
|
||
|
||
// computeContentMd5 计算content-md5
|
||
func computeContentMd5(body string) (string, error) {
|
||
h := md5.New()
|
||
_, err := h.Write([]byte(body))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
md5Str := hex.EncodeToString(h.Sum(nil))
|
||
return base64.StdEncoding.EncodeToString([]byte(md5Str)), nil
|
||
}
|
||
|
||
// computeForHMACSHA256 计算HMACSHA265
|
||
func computeForHMACSHA256(str, secret string) (string, error) {
|
||
mac := hmac.New(sha256.New, []byte(secret))
|
||
_, err := mac.Write([]byte(str))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return base64.StdEncoding.EncodeToString(mac.Sum(nil)), nil
|
||
}
|
||
|
||
// buildSignString 计算签名字符串
|
||
func buildSignString(header map[string]string, url, method string) string {
|
||
var sb []string
|
||
sb = append(sb, strings.ToUpper(method))
|
||
sb = append(sb, "\n")
|
||
|
||
if header != nil {
|
||
if _, ok := header["Accept"]; ok {
|
||
sb = append(sb, header["Accept"])
|
||
sb = append(sb, "\n")
|
||
}
|
||
if _, ok := header["Content-MD5"]; ok {
|
||
sb = append(sb, header["Content-MD5"])
|
||
sb = append(sb, "\n")
|
||
}
|
||
if _, ok := header["Content-Type"]; ok {
|
||
sb = append(sb, header["Content-Type"])
|
||
sb = append(sb, "\n")
|
||
}
|
||
if _, ok := header["Date"]; ok {
|
||
sb = append(sb, header["Date"])
|
||
sb = append(sb, "\n")
|
||
}
|
||
}
|
||
sb = append(sb, buildSignHeader(header))
|
||
sb = append(sb, url)
|
||
return strings.Join(sb, "")
|
||
}
|
||
|
||
// buildSignHeader 计算签名头
|
||
func buildSignHeader(header map[string]string) string {
|
||
var sortedDicHeader map[string]string
|
||
sortedDicHeader = header
|
||
|
||
var sslice []string
|
||
for key, _ := range sortedDicHeader {
|
||
sslice = append(sslice, key)
|
||
}
|
||
sort.Strings(sslice)
|
||
|
||
var sbSignHeader []string
|
||
var sb []string
|
||
//在将key输出
|
||
for _, k := range sslice {
|
||
if strings.Contains(strings.ReplaceAll(k, " ", ""), "x-ca-") {
|
||
sb = append(sb, k+":")
|
||
if sortedDicHeader[k] != "" {
|
||
sb = append(sb, sortedDicHeader[k])
|
||
}
|
||
sb = append(sb, "\n")
|
||
if len(sbSignHeader) > 0 {
|
||
sbSignHeader = append(sbSignHeader, ",")
|
||
}
|
||
sbSignHeader = append(sbSignHeader, k)
|
||
}
|
||
}
|
||
|
||
header["x-ca-signature-headers"] = strings.Join(sbSignHeader, "")
|
||
return strings.Join(sb, "")
|
||
}
|