常用类型及数据操作方法
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
9.8 KiB

  1. package helper
  2. import (
  3. "bytes"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "errors"
  7. "git.tetele.net/tgo/crypter"
  8. "github.com/ZZMarquis/gm/sm2"
  9. "github.com/ZZMarquis/gm/sm3"
  10. jsoniter "github.com/json-iterator/go"
  11. "io/ioutil"
  12. "log"
  13. "math/big"
  14. "net/http"
  15. "reflect"
  16. "sort"
  17. "strings"
  18. "time"
  19. )
  20. var json = jsoniter.ConfigCompatibleWithStandardLibrary
  21. // 合并map数据
  22. func MergeMapData(x, y map[string]interface{}) map[string]interface{} {
  23. n := make(map[string]interface{})
  24. for i, v := range x {
  25. for j, w := range y {
  26. if i == j {
  27. n[i] = w
  28. } else {
  29. if _, ok := n[i]; !ok {
  30. n[i] = v
  31. }
  32. if _, ok := n[j]; !ok {
  33. n[j] = w
  34. }
  35. }
  36. }
  37. }
  38. return n
  39. }
  40. // 针对传参为json或者数组类型的字段,进行字符串排序
  41. func HttpBuildSort(data map[string]interface{}) string {
  42. keySlice := []string{}
  43. for k, _ := range data {
  44. keySlice = append(keySlice, k)
  45. }
  46. // 排序字符串
  47. sort.Strings(keySlice)
  48. res := make(map[string]interface{}, 0)
  49. for _, value := range keySlice {
  50. data_val := ToStr(data[value])
  51. if value != "" && data_val != "" {
  52. res[value] = data_val
  53. }
  54. }
  55. res_byte, _ := json.Marshal(res)
  56. return string(res_byte)
  57. }
  58. // body参数处理
  59. func FormatBodyData(body map[string]interface{}) map[string]interface{} {
  60. data := map[string]interface{}{}
  61. if len(body) > 0 {
  62. for k, v := range body {
  63. typeOfA := reflect.TypeOf(v)
  64. if typeOfA.Kind().String() == "map" {
  65. build_str_format, _ := InterfaceToMapInterface(v)
  66. if len(build_str_format) < 1 {
  67. continue
  68. }
  69. // json键值对处理
  70. data[k] = HttpBuildSort(build_str_format)
  71. // log.Println("排序后的数据: ", data[k])
  72. } else if typeOfA.Kind().String() == "slice" {
  73. val_slice := []interface{}{}
  74. // json键值对处理
  75. for _, val_inter := range v.([]interface{}) {
  76. val_map, _ := InterfaceToMapInterface(val_inter)
  77. each_val := HttpBuildSort(val_map)
  78. val_slice = append(val_slice, each_val)
  79. }
  80. if len(val_slice) < 1 {
  81. continue
  82. }
  83. data[k] = val_slice
  84. // log.Println("排序后的数据: ", data[k])
  85. } else {
  86. data[k] = v
  87. }
  88. }
  89. }
  90. return data
  91. }
  92. // 字符串排序拼接
  93. func CmbHttpBuildQuery(data map[string]interface{}, filter_sign bool) string {
  94. keySlice := []string{}
  95. // 剔除sign字段
  96. for k, _ := range data {
  97. if filter_sign && k == "sign" {
  98. continue
  99. }
  100. keySlice = append(keySlice, k)
  101. }
  102. // 排序字符串
  103. sort.Strings(keySlice)
  104. var query string
  105. for _, value := range keySlice {
  106. if value != "" && data[value] != "" {
  107. query += StringJoin(value, "=", ToStr(data[value]), "&")
  108. }
  109. }
  110. build_str := strings.Trim(query, "&")
  111. return build_str
  112. }
  113. // 生成签名sign--聚合支付
  114. func SetSign(data map[string]interface{}, privateKey string) string {
  115. build_str := CmbHttpBuildQuery(data, true)
  116. priv := new(sm2.PrivateKey)
  117. priv.Curve = sm2.GetSm2P256V1()
  118. dBytes, _ := hex.DecodeString(privateKey)
  119. priv.D = new(big.Int).SetBytes(dBytes)
  120. signature, err := sm2.Sign(priv, []byte("1234567812345678"), []byte(build_str))
  121. if err != nil {
  122. log.Println("国密加密异常", err)
  123. return ""
  124. }
  125. sign := base64.StdEncoding.EncodeToString(signature)
  126. return sign
  127. }
  128. // 创建请求头信息--聚合支付
  129. func HeaderInfo(appid, secret, sign string) map[string]string {
  130. if appid == "" || secret == "" || sign == "" {
  131. return map[string]string{}
  132. }
  133. headerData := map[string]string{}
  134. headerData["appid"] = appid
  135. headerData["sign"] = sign
  136. headerData["secret"] = secret
  137. headerData["timestamp"] = ToStr(time.Now().Unix())
  138. build_str := CmbHttpBuildQuery(MapStringToInterface(headerData), false)
  139. headerData["apisign"] = crypter.Md5Str(build_str)
  140. delete(headerData, "sign")
  141. delete(headerData, "secret")
  142. return headerData
  143. }
  144. // 接口验签--各客户端请求我们接口验签
  145. func CheckSign(appid, app_secret, timeStamp, nonce, sign string, body map[string]interface{}) error {
  146. /*time_now := time.Now().Unix()
  147. if time_now-ToInt64(timeStamp) > 10 {
  148. return errors.New("请求时间超出范围,拒绝访问")
  149. }*/
  150. sign_info := map[string]interface{}{
  151. "appid": appid,
  152. "timestamp": timeStamp,
  153. "nonce": nonce,
  154. }
  155. if len(body) > 0 {
  156. body_format := FormatBodyDataNoList(body)
  157. sign_info = MergeMapData(sign_info, body_format)
  158. }
  159. str := CmbHttpBuildQuery(sign_info, false) + "&" + app_secret
  160. sign_str := crypter.Md5Str(str)
  161. if sign_str != sign {
  162. return errors.New("签名不正确")
  163. }
  164. return nil
  165. }
  166. // post 请求
  167. func PostJsonData(url string, param interface{}, headerinfo map[string]string) ([]byte, error) {
  168. httpClient := &http.Client{}
  169. params, err := json.Marshal(param)
  170. if err != nil {
  171. return []byte(""), err
  172. }
  173. req, err := http.NewRequest("POST", url, bytes.NewBuffer(params))
  174. if err != nil {
  175. return []byte(""), err
  176. }
  177. req.Header.Set("Content-Type", "application/json")
  178. if len(headerinfo) > 0 {
  179. for k, v := range headerinfo {
  180. req.Header[k] = []string{v}
  181. }
  182. }
  183. resp, err := httpClient.Do(req)
  184. if err != nil {
  185. return []byte(""), err
  186. }
  187. defer resp.Body.Close()
  188. body, err := ioutil.ReadAll(resp.Body)
  189. if err != nil {
  190. return []byte(""), err
  191. }
  192. return body, nil
  193. }
  194. func SetSignsm3(data map[string]interface{}) string {
  195. build_str := HttpBuildjson(data, false)
  196. h := sm3.New()
  197. h.Write([]byte(build_str))
  198. sum := h.Sum(nil)
  199. sign := hex.EncodeToString(sum)
  200. return sign
  201. }
  202. func CashierHeaderInfoCompany(appid, secret, sign, private_key string) map[string]string {
  203. if appid == "" || secret == "" || sign == "" || private_key == "" {
  204. return map[string]string{}
  205. }
  206. headerData := map[string]string{}
  207. headerData["appid"] = appid
  208. headerData["sign"] = sign
  209. headerData["secret"] = secret
  210. headerData["timestamp"] = ToStr(time.Now().Unix())
  211. headerData["apisign"] = SetSignhex(headerData, private_key)
  212. headerData["verify"] = "SM3withSM2"
  213. delete(headerData, "secret")
  214. return headerData
  215. }
  216. // 生成签名sign
  217. func SetSignhex(data map[string]string, privateKey string) string {
  218. build_str := CmbHttpBuildQuery(MapStringToInterface(data), false)
  219. priv := new(sm2.PrivateKey)
  220. priv.Curve = sm2.GetSm2P256V1()
  221. dBytes, _ := hex.DecodeString(privateKey)
  222. priv.D = new(big.Int).SetBytes(dBytes)
  223. sign, _ := sm2.Sign(priv, []byte("1234567812345678"), []byte(build_str))
  224. sign = SM2Asn1ToRaw(sign)
  225. return hex.EncodeToString(sign)
  226. }
  227. func SM2Asn1ToRaw(data []byte) []byte {
  228. i := 3
  229. ret := []byte{}
  230. if data[i] == 32 {
  231. i = i + 1
  232. } else if data[i] == 33 {
  233. i = i + 2
  234. }
  235. for k := 0; k < 32; k++ {
  236. ret = append(ret, data[i+k])
  237. }
  238. i = i + 32
  239. i = i + 1
  240. if data[i] == 32 {
  241. i = i + 1
  242. } else if data[i] == 33 {
  243. i = i + 2
  244. }
  245. for k := 0; k < 32; k++ {
  246. ret = append(ret, data[i+k])
  247. }
  248. return ret
  249. }
  250. // 字符串排序拼接
  251. func HttpBuildjson(data map[string]interface{}, filter_sign bool) string {
  252. keySlice := []string{}
  253. res := map[string]interface{}{}
  254. // 剔除sign字段
  255. for k, _ := range data {
  256. if filter_sign && k == "sign" {
  257. continue
  258. }
  259. keySlice = append(keySlice, k)
  260. }
  261. // 排序字符串
  262. sort.Strings(keySlice)
  263. for _, value := range keySlice {
  264. if value != "" && data[value] != "" {
  265. res[value] = data[value]
  266. }
  267. }
  268. ss, _ := json.Marshal(res)
  269. return string(ss)
  270. }
  271. // body参数处理
  272. func FormatBodyDataNoList(body map[string]interface{}) map[string]interface{} {
  273. data := map[string]interface{}{}
  274. if len(body) > 0 {
  275. for k, v := range body {
  276. typeOfA := reflect.TypeOf(v)
  277. if typeOfA.Kind().String() == "map" || typeOfA.Kind().String() == "slice" {
  278. continue
  279. } else {
  280. if typeOfA.Kind().String() == "string" {
  281. if ToStr(v) != "" {
  282. data[k] = v
  283. }
  284. }
  285. }
  286. }
  287. }
  288. return data
  289. }
  290. // 聚合支付异步回调验签
  291. func JhNotifyCheckSign(sign, public_key string, data map[string]string) bool {
  292. build_sort_str := CmbHttpBuildQuery(MapStringToInterface(data), true)
  293. pub_x := ""
  294. pub_y := ""
  295. // 私钥截取
  296. if len(public_key) == 128 {
  297. pub_x = public_key[:64]
  298. pub_y = public_key[64:]
  299. } else if len(public_key) == 130 && (public_key[:2] == "04") {
  300. public_key = public_key[2:]
  301. pub_x = public_key[:64]
  302. pub_y = public_key[64:]
  303. } else {
  304. log.Println("异步验签公钥出错", public_key)
  305. return false
  306. }
  307. sign_b64, _ := base64.StdEncoding.DecodeString(sign)
  308. pub := new(sm2.PublicKey)
  309. pub.Curve = sm2.GetSm2P256V1()
  310. xBytes, _ := hex.DecodeString(pub_x)
  311. yBytes, _ := hex.DecodeString(pub_y)
  312. pub.X = new(big.Int).SetBytes(xBytes)
  313. pub.Y = new(big.Int).SetBytes(yBytes)
  314. result := sm2.Verify(pub, []byte("1234567812345678"), []byte(build_sort_str), sign_b64)
  315. if !result {
  316. return false
  317. }
  318. return true
  319. }