常用类型及数据操作方法
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.

402 lines
10 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. log.Println("拼接后的数据: ", build_str)
  112. return build_str
  113. }
  114. // 生成签名sign--聚合支付
  115. func SetSign(data map[string]interface{}, privateKey string) string {
  116. log.Println("招行加签start")
  117. build_str := CmbHttpBuildQuery(data, true)
  118. priv := new(sm2.PrivateKey)
  119. priv.Curve = sm2.GetSm2P256V1()
  120. dBytes, _ := hex.DecodeString(privateKey)
  121. priv.D = new(big.Int).SetBytes(dBytes)
  122. signature, err := sm2.Sign(priv, []byte("1234567812345678"), []byte(build_str))
  123. if err != nil {
  124. log.Println("国密加密异常", err)
  125. return ""
  126. }
  127. sign := base64.StdEncoding.EncodeToString(signature)
  128. log.Println("加密后sign值: ", sign)
  129. log.Println("招行加签end")
  130. return sign
  131. }
  132. // 创建请求头信息--聚合支付
  133. func HeaderInfo(appid, secret, sign string) map[string]string {
  134. if appid == "" || secret == "" || sign == "" {
  135. return map[string]string{}
  136. }
  137. headerData := map[string]string{}
  138. headerData["appid"] = appid
  139. headerData["sign"] = sign
  140. headerData["secret"] = secret
  141. headerData["timestamp"] = ToStr(time.Now().Unix())
  142. build_str := CmbHttpBuildQuery(MapStringToInterface(headerData), false)
  143. headerData["apisign"] = crypter.Md5Str(build_str)
  144. delete(headerData, "sign")
  145. delete(headerData, "secret")
  146. log.Println("header信息", headerData)
  147. return headerData
  148. }
  149. // 接口验签--各客户端请求我们接口验签
  150. func CheckSign(appid, app_secret, timeStamp, nonce, sign string, body map[string]interface{}) error {
  151. log.Println("请求验签start")
  152. /*time_now := time.Now().Unix()
  153. if time_now-ToInt64(timeStamp) > 10 {
  154. return errors.New("请求时间超出范围,拒绝访问")
  155. }*/
  156. sign_info := map[string]interface{}{
  157. "appid": appid,
  158. "timestamp": timeStamp,
  159. "nonce": nonce,
  160. }
  161. if len(body) > 0 {
  162. body_format := FormatBodyDataNoList(body)
  163. sign_info = MergeMapData(sign_info, body_format)
  164. }
  165. str := CmbHttpBuildQuery(sign_info, false) + "&" + app_secret
  166. log.Println("加密前数据: ", str)
  167. sign_str := crypter.Md5Str(str)
  168. log.Println("加密后数据: ", sign_str)
  169. if sign_str != sign {
  170. return errors.New("签名不正确")
  171. }
  172. log.Println("请求验签end")
  173. return nil
  174. }
  175. // post 请求
  176. func PostJsonData(url string, param interface{}, headerinfo map[string]string) ([]byte, error) {
  177. httpClient := &http.Client{}
  178. params, err := json.Marshal(param)
  179. if err != nil {
  180. return []byte(""), err
  181. }
  182. log.Println(bytes.NewBuffer(params))
  183. req, err := http.NewRequest("POST", url, bytes.NewBuffer(params))
  184. if err != nil {
  185. return []byte(""), err
  186. }
  187. req.Header.Set("Content-Type", "application/json")
  188. if len(headerinfo) > 0 {
  189. for k, v := range headerinfo {
  190. req.Header[k] = []string{v}
  191. }
  192. }
  193. resp, err := httpClient.Do(req)
  194. if err != nil {
  195. return []byte(""), err
  196. }
  197. defer resp.Body.Close()
  198. body, err := ioutil.ReadAll(resp.Body)
  199. if err != nil {
  200. return []byte(""), err
  201. }
  202. return body, nil
  203. }
  204. func SetSignsm3(data map[string]interface{}) string {
  205. build_str := HttpBuildjson(data, false)
  206. h := sm3.New()
  207. h.Write([]byte(build_str))
  208. sum := h.Sum(nil)
  209. sign := hex.EncodeToString(sum)
  210. return sign
  211. }
  212. func CashierHeaderInfoCompany(appid, secret, sign, private_key string) map[string]string {
  213. if appid == "" || secret == "" || sign == "" || private_key == "" {
  214. return map[string]string{}
  215. }
  216. headerData := map[string]string{}
  217. headerData["appid"] = appid
  218. headerData["sign"] = sign
  219. headerData["secret"] = secret
  220. headerData["timestamp"] = ToStr(time.Now().Unix())
  221. headerData["apisign"] = SetSignhex(headerData, private_key)
  222. headerData["verify"] = "SM3withSM2"
  223. delete(headerData, "secret")
  224. return headerData
  225. }
  226. // 生成签名sign
  227. func SetSignhex(data map[string]string, privateKey string) string {
  228. build_str := CmbHttpBuildQuery(MapStringToInterface(data), false)
  229. priv := new(sm2.PrivateKey)
  230. priv.Curve = sm2.GetSm2P256V1()
  231. dBytes, _ := hex.DecodeString(privateKey)
  232. priv.D = new(big.Int).SetBytes(dBytes)
  233. sign, _ := sm2.Sign(priv, []byte("1234567812345678"), []byte(build_str))
  234. sign = SM2Asn1ToRaw(sign)
  235. return hex.EncodeToString(sign)
  236. }
  237. func SM2Asn1ToRaw(data []byte) []byte {
  238. i := 3
  239. ret := []byte{}
  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. i = i + 32
  249. i = i + 1
  250. if data[i] == 32 {
  251. i = i + 1
  252. } else if data[i] == 33 {
  253. i = i + 2
  254. }
  255. for k := 0; k < 32; k++ {
  256. ret = append(ret, data[i+k])
  257. }
  258. return ret
  259. }
  260. // 字符串排序拼接
  261. func HttpBuildjson(data map[string]interface{}, filter_sign bool) string {
  262. keySlice := []string{}
  263. res := map[string]interface{}{}
  264. // 剔除sign字段
  265. for k, _ := range data {
  266. if filter_sign && k == "sign" {
  267. continue
  268. }
  269. keySlice = append(keySlice, k)
  270. }
  271. // 排序字符串
  272. sort.Strings(keySlice)
  273. for _, value := range keySlice {
  274. if value != "" && data[value] != "" {
  275. res[value] = data[value]
  276. }
  277. }
  278. ss, _ := json.Marshal(res)
  279. log.Println("拼接后的数据: ", string(ss))
  280. return string(ss)
  281. }
  282. // body参数处理
  283. func FormatBodyDataNoList(body map[string]interface{}) map[string]interface{} {
  284. data := map[string]interface{}{}
  285. if len(body) > 0 {
  286. for k, v := range body {
  287. typeOfA := reflect.TypeOf(v)
  288. if typeOfA.Kind().String() == "map" || typeOfA.Kind().String() == "slice" {
  289. continue
  290. } else {
  291. if typeOfA.Kind().String() == "string" {
  292. if ToStr(v) != "" {
  293. data[k] = v
  294. }
  295. }
  296. }
  297. }
  298. }
  299. return data
  300. }
  301. // 聚合支付异步回调验签
  302. func JhNotifyCheckSign(sign, public_key string, data map[string]string) bool {
  303. build_sort_str := CmbHttpBuildQuery(MapStringToInterface(data), true)
  304. pub_x := ""
  305. pub_y := ""
  306. // 私钥截取
  307. if len(public_key) == 128 {
  308. pub_x = public_key[:64]
  309. pub_y = public_key[64:]
  310. } else if len(public_key) == 130 && (public_key[:2] == "04") {
  311. public_key = public_key[2:]
  312. pub_x = public_key[:64]
  313. pub_y = public_key[64:]
  314. } else {
  315. log.Println("异步验签公钥出错", public_key)
  316. return false
  317. }
  318. sign_b64, _ := base64.StdEncoding.DecodeString(sign)
  319. pub := new(sm2.PublicKey)
  320. pub.Curve = sm2.GetSm2P256V1()
  321. xBytes, _ := hex.DecodeString(pub_x)
  322. yBytes, _ := hex.DecodeString(pub_y)
  323. pub.X = new(big.Int).SetBytes(xBytes)
  324. pub.Y = new(big.Int).SetBytes(yBytes)
  325. result := sm2.Verify(pub, []byte("1234567812345678"), []byte(build_sort_str), sign_b64)
  326. if !result {
  327. return false
  328. }
  329. return true
  330. }