|
@@ -0,0 +1,341 @@
|
|
|
+package pji_client
|
|
|
+
|
|
|
+import (
|
|
|
+ "context"
|
|
|
+ "crypto/rand"
|
|
|
+ "crypto/rsa"
|
|
|
+ "crypto/sha256"
|
|
|
+ "crypto/tls"
|
|
|
+ "crypto/x509"
|
|
|
+ "encoding/base64"
|
|
|
+ "encoding/hex"
|
|
|
+ "encoding/json"
|
|
|
+ "encoding/pem"
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "github.com/cloudwego/hertz/pkg/app/client"
|
|
|
+ "github.com/cloudwego/hertz/pkg/protocol"
|
|
|
+ "sort"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ PEM_BEGIN = "-----BEGIN PRIVATE KEY-----\n"
|
|
|
+ PEM_END = "\n-----END PRIVATE KEY-----"
|
|
|
+)
|
|
|
+
|
|
|
+// SysUserApiClient 是用于API交互的客户端结构体
|
|
|
+type SysUserApiClient struct {
|
|
|
+ HttpClient *client.Client // Hertz客户端实例
|
|
|
+ PrivateKey *rsa.PrivateKey // RSA私钥
|
|
|
+}
|
|
|
+
|
|
|
+// NewSysUserApiClient 创建并返回一个SysUserApiClient实例
|
|
|
+func NewSysUserApiClient(privateKey *rsa.PrivateKey) (*SysUserApiClient, error) {
|
|
|
+ hClient, err := client.NewClient(client.WithTLSConfig(&tls.Config{
|
|
|
+ InsecureSkipVerify: true,
|
|
|
+ }))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ return &SysUserApiClient{
|
|
|
+ HttpClient: hClient,
|
|
|
+ PrivateKey: privateKey,
|
|
|
+ }, nil
|
|
|
+}
|
|
|
+
|
|
|
+func ParsePrivateKey(privateKeyPEM string) (*rsa.PrivateKey, error) {
|
|
|
+ privateKeyPEM = FormatPrivateKey(privateKeyPEM)
|
|
|
+ //fmt.Println("privateKeyPEM", privateKeyPEM)
|
|
|
+ // 2、解码私钥字节,生成加密对象
|
|
|
+ block, _ := pem.Decode([]byte(privateKeyPEM))
|
|
|
+
|
|
|
+ if block == nil {
|
|
|
+
|
|
|
+ return nil, errors.New("私钥信息错误!")
|
|
|
+ }
|
|
|
+
|
|
|
+ //fmt.Println("block", block.Bytes)
|
|
|
+ // 3、生成私钥对象
|
|
|
+ priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ // 4. 类型断言为*RSA私钥
|
|
|
+ privateKey := priKey.(*rsa.PrivateKey)
|
|
|
+ return privateKey, nil
|
|
|
+}
|
|
|
+
|
|
|
+func FormatPrivateKey(privateKey string) string {
|
|
|
+ if !strings.HasPrefix(privateKey, PEM_BEGIN) {
|
|
|
+ privateKey = PEM_BEGIN + privateKey
|
|
|
+ }
|
|
|
+ if !strings.HasSuffix(privateKey, PEM_END) {
|
|
|
+ privateKey = privateKey + PEM_END
|
|
|
+ }
|
|
|
+ return privateKey
|
|
|
+}
|
|
|
+
|
|
|
+// 辅助函数:对Map的键进行排序
|
|
|
+func sortMapByKey(m map[string]interface{}) map[string]interface{} {
|
|
|
+ sortedMap := make(map[string]interface{})
|
|
|
+ keys := make([]string, 0, len(m))
|
|
|
+
|
|
|
+ for k := range m {
|
|
|
+ keys = append(keys, k)
|
|
|
+ }
|
|
|
+
|
|
|
+ sort.Strings(keys)
|
|
|
+
|
|
|
+ for _, k := range keys {
|
|
|
+ sortedMap[k] = m[k]
|
|
|
+ }
|
|
|
+
|
|
|
+ return sortedMap
|
|
|
+}
|
|
|
+
|
|
|
+// 生成SHA-256哈希并进行RSA签名
|
|
|
+func (c *SysUserApiClient) generateSignature(val string) (string, error) {
|
|
|
+ fmt.Println("val", val)
|
|
|
+ // 签名摘要
|
|
|
+ hash := sha256.New()
|
|
|
+ hash.Write([]byte(val))
|
|
|
+ hashed := hash.Sum(nil)
|
|
|
+ fmt.Println("hashed", hashed)
|
|
|
+ str := hex.EncodeToString(hashed)
|
|
|
+ bytes := []byte(str)
|
|
|
+ fmt.Println("str", str)
|
|
|
+ fmt.Println("bytes", bytes)
|
|
|
+ signedData, err := rsa.SignPKCS1v15(rand.Reader, c.PrivateKey, 0, bytes)
|
|
|
+ str = hex.EncodeToString(signedData)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ fmt.Println("base64", str)
|
|
|
+ fmt.Println("base64 signedData", base64.StdEncoding.EncodeToString([]byte(str)))
|
|
|
+ return base64.StdEncoding.EncodeToString([]byte(str)), nil
|
|
|
+}
|
|
|
+
|
|
|
+// 通用请求生成函数,设置通用头部信息
|
|
|
+func (c *SysUserApiClient) getHttpRequest(method string, url string, secretId string, encode string) *protocol.Request {
|
|
|
+ req := protocol.AcquireRequest()
|
|
|
+ req.Header.SetMethod(method)
|
|
|
+ req.SetRequestURI(url)
|
|
|
+ req.Header.Set("PJI-TIMESTAMP", strconv.FormatInt(time.Now().Unix(), 10))
|
|
|
+ req.Header.Set("PJI-API-VERSION", "v1.0")
|
|
|
+ req.Header.Set("PJI-ALGORITHM", "SHA3-256")
|
|
|
+ req.Header.Set("PJI-SECRET-ID", secretId)
|
|
|
+ req.Header.Set("PJI-ABSTRACT-SIGN", encode)
|
|
|
+ req.Header.Set("Content-Type", "application/json")
|
|
|
+ fmt.Println("req", req.Header.String())
|
|
|
+ return req
|
|
|
+}
|
|
|
+
|
|
|
+// JsonPostRequest 发送带有JSON请求体的POST请求
|
|
|
+func (c *SysUserApiClient) JsonPostRequest(url string, paramMap map[string]interface{}, secretId string) (*protocol.Response, error) {
|
|
|
+ paramMap = sortMapByKey(paramMap)
|
|
|
+
|
|
|
+ jsonData, err := json.Marshal(paramMap)
|
|
|
+ fmt.Println("jsonData", string(jsonData))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ str := string(jsonData)
|
|
|
+ if string(jsonData) == "{}" {
|
|
|
+ return nil, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ signature, err := c.generateSignature(str)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ req := c.getHttpRequest("POST", url, secretId, signature)
|
|
|
+ req.SetBody(jsonData)
|
|
|
+
|
|
|
+ resp := protocol.AcquireResponse()
|
|
|
+
|
|
|
+ ctx := context.Background()
|
|
|
+ err = c.HttpClient.Do(ctx, req, resp)
|
|
|
+ return resp, err
|
|
|
+}
|
|
|
+
|
|
|
+//// PutRequest 发送PUT请求
|
|
|
+//func (c *SysUserApiClient) PutRequest(url string, paramMap map[string]interface{}, secretId string) (*protocol.Response, error) {
|
|
|
+// paramMap = sortMapByKey(paramMap)
|
|
|
+//
|
|
|
+// jsonData, err := json.Marshal(paramMap)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// signature, err := c.generateSignature(jsonData)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// req := c.getHttpRequest("PUT", url, secretId, signature)
|
|
|
+// req.SetBody(jsonData)
|
|
|
+//
|
|
|
+// resp := protocol.AcquireResponse()
|
|
|
+// ctx := context.Background()
|
|
|
+// err = c.HttpClient.Do(ctx, req, resp)
|
|
|
+// return resp, err
|
|
|
+//}
|
|
|
+
|
|
|
+// GetRequest 发送GET请求
|
|
|
+func (c *SysUserApiClient) GetRequest(url string, paramMap map[string]string, secretId string) (*protocol.Response, error) {
|
|
|
+ //sortedParams := url.Values{}
|
|
|
+ //for k, v := range paramMap {
|
|
|
+ // sortedParams.Add(k, v)
|
|
|
+ //}
|
|
|
+ //sortedURL := url + "?" + sortedParams.Encode()
|
|
|
+
|
|
|
+ //jsonData, err := json.Marshal(paramMap)
|
|
|
+ jsonData, err := json.Marshal(paramMap)
|
|
|
+ fmt.Println("jsonData", string(jsonData))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ str := string(jsonData)
|
|
|
+ if string(jsonData) == "{}" {
|
|
|
+ str = ""
|
|
|
+ }
|
|
|
+ signature, err := c.generateSignature(str)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ req := c.getHttpRequest("GET", url, secretId, signature)
|
|
|
+
|
|
|
+ resp := protocol.AcquireResponse()
|
|
|
+ ctx := context.Background()
|
|
|
+ err = c.HttpClient.Do(ctx, req, resp)
|
|
|
+ return resp, err
|
|
|
+}
|
|
|
+
|
|
|
+//// DeleteRequest 发送DELETE请求
|
|
|
+//func (c *SysUserApiClient) DeleteRequest(url string, paramMap map[string]string, secretId string) (*protocol.Response, error) {
|
|
|
+// sortedParams := url.Values{}
|
|
|
+// for k, v := range paramMap {
|
|
|
+// sortedParams.Add(k, v)
|
|
|
+// }
|
|
|
+// sortedURL := url + "?" + sortedParams.Encode()
|
|
|
+//
|
|
|
+// jsonData, err := json.Marshal(paramMap)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// signature, err := c.generateSignature(jsonData)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// req := c.getHttpRequest("DELETE", sortedURL, secretId, signature)
|
|
|
+//
|
|
|
+// resp := protocol.AcquireResponse()
|
|
|
+// err = c.HttpClient.Do(req, resp)
|
|
|
+// return resp, err
|
|
|
+//}
|
|
|
+
|
|
|
+//// FormDataRequest 发送带有form-data的POST请求
|
|
|
+//func (c *SysUserApiClient) FormDataRequest(url string, paramMap map[string]string, secretId string) (*protocol.Response, error) {
|
|
|
+// paramMap = sortMapByKeyString(paramMap)
|
|
|
+//
|
|
|
+// jsonData, err := json.Marshal(paramMap)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// signature, err := c.generateSignature(jsonData)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// req := c.getHttpRequest("POST", url, secretId, signature)
|
|
|
+// formBody := url.Values{}
|
|
|
+// for k, v := range paramMap {
|
|
|
+// formBody.Set(k, v)
|
|
|
+// }
|
|
|
+// req.Header.SetContentType("multipart/form-data")
|
|
|
+// req.SetBody([]byte(formBody.Encode()))
|
|
|
+//
|
|
|
+// resp := protocol.AcquireResponse()
|
|
|
+// err = c.HttpClient.Do(req, resp)
|
|
|
+// return resp, err
|
|
|
+//}
|
|
|
+
|
|
|
+//// UploadRequest 上传文件
|
|
|
+//func (c *SysUserApiClient) UploadRequest(url string, paramMap map[string]string, file []byte, secretId string) (*protocol.Response, error) {
|
|
|
+// paramMap = sortMapByKeyString(paramMap)
|
|
|
+//
|
|
|
+// jsonData, err := json.Marshal(paramMap)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// signature, err := c.generateSignature(jsonData)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// req := c.getHttpRequest("POST", url, secretId, signature)
|
|
|
+// formBody := url.Values{}
|
|
|
+// for k, v := range paramMap {
|
|
|
+// formBody.Set(k, v)
|
|
|
+// }
|
|
|
+//
|
|
|
+// req.Header.SetContentType("multipart/form-data")
|
|
|
+// req.SetBody([]byte(formBody.Encode())) // 文件数据可以单独处理
|
|
|
+//
|
|
|
+// resp := protocol.AcquireResponse()
|
|
|
+// err = c.HttpClient.Do(req, resp)
|
|
|
+// return resp, err
|
|
|
+//}
|
|
|
+//
|
|
|
+//// DownLoadRequest 文件下载
|
|
|
+//func (c *SysUserApiClient) DownLoadRequest(url string, paramMap map[string]string, secretId string) (*protocol.Response, error) {
|
|
|
+// sortedParams := url.Values{}
|
|
|
+// for k, v := range paramMap {
|
|
|
+// sortedParams.Add(k, v)
|
|
|
+// }
|
|
|
+// sortedURL := url + "?" + sortedParams.Encode()
|
|
|
+//
|
|
|
+// jsonData, err := json.Marshal(paramMap)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// signature, err := c.generateSignature(jsonData)
|
|
|
+// if err != nil {
|
|
|
+// return nil, err
|
|
|
+// }
|
|
|
+//
|
|
|
+// req := c.getHttpRequest("GET", sortedURL, secretId, signature)
|
|
|
+// req.SetBody([]byte{})
|
|
|
+//
|
|
|
+// resp := protocol.AcquireResponse()
|
|
|
+// err = c.HttpClient.Do(req, resp)
|
|
|
+// return resp, err
|
|
|
+//}
|
|
|
+
|
|
|
+// 辅助函数:对字符串Map的键进行排序
|
|
|
+func sortMapByKeyString(m map[string]string) map[string]string {
|
|
|
+ sortedMap := make(map[string]string)
|
|
|
+ keys := make([]string, 0, len(m))
|
|
|
+
|
|
|
+ for k := range m {
|
|
|
+ keys = append(keys, k)
|
|
|
+ }
|
|
|
+
|
|
|
+ sort.Strings(keys)
|
|
|
+
|
|
|
+ for _, k := range keys {
|
|
|
+ sortedMap[k] = m[k]
|
|
|
+ }
|
|
|
+
|
|
|
+ return sortedMap
|
|
|
+}
|