pji_client.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. package pji_client
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/rand"
  6. "crypto/rsa"
  7. "crypto/sha256"
  8. "crypto/tls"
  9. "crypto/x509"
  10. "encoding/base64"
  11. "encoding/hex"
  12. "encoding/json"
  13. "encoding/pem"
  14. "errors"
  15. "fmt"
  16. "github.com/cloudwego/hertz/pkg/app/client"
  17. "github.com/cloudwego/hertz/pkg/protocol"
  18. "io"
  19. "mime/multipart"
  20. "pji_desktop_http/common/config/c_log"
  21. "sort"
  22. "strconv"
  23. "strings"
  24. "time"
  25. )
  26. const (
  27. PEM_BEGIN = "-----BEGIN PRIVATE KEY-----\n"
  28. PEM_END = "\n-----END PRIVATE KEY-----"
  29. )
  30. var (
  31. ApiClient *SysUserApiClient
  32. )
  33. var (
  34. MapSecretId = "bz765sfnx4wsr6axx91b09ugi56jvzqox"
  35. MapPrivateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJ/7TuC6YrE6wX4qIyKi7ZmGl6cyYkmTwohCsvAnUdTK1l2uX2C4/lVybgFCp4dklZZgNewDDG8jMSp1KxXVUE4TxEJQQt8g1qx0JWPs1GPz5vP67yMndLbGfm360SDLjgnEBYKcpWe65f6eAPjFXgBrwdue2kZBHqTGRB8LwweVAgMBAAECgYABZx67RxHJJA7A9cr2aXSpPU45ym36NIV8KbmP9DL6KV0qgnZA+Yj2uYN6wgQzYmUSuyfojeOfWzD516qCYoB1wJYXXL3OgDP0HLJZ6WsZfIHC4uSfIRtfepccfGDxjWTCoQHYoHMC1uWww79XjqS6bnRgXCulG7itg9SHHfO2cQJBANVuktJq/bZJFGt7tXvV1IAqJ6Cc5zS62OmAeQ7YYJJIdh9xdtW0ASGzVS6Cj5wPfXp/SsfKl9ZGfql3BaeOzhsCQQC/46qqds6ztKfIAs1uKwB7M0SjASXLmO/+4dubvkabbyT4tcSqmAdOt0RqGb7/AgE6QU/an3IdbUcl/RXpLhwPAkBF0CZsd5zHzH3Gbq+9cwNQbPmLWudx4xBiyKhQh8yG7PbecCHb40ZffKaHUSOie5qiwBJ46bbi2ypBSnJqDZczAkBMEjhtXa4yJdNCAoJoQ1nsfXWfXWwbW6UBGY7THkqlghlZE85EhwKWnSbdHRnPxH6yFoROulkl+1VyZPPTvjjXAkEAryJwhKTIYXwc+cgUhWeLY/Yehj6iuwWwOfT9UbuwjnhKgKmn2tPnwY8JJcQQ99zBhQDWizj7Z9F+LlkMR6rlxw=="
  36. )
  37. func InitApiClient() {
  38. var err error
  39. c_log.GlobalLogger.Info("初始化Pji Api客户端对象 - 开始。")
  40. priv, err := ParsePrivateKey(MapPrivateKey)
  41. if err != nil {
  42. c_log.GlobalLogger.Error("无法解析私钥:", err)
  43. }
  44. // 创建客户端
  45. ApiClient, err = NewSysUserApiClient(priv)
  46. if err != nil {
  47. c_log.GlobalLogger.Error("无法创建 Pji Api客户端:", err)
  48. }
  49. c_log.GlobalLogger.Info("初始化Pji Api客户端对象 - 成功。")
  50. }
  51. // SysUserApiClient 是用于API交互的客户端结构体
  52. type SysUserApiClient struct {
  53. HttpClient *client.Client // Hertz客户端实例
  54. PrivateKey *rsa.PrivateKey // RSA私钥
  55. }
  56. // NewSysUserApiClient 创建并返回一个SysUserApiClient实例
  57. func NewSysUserApiClient(privateKey *rsa.PrivateKey) (*SysUserApiClient, error) {
  58. hClient, err := client.NewClient(client.WithTLSConfig(&tls.Config{
  59. InsecureSkipVerify: true,
  60. }))
  61. if err != nil {
  62. return nil, err
  63. }
  64. return &SysUserApiClient{
  65. HttpClient: hClient,
  66. PrivateKey: privateKey,
  67. }, nil
  68. }
  69. func ParsePrivateKey(privateKeyPEM string) (*rsa.PrivateKey, error) {
  70. privateKeyPEM = FormatPrivateKey(privateKeyPEM)
  71. //fmt.Println("privateKeyPEM", privateKeyPEM)
  72. // 解码私钥字节,生成加密对象
  73. block, _ := pem.Decode([]byte(privateKeyPEM))
  74. if block == nil {
  75. return nil, errors.New("私钥信息错误!")
  76. }
  77. //fmt.Println("block", block.Bytes)
  78. // 生成私钥对象
  79. priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
  80. if err != nil {
  81. return nil, err
  82. }
  83. // 类型断言为*RSA私钥
  84. privateKey := priKey.(*rsa.PrivateKey)
  85. return privateKey, nil
  86. }
  87. func FormatPrivateKey(privateKey string) string {
  88. if !strings.HasPrefix(privateKey, PEM_BEGIN) {
  89. privateKey = PEM_BEGIN + privateKey
  90. }
  91. if !strings.HasSuffix(privateKey, PEM_END) {
  92. privateKey = privateKey + PEM_END
  93. }
  94. return privateKey
  95. }
  96. // 辅助函数:对Map的键进行排序
  97. func sortMapByKey(m map[string]interface{}) map[string]interface{} {
  98. sortedMap := make(map[string]interface{})
  99. keys := make([]string, 0, len(m))
  100. for k := range m {
  101. keys = append(keys, k)
  102. }
  103. sort.Strings(keys)
  104. for _, k := range keys {
  105. sortedMap[k] = m[k]
  106. }
  107. return sortedMap
  108. }
  109. // 生成SHA-256哈希并进行RSA签名
  110. func (c *SysUserApiClient) generateSignature(val string) (string, error) {
  111. fmt.Println("val", val)
  112. // 签名摘要
  113. hash := sha256.New()
  114. hash.Write([]byte(val))
  115. hashed := hash.Sum(nil)
  116. fmt.Println("hashed", hashed)
  117. str := hex.EncodeToString(hashed)
  118. bytes := []byte(str)
  119. fmt.Println("str", str)
  120. fmt.Println("bytes", bytes)
  121. signedData, err := rsa.SignPKCS1v15(rand.Reader, c.PrivateKey, 0, bytes)
  122. str = hex.EncodeToString(signedData)
  123. if err != nil {
  124. return "", err
  125. }
  126. fmt.Println("base64", str)
  127. fmt.Println("base64 signedData", base64.StdEncoding.EncodeToString([]byte(str)))
  128. return base64.StdEncoding.EncodeToString([]byte(str)), nil
  129. }
  130. // 通用请求生成函数,设置通用头部信息
  131. func (c *SysUserApiClient) getHttpRequest(method string, url string, secretId string, encode string) *protocol.Request {
  132. req := protocol.AcquireRequest()
  133. req.Header.SetMethod(method)
  134. req.SetRequestURI(url)
  135. req.Header.Set("PJI-TIMESTAMP", strconv.FormatInt(time.Now().Unix(), 10))
  136. req.Header.Set("PJI-API-VERSION", "v1.0")
  137. req.Header.Set("PJI-ALGORITHM", "SHA3-256")
  138. req.Header.Set("PJI-SECRET-ID", secretId)
  139. req.Header.Set("PJI-ABSTRACT-SIGN", encode)
  140. return req
  141. }
  142. // JsonPostRequest 发送带有JSON请求体的POST请求
  143. func (c *SysUserApiClient) JsonPostRequest(url string, paramMap map[string]interface{}, secretId string) (*protocol.Response, error) {
  144. paramMap = sortMapByKey(paramMap)
  145. jsonData, err := json.Marshal(paramMap)
  146. fmt.Println("jsonData", string(jsonData))
  147. if err != nil {
  148. return nil, err
  149. }
  150. str := string(jsonData)
  151. if str == "{}" {
  152. return nil, nil
  153. }
  154. signature, err := c.generateSignature(str)
  155. if err != nil {
  156. return nil, err
  157. }
  158. req := c.getHttpRequest("POST", url, secretId, signature)
  159. req.SetBody(jsonData)
  160. req.Header.Set("Content-Type", "application/json")
  161. resp := protocol.AcquireResponse()
  162. ctx := context.Background()
  163. err = c.HttpClient.Do(ctx, req, resp)
  164. return resp, err
  165. }
  166. // GetRequest 发送GET请求
  167. func (c *SysUserApiClient) GetRequest(url string, paramMap map[string]interface{}, secretId string) (*protocol.Response, error) {
  168. paramMap = sortMapByKey(paramMap)
  169. jsonData, err := json.Marshal(paramMap)
  170. fmt.Println("jsonData", string(jsonData))
  171. if err != nil {
  172. return nil, err
  173. }
  174. str := string(jsonData)
  175. if str == "{}" {
  176. str = ""
  177. }
  178. signature, err := c.generateSignature(str)
  179. if err != nil {
  180. return nil, err
  181. }
  182. req := c.getHttpRequest("GET", url, secretId, signature)
  183. resp := protocol.AcquireResponse()
  184. ctx := context.Background()
  185. err = c.HttpClient.Do(ctx, req, resp)
  186. return resp, err
  187. }
  188. // UploadRequest 上传文件
  189. func (c *SysUserApiClient) UploadRequest(url string, paramMap map[string]interface{}, secretId string, file []byte) (*protocol.Response, error) {
  190. paramMap = sortMapByKey(paramMap)
  191. jsonData, err := json.Marshal(paramMap)
  192. fmt.Println("jsonData", string(jsonData))
  193. if err != nil {
  194. return nil, err
  195. }
  196. str := string(jsonData)
  197. if str == "{}" {
  198. str = ""
  199. }
  200. signature, err := c.generateSignature(str)
  201. if err != nil {
  202. return nil, err
  203. }
  204. req := c.getHttpRequest("POST", url, secretId, signature)
  205. body := &bytes.Buffer{}
  206. writer := multipart.NewWriter(body)
  207. //req.Header.Set("Content-Type", writer.FormDataContentType())
  208. req.Header.Set("Content-Type", writer.FormDataContentType())
  209. fmt.Println("req", req.Header.String())
  210. // 添加表单字段
  211. for key, val := range paramMap {
  212. part, err := writer.CreateFormField(key)
  213. if err != nil {
  214. fmt.Println("Error creating form field", key)
  215. return nil, err
  216. }
  217. part.Write([]byte(val.(string)))
  218. }
  219. formFile, err := writer.CreateFormFile("file", "map.zip")
  220. if err != nil {
  221. return nil, err
  222. }
  223. _, err = io.Copy(formFile, bytes.NewReader(file))
  224. //fmt.Println("body", body.String())
  225. writer.Close()
  226. req.SetBody(body.Bytes()) // 文件数据可以单独处理
  227. resp := protocol.AcquireResponse()
  228. ctx := context.Background()
  229. err = c.HttpClient.Do(ctx, req, resp)
  230. return resp, err
  231. }
  232. // 辅助函数:对字符串Map的键进行排序
  233. func sortMapByKeyString(m map[string]string) map[string]string {
  234. sortedMap := make(map[string]string)
  235. keys := make([]string, 0, len(m))
  236. for k := range m {
  237. keys = append(keys, k)
  238. }
  239. sort.Strings(keys)
  240. for _, k := range keys {
  241. sortedMap[k] = m[k]
  242. }
  243. return sortedMap
  244. }