http.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package asign
  2. import (
  3. "bytes"
  4. "crypto"
  5. "crypto/md5"
  6. "crypto/rand"
  7. "crypto/rsa"
  8. "crypto/sha1"
  9. "crypto/x509"
  10. "encoding/base64"
  11. "encoding/hex"
  12. "encoding/pem"
  13. "fmt"
  14. "io"
  15. "mime/multipart"
  16. "mtp2_if/config"
  17. "mtp2_if/logger"
  18. "net/http"
  19. "sort"
  20. "strconv"
  21. "strings"
  22. "time"
  23. )
  24. // HttpPost
  25. //
  26. // 爱签HttpPost请求方法
  27. // @param apiUrl 接口地址
  28. // @param bizData formData入参
  29. // @return rspBody response body数据
  30. // @return err 错误
  31. func HttpPost(apiUrl string, bizData map[string]interface{}) (rspBody []byte, err error) {
  32. appId := config.SerCfg.AsignCfg.AppId
  33. privateKey := fmt.Sprintf("-----BEGIN PRIVATE KEY-----\n%s\n-----END PRIVATE KEY-----", config.SerCfg.AsignCfg.PrivateKey)
  34. // fuck asign dev.
  35. timestamp := strconv.Itoa(int(time.Now().UnixMilli() + 1000*60))
  36. // 签名
  37. sortedData := sortMapByKey(bizData)
  38. signature, err := getSignature(sortedData, appId, timestamp, privateKey)
  39. if err != nil {
  40. logger.GetLogger().Errorf("[asign.HttpPost] 签名失败:" + err.Error())
  41. return
  42. }
  43. // 构建form-data请求参数
  44. var requestBody bytes.Buffer
  45. multipartWriter := multipart.NewWriter(&requestBody)
  46. multipartWriter.WriteField("appId", appId)
  47. multipartWriter.WriteField("timestamp", timestamp)
  48. multipartWriter.WriteField("bizData", sortedData)
  49. multipartWriter.Close()
  50. // 构建请求
  51. req, err := http.NewRequest("POST", apiUrl, &requestBody)
  52. // 设置请求头
  53. req.Header.Set("sign", signature)
  54. req.Header.Set("timestamp", timestamp)
  55. req.Header.Set("Content-Type", multipartWriter.FormDataContentType())
  56. // 调用接口
  57. client := &http.Client{}
  58. rsp, err := client.Do(req)
  59. if err != nil {
  60. logger.GetLogger().Errorf("[asign.HttpPost] 调用接口失败:" + err.Error())
  61. return
  62. }
  63. defer rsp.Body.Close()
  64. rspBody, err = io.ReadAll(rsp.Body)
  65. return
  66. }
  67. // 签名规范:
  68. // 1、表单提交方式:form-data
  69. // 示例:1B2M2Y8AsgTpgAmY7PhCfg==
  70. // 2、请求头部参数
  71. // 参数1:sign(签名值,具体算法参考一下的前面算法)
  72. // 参数2:timestamp(时间戳,13位)
  73. // 3、请求体参数:
  74. // 参数1:appId(appId值,每个接入者唯一一个)
  75. // 参数2:timestamp(时间戳,13位,与上述一致)
  76. // 参数3:bizData(json字符串,举个例子,比方说要传合同编号如:{"contractNo":"0001"})
  77. // 4、签名算法:
  78. // 4.1、将上述3所属的bizData(json字符串),按照阿拉伯字母排序(如:{"ba":1,"ac":2}--->{"ac":2,"ba":1}),
  79. // 4.2、将4.1排序后的字符串,将【bizData+md5(bizData)+ appId + timestatmp】拼接后利用RSA非对称加密算法(SHA1withRSA),计算出最后的签名sign,对其base64编码,放入head的key(sign)中。
  80. //
  81. // String sign ;
  82. // String rsaSuffix = jsonStr + DigestUtils.md5Hex ( jsonStr ) + appId + timestatmp ;
  83. // byte [] bytes = RSAUtils.generateSHA1withRSASignature ( rsaSuffix, privateKey ) ;
  84. // try {
  85. // sign = Base64Utils.encode ( bytes ) ;
  86. // sign = sign.replaceAll ( " \r\n" , "" ) ;
  87. // } catch ( Exception e ) {
  88. // log.error( "sdk异常", e ) ;
  89. // return ApiRespBody.create ( ApiResponseInfo. _ERROR ) ;
  90. // }
  91. func getSignature(sortedData string, appId, timestamp, privateKey string) (signature string, err error) {
  92. pem10, _ := pem.Decode([]byte(privateKey))
  93. privateKey10I, _ := x509.ParsePKCS8PrivateKey(pem10.Bytes)
  94. privateKey10 := privateKey10I.(*rsa.PrivateKey)
  95. // md5(bizData)
  96. m := md5.New()
  97. m.Write([]byte(sortedData))
  98. bdMd5Hx := hex.EncodeToString(m.Sum(nil))
  99. // 待签内容
  100. message := sortedData + bdMd5Hx + appId + timestamp
  101. h := sha1.New()
  102. h.Write([]byte(message))
  103. sum := h.Sum(nil)
  104. // 使用私钥进行签名
  105. sign, err := rsa.SignPKCS1v15(rand.Reader, privateKey10, crypto.SHA1, sum)
  106. if err != nil {
  107. fmt.Println("Error signing:", err)
  108. return
  109. }
  110. // fmt.Println(signature)
  111. signature = base64.StdEncoding.EncodeToString(sign)
  112. signature = strings.ReplaceAll(signature, "\r\n", "")
  113. return
  114. }
  115. // sortMapByKey 按key排序map返回string
  116. func sortMapByKey(data map[string]interface{}) (sortedData string) {
  117. keys := make([]string, 0, len(data))
  118. for k := range data {
  119. keys = append(keys, k)
  120. }
  121. sort.Strings(keys)
  122. for i, k := range keys {
  123. if i > 0 {
  124. sortedData += ","
  125. }
  126. switch data[k].(type) {
  127. case string:
  128. sortedData += fmt.Sprintf(`"%s":"%s"`, k, data[k].(string))
  129. case map[string]interface{}:
  130. sortedData += fmt.Sprintf(`"%s":%s`, k, sortMapByKey(data[k].(map[string]interface{})))
  131. case []interface{}:
  132. list := data[k].([]interface{})
  133. sortedData += fmt.Sprintf(`"%s":[`, k)
  134. for j, item := range list {
  135. if j > 0 {
  136. sortedData += ","
  137. }
  138. sortedData += sortMapByKey(item.(map[string]interface{}))
  139. }
  140. sortedData += "]"
  141. default:
  142. sortedData += fmt.Sprintf(`"%s":%v`, k, data[k])
  143. }
  144. }
  145. return fmt.Sprintf("{%s}", sortedData)
  146. }
  147. // func main() {
  148. // datas := make(map[string]interface{})
  149. // json.Unmarshal([]byte(`{"account":"12345","name":"张三","map":{"ccc":"adfasd","aaa":34355},"list":[{"ccc":"adfasd","aaa":34355},{"dddd":"8ghg","kkkk":12.55}]}`), &datas)
  150. // getSignature(datas, "290912417", "1701866011940",
  151. // `-----BEGIN PRIVATE KEY-----
  152. // MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAkMD+72J6iAF0ZNV+3t628lsRHfJ80nKZWK5/C7Pg+AZmOIzJlwHsKhRzCvxoxqYHQprhiFzW9l73v9vD9l1JYwIDAQABAkBVijccr01JYdKuY5t9iI8D2NzcnZc1pZMI3NUmzT18Uyg7b9CUvGHlLeg/gdT4QtVd7wIzHYCY4letEcEMh54BAiEAwzNWusj5XiLmty7PI0Hbakx4HtcND1+P0UHLEWqWOuECIQC91zQuL7nStgGzT3HvaeBB5Ouapa39fHRm2nCjHaxwwwIgRR2XdvmUOj23XWMomr5F14SN/7V7fVcD0D8wjNElsmECIDYavV5kb7tj7/wgqkInlKhzC8rZaUsTS0F9BBkY/eptAiAQJ8Saz8YlMIESdHMxANGSog01fECbcZqLFMuNf8SorA==
  153. // -----END PRIVATE KEY-----`)
  154. // }