api.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. "errors"
  14. "fmt"
  15. "io"
  16. "mime/multipart"
  17. "mtp2_if/config"
  18. "mtp2_if/logger"
  19. "net/http"
  20. "reflect"
  21. "sort"
  22. "strconv"
  23. "strings"
  24. "time"
  25. "github.com/bytedance/sonic"
  26. "github.com/bytedance/sonic/encoder"
  27. )
  28. func APIPost[T1 APIReqData, T2 APIRspData](req APIReq[T1], apiPort APIURL) (rsp *APIRsp[T2], err error) {
  29. apiUrl := config.SerCfg.AsignCfg.Url + string(apiPort)
  30. var rspBody []byte
  31. rspBody, err = httpPost(apiUrl, req.Data)
  32. if err != nil {
  33. return
  34. }
  35. rspStr := string(rspBody)
  36. if len(rspStr) == 0 {
  37. logger.GetLogger().Error("调用接口 " + apiUrl + " 错误, response为空")
  38. err = errors.New("调用接口返回内容为空")
  39. return
  40. }
  41. rsp = new(APIRsp[T2])
  42. err = sonic.Unmarshal(rspBody, rsp)
  43. return
  44. }
  45. func httpPost(apiUrl string, bizData ...interface{}) (rspBody []byte, err error) {
  46. appId := config.SerCfg.AsignCfg.AppId
  47. privateKey := fmt.Sprintf("-----BEGIN PRIVATE KEY-----\n%s\n-----END PRIVATE KEY-----", config.SerCfg.AsignCfg.PrivateKey)
  48. // fuck asign dev.
  49. timestamp := strconv.Itoa(int(time.Now().UnixMilli() + 10000*60))
  50. // 排序key
  51. var b []byte
  52. if len(bizData) == 1 {
  53. b, err = encoder.Encode(bizData[0], encoder.SortMapKeys)
  54. } else {
  55. b, err = encoder.Encode(bizData, encoder.SortMapKeys)
  56. }
  57. if err != nil {
  58. logger.GetLogger().Errorf("处理入参排序失败:" + err.Error())
  59. return
  60. }
  61. sortedData := string(b)
  62. // 签名
  63. signature, err := getSignature(sortedData, appId, timestamp, privateKey)
  64. if err != nil {
  65. logger.GetLogger().Errorf("签名失败:" + err.Error())
  66. return
  67. }
  68. // 构建form-data请求参数
  69. var requestBody bytes.Buffer
  70. multipartWriter := multipart.NewWriter(&requestBody)
  71. multipartWriter.WriteField("appId", appId)
  72. multipartWriter.WriteField("timestamp", timestamp)
  73. multipartWriter.WriteField("bizData", sortedData)
  74. multipartWriter.Close()
  75. // 构建请求
  76. req, err := http.NewRequest("POST", apiUrl, &requestBody)
  77. // 设置请求头
  78. req.Header.Set("sign", signature)
  79. req.Header.Set("timestamp", timestamp)
  80. req.Header.Set("Content-Type", multipartWriter.FormDataContentType())
  81. // 调用接口
  82. logger.GetLogger().Info("调用接口 "+apiUrl+" 请求, request:", sortedData)
  83. client := &http.Client{}
  84. rsp, err := client.Do(req)
  85. if err != nil {
  86. logger.GetLogger().Error("调用接口 "+apiUrl+" 错误, error:", err.Error())
  87. return
  88. }
  89. defer rsp.Body.Close()
  90. rspBody, err = io.ReadAll(rsp.Body)
  91. logger.GetLogger().Info("调用接口 "+apiUrl+" 返回, response:", string(rspBody))
  92. return
  93. }
  94. // 签名规范:
  95. // 1、表单提交方式:form-data
  96. // 示例:1B2M2Y8AsgTpgAmY7PhCfg==
  97. // 2、请求头部参数
  98. // 参数1:sign(签名值,具体算法参考一下的前面算法)
  99. // 参数2:timestamp(时间戳,13位)
  100. // 3、请求体参数:
  101. // 参数1:appId(appId值,每个接入者唯一一个)
  102. // 参数2:timestamp(时间戳,13位,与上述一致)
  103. // 参数3:bizData(json字符串,举个例子,比方说要传合同编号如:{"contractNo":"0001"})
  104. // 4、签名算法:
  105. // 4.1、将上述3所属的bizData(json字符串),按照阿拉伯字母排序(如:{"ba":1,"ac":2}--->{"ac":2,"ba":1}),
  106. // 4.2、将4.1排序后的字符串,将【bizData+md5(bizData)+ appId + timestatmp】拼接后利用RSA非对称加密算法(SHA1withRSA),计算出最后的签名sign,对其base64编码,放入head的key(sign)中。
  107. //
  108. // String sign ;
  109. // String rsaSuffix = jsonStr + DigestUtils.md5Hex ( jsonStr ) + appId + timestatmp ;
  110. // byte [] bytes = RSAUtils.generateSHA1withRSASignature ( rsaSuffix, privateKey ) ;
  111. // try {
  112. // sign = Base64Utils.encode ( bytes ) ;
  113. // sign = sign.replaceAll ( " \r\n" , "" ) ;
  114. // } catch ( Exception e ) {
  115. // log.error( "sdk异常", e ) ;
  116. // return ApiRespBody.create ( ApiResponseInfo. _ERROR ) ;
  117. // }
  118. func getSignature(sortedData string, appId, timestamp, privateKey string) (signature string, err error) {
  119. pem10, _ := pem.Decode([]byte(privateKey))
  120. privateKey10I, _ := x509.ParsePKCS8PrivateKey(pem10.Bytes)
  121. privateKey10 := privateKey10I.(*rsa.PrivateKey)
  122. // md5(bizData)
  123. m := md5.New()
  124. m.Write([]byte(sortedData))
  125. bdMd5Hx := hex.EncodeToString(m.Sum(nil))
  126. // 待签内容
  127. message := sortedData + bdMd5Hx + appId + timestamp
  128. h := sha1.New()
  129. h.Write([]byte(message))
  130. sum := h.Sum(nil)
  131. // 使用私钥进行签名
  132. sign, err := rsa.SignPKCS1v15(rand.Reader, privateKey10, crypto.SHA1, sum)
  133. if err != nil {
  134. return
  135. }
  136. // fmt.Println(signature)
  137. signature = base64.StdEncoding.EncodeToString(sign)
  138. signature = strings.ReplaceAll(signature, "\r\n", "")
  139. return
  140. }
  141. // SortMapByKey 按key排序map返回string -- 已经不使用的方法
  142. func SortMapByKey(data map[string]interface{}) (sortedData string) {
  143. keys := make([]string, 0, len(data))
  144. for k := range data {
  145. keys = append(keys, k)
  146. }
  147. sort.Strings(keys)
  148. for i, k := range keys {
  149. if i > 0 {
  150. sortedData += ","
  151. }
  152. // 判断是否指针
  153. v := reflect.ValueOf(data[k])
  154. if v.Kind() == reflect.Ptr {
  155. switch data[k].(type) {
  156. case *string:
  157. sortedData += fmt.Sprintf(`"%s":"%s"`, k, *(data[k].(*string)))
  158. case *map[string]interface{}:
  159. sortedData += fmt.Sprintf(`"%s":%s`, k, SortMapByKey(*(data[k].(*map[string]interface{}))))
  160. case *[]interface{}:
  161. list := data[k].([]interface{})
  162. sortedData += fmt.Sprintf(`"%s":[`, k)
  163. for j, item := range list {
  164. if j > 0 {
  165. sortedData += ","
  166. }
  167. sortedData += SortMapByKey(item.(map[string]interface{}))
  168. }
  169. sortedData += "]"
  170. default:
  171. sortedData += fmt.Sprintf(`"%s":%v`, k, reflect.ValueOf(data[k]).Elem())
  172. }
  173. } else {
  174. switch data[k].(type) {
  175. case string:
  176. sortedData += fmt.Sprintf(`"%s":"%s"`, k, data[k].(string))
  177. case map[string]interface{}:
  178. sortedData += fmt.Sprintf(`"%s":%s`, k, SortMapByKey(data[k].(map[string]interface{})))
  179. case []interface{}:
  180. list := data[k].([]interface{})
  181. sortedData += fmt.Sprintf(`"%s":[`, k)
  182. for j, item := range list {
  183. if j > 0 {
  184. sortedData += ","
  185. }
  186. sortedData += SortMapByKey(item.(map[string]interface{}))
  187. }
  188. sortedData += "]"
  189. default:
  190. sortedData += fmt.Sprintf(`"%s":%v`, k, data[k])
  191. }
  192. }
  193. }
  194. return fmt.Sprintf("{%s}", sortedData)
  195. }