base_api_try.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. // Copyright 2019 getensh.com. All rights reserved.
  2. // Use of this source code is governed by getensh.com.
  3. package base_api
  4. import (
  5. "context"
  6. "encoding/hex"
  7. "encoding/json"
  8. "fmt"
  9. "gd_management/apis"
  10. "gd_management/common.in/config"
  11. "gd_management/common.in/httpClient"
  12. "gd_management/common.in/utils"
  13. "gd_management/consts"
  14. "gd_management/errors"
  15. "github.com/astaxie/beego/orm"
  16. "github.com/tidwall/gjson"
  17. "strconv"
  18. "strings"
  19. "sync"
  20. )
  21. // convertParam 将value转为ptype指定的数据类型, 返回值依次为转换后的数据,是否是struct nil, 错误信息
  22. func convertParam(value string, ptype string, child []apis.ManagementBaseApiParam) (interface{}, bool, error) {
  23. ptype = strings.ToLower(ptype)
  24. if strings.Contains(ptype, "int") {
  25. v, _ := strconv.Atoi(value)
  26. return v, false, nil
  27. }
  28. if strings.Contains(ptype, "float") {
  29. v, _ := strconv.ParseFloat(value, 64)
  30. return v, false, nil
  31. }
  32. if strings.Contains(ptype, "bool") {
  33. if value == "true" {
  34. return true, false, nil
  35. }
  36. return false, false, nil
  37. }
  38. if strings.Contains(ptype, "list") {
  39. v := []interface{}{}
  40. if value == "" {
  41. return nil, true, nil
  42. }
  43. err := json.Unmarshal([]byte(value), &v)
  44. if err != nil {
  45. return nil, false, errors.ArgsError
  46. }
  47. return v, false, nil
  48. }
  49. if ptype == "struct" {
  50. if len(child) == 0 {
  51. return nil, true, nil
  52. }
  53. v, err := parseStructParam(child)
  54. if err != nil {
  55. return nil, false, err
  56. }
  57. return v, false, nil
  58. }
  59. return value, false, nil
  60. }
  61. func encrypt(src string, secret string,encryptType int,head map[string]string) []byte {
  62. var retMap = map[string]string{}
  63. json.Unmarshal([]byte(src),&retMap)
  64. // AES
  65. if encryptType == consts.AESCRYPTO{
  66. for k,v := range retMap{
  67. bytes, _ := config.AesEncrypt(v, secret)
  68. ret := hex.EncodeToString(bytes)
  69. retMap[k] = ret
  70. }
  71. head["encrypt_type"] = "AES"
  72. // MD5
  73. }else if encryptType == 3{
  74. //head["encrypt_type"] = "MD5"
  75. }
  76. rByte ,_ :=json.Marshal(retMap)
  77. /*bytes, _ := config.AesEncrypt(src, secret)
  78. ret := hex.EncodeToString(bytes)
  79. return ret*/
  80. return rByte
  81. }
  82. func decrypt(src string, secret string) string {
  83. if src == "" {
  84. return ""
  85. }
  86. bytes, err := hex.DecodeString(src)
  87. if err != nil {
  88. return src
  89. }
  90. ret, err := config.AesDecrypt(bytes, []byte(secret))
  91. if err != nil {
  92. return src
  93. }
  94. return string(ret)
  95. }
  96. // parseStructParam 解析结构体数据
  97. func parseStructParam(params []apis.ManagementBaseApiParam) (map[string]interface{}, error) {
  98. var m = map[string]interface{}{}
  99. for _, v := range params {
  100. value := strings.Replace(v.Value, "\r\n", "", -1)
  101. realValue, isStructNil, err := convertParam(value, v.Type, v.Child)
  102. if err != nil {
  103. return nil, err
  104. }
  105. if isStructNil == false {
  106. if v.In != "" {
  107. m[v.In] = realValue
  108. } else {
  109. m[v.Name] = realValue
  110. }
  111. }
  112. }
  113. return m, nil
  114. }
  115. // parseParam 解析数据查询入参为json字节流
  116. func parseParam(req *apis.ManagementTryBaseApiReq) ([]byte, error) {
  117. var m = map[string]interface{}{}
  118. if len(req.Params) == 0 {
  119. return nil, nil
  120. }
  121. m, err := parseStructParam(req.Params)
  122. if err != nil {
  123. return nil, err
  124. }
  125. bytes, _ := json.Marshal(m)
  126. return bytes, nil
  127. }
  128. func getSign(ts string, key string, secret string, param string) string {
  129. signtext := fmt.Sprintf("%s%s%s%s", ts, param, key, secret)
  130. signcomput := utils.MD5(signtext)
  131. return signcomput
  132. }
  133. type ApiResponse struct {
  134. Code int `json:"code" description:"返回码"`
  135. Msg string `json:"msg" description:"错误消息" default:""`
  136. Data interface{} `json:"data"`
  137. OrderNo string `json:"order_no,omitempty"`
  138. }
  139. // getUrl 组装api url
  140. func getUrl(host string, router string) string {
  141. return strings.TrimRight(host, "/") + "/" +
  142. strings.TrimPrefix(router, "/")
  143. }
  144. func getToken(user, password string) (string, error) {
  145. url := getUrl(config.Conf.GdApiHost, "/api/v1/token")
  146. apiParam := map[string]string{
  147. "user": user,
  148. "password": password,
  149. }
  150. resp, err := httpClient.HttpGetWithHead(url, map[string]string{}, apiParam)
  151. // 响应结果处理
  152. if err != nil {
  153. return "", err
  154. }
  155. token := gjson.GetBytes(resp, "token").String()
  156. if token == "" {
  157. return "", errors.LoginTokenFail
  158. }
  159. return token, nil
  160. }
  161. // ManagementTryBaseApi 数据查询接口
  162. func ManagementTryBaseApi(ctx context.Context, req *apis.ManagementTryBaseApiReq, reply *apis.ManagementTryBaseApiReply) (err error) {
  163. //ts := fmt.Sprintf("%d", time.Now().Unix())
  164. // 参数转换
  165. param, err := parseParam(req)
  166. if err != nil {
  167. return err
  168. }
  169. // 通用参数检查
  170. if req.Method == "" {
  171. return errors.ArgsError
  172. }
  173. if config.Conf.GdApiHost == "" {
  174. return errors.EtcdError
  175. }
  176. if req.AppSecret == "" || req.AppKey == "" || req.AppPassword == "" {
  177. return errors.ArgsError
  178. }
  179. token, err := getToken(req.AppKey, req.AppPassword)
  180. if err != nil {
  181. reply.Data = err.Error()
  182. if strings.Contains(reply.Data, "\"code\"") == false {
  183. m := map[string]interface{}{
  184. "code": 10002,
  185. "msg": reply.Data,
  186. "data": "",
  187. }
  188. bytes, _ := json.Marshal(m)
  189. reply.Data = string(bytes)
  190. }
  191. return nil
  192. }
  193. // url, 签名,header 准备
  194. url := getUrl(config.Conf.GdApiHost, req.Router)
  195. //appKey := req.AppKey
  196. appSecret := req.AppSecret
  197. method := strings.ToUpper(req.Method)
  198. //en := string(param)
  199. head := map[string]string{
  200. "token": token,
  201. }
  202. param = encrypt(string(param), appSecret,req.EncryptoType,head)
  203. //sign := getSign(ts, appKey, appSecret, en)
  204. if !req.MerchantAccount {
  205. if config.Conf.GdInnerAccount == "" {
  206. return errors.EtcdError
  207. }
  208. head["replace_app_key"] = config.Conf.GdInnerAccount
  209. }
  210. apiParam := map[string]string{}
  211. m := map[string]interface{}{}
  212. json.Unmarshal(param, &m)
  213. for k, v := range m {
  214. apiParam[k] = fmt.Sprintf("%v", v)
  215. }
  216. // 调用api
  217. var resp []byte
  218. if method == "GET" {
  219. resp, err = httpClient.HttpGetWithHead(url, head, apiParam)
  220. }
  221. if method == "DELETE" {
  222. resp, err = httpClient.HttpDeleteWithHead(url, head, apiParam)
  223. }
  224. if method == "POST" {
  225. bytes, _ := json.Marshal(apiParam)
  226. resp, err = httpClient.HttpPostWithHead(url, head, nil, bytes)
  227. }
  228. if method == "PUT" {
  229. bytes, _ := json.Marshal(apiParam)
  230. resp, err = httpClient.HttpPutWithHead(url, head, nil, bytes)
  231. }
  232. // 响应结果处理
  233. if err != nil {
  234. reply.Data = err.Error()
  235. if strings.Contains(reply.Data, "\"code\"") == false {
  236. m := map[string]interface{}{
  237. "code": 10002,
  238. "msg": reply.Data,
  239. "data": "",
  240. }
  241. bytes, _ := json.Marshal(m)
  242. reply.Data = string(bytes)
  243. }
  244. return nil
  245. }
  246. if len(resp) > 0 {
  247. ret := ApiResponse{}
  248. err := json.Unmarshal(resp, &ret)
  249. if err != nil {
  250. reply.Data = string(resp)
  251. return nil
  252. }
  253. if ret.Data == nil{
  254. ret.Data = ""
  255. }
  256. text := ""
  257. // AES加密
  258. if req.EncryptoType == consts.AESCRYPTO {
  259. text = decrypt(ret.Data.(string), appSecret)
  260. } else {
  261. tmpbytes, _ := json.Marshal(ret.Data)
  262. text = string(tmpbytes)
  263. }
  264. ret.Data = text
  265. bytes, _ := json.Marshal(ret)
  266. reply.Data = string(bytes)
  267. reply.OrderNo = ret.OrderNo
  268. }
  269. return err
  270. }
  271. // convertType 将字符串数据value,转化为ptype指定的类型
  272. func convertType(ptype string, value string) interface{} {
  273. ptype = strings.ToLower(ptype)
  274. if ptype == "" || strings.Contains(ptype, "string") {
  275. return value
  276. }
  277. if strings.Contains(ptype, "bool") {
  278. if value == "0" || value == "false" || value == "FALSE" {
  279. return false
  280. }
  281. return true
  282. }
  283. if strings.Contains(ptype, "int") && strings.Contains(ptype, "[") == false {
  284. ret, _ := strconv.Atoi(value)
  285. return ret
  286. }
  287. if strings.Contains(ptype, "float") && strings.Contains(ptype, "[") == false {
  288. ret, _ := strconv.ParseFloat(value, 64)
  289. return ret
  290. }
  291. return value
  292. }
  293. // batchCallApi 跑批调用api
  294. func batchCallApi(req *apis.ManagementBatchTryApiReq, m map[string]interface{}) ([]byte, error) {
  295. //ts := fmt.Sprintf("%d", time.Now().Unix())
  296. param, _ := json.Marshal(m)
  297. //config.Conf.GdApiHost = "http://192.168.1.40:61001"
  298. if config.Conf.GdApiHost == "" {
  299. return nil, errors.EtcdError
  300. }
  301. if req.AppKey == "" || req.AppSecret == "" || req.AppPassword == "" {
  302. return nil, errors.ArgsError
  303. }
  304. token, err := getToken(req.AppKey, req.AppPassword)
  305. if err != nil {
  306. return nil, err
  307. }
  308. url := getUrl(config.Conf.GdApiHost, req.Router)
  309. //appKey := req.AppKey
  310. appSecret := req.AppSecret
  311. method := strings.ToUpper(req.Method)
  312. //en := string(param)
  313. head := map[string]string{
  314. //"app_key": appKey,
  315. //: ts,
  316. //"sign": sign,
  317. "token": token,
  318. }
  319. param = encrypt(string(param), appSecret,req.EncryptoType,head)
  320. //sign := getSign(ts, appKey, appSecret, en)
  321. if !req.MerchantAccount {
  322. if config.Conf.GdInnerAccount == "" {
  323. return nil, errors.EtcdError
  324. }
  325. head["replace_app_key"] = config.Conf.GdInnerAccount
  326. }
  327. apiParam := map[string]string{}
  328. m1 := map[string]interface{}{}
  329. json.Unmarshal(param, &m1)
  330. for k, v := range m1 {
  331. apiParam[k] = fmt.Sprintf("%v", v)
  332. }
  333. if method == "GET" {
  334. return httpClient.HttpGetWithHead(url, head, apiParam)
  335. }
  336. if method == "DELETE" {
  337. return httpClient.HttpDeleteWithHead(url, head, apiParam)
  338. }
  339. if method == "POST" {
  340. bytes, _ := json.Marshal(apiParam)
  341. return httpClient.HttpPostWithHead(url, head, nil, bytes)
  342. }
  343. if method == "PUT" {
  344. bytes, _ := json.Marshal(apiParam)
  345. return httpClient.HttpPutWithHead(url, head, nil, bytes)
  346. }
  347. return nil, nil
  348. }
  349. // parseBatchAndCallMultiMode 跑批并发调接口
  350. func parseBatchAndCallMultiMode(reqstring string, req *apis.ManagementBatchTryApiReq, reply *apis.ManagementBatchTryApiReply) (stop bool) {
  351. reqstruct := []apis.ManagementBaseApiParam{}
  352. json.Unmarshal([]byte(reqstring), &reqstruct)
  353. var wg sync.WaitGroup
  354. wg.Add(len(req.Params))
  355. ret := make([]apis.BatchTryApiParams, len(req.Params))
  356. var mu sync.Mutex
  357. for i, pa := range req.Params {
  358. // index 为参数顺序,并发执行后响应结果需和请求参数顺序一致
  359. go func(index int, v string) {
  360. // 准备参数
  361. data := map[string]interface{}{}
  362. m := map[string]string{}
  363. json.Unmarshal([]byte(v), &m)
  364. for _, p := range reqstruct {
  365. if value, ok := m[p.Name]; ok {
  366. data[p.Name] = convertType(p.Type, value)
  367. }
  368. }
  369. resp, err := batchCallApi(req, data)
  370. item := apis.BatchTryApiParams{}
  371. item.Requset = v
  372. if err != nil {
  373. item.OriginResponse = err.Error()
  374. } else {
  375. ret := ApiResponse{}
  376. err := json.Unmarshal(resp, &ret)
  377. if err != nil {
  378. item.OriginResponse = string(resp)
  379. } else {
  380. // 通用错误表示后续数据不续再传递
  381. if ret.Code == 10019 ||
  382. ret.Code == 10016 ||
  383. ret.Code == 10017 ||
  384. (ret.Code >= 10004 && ret.Code <= 10013) {
  385. mu.Lock()
  386. stop = true
  387. mu.Unlock()
  388. }
  389. appSecret := req.AppSecret
  390. text := ""
  391. if req.IsCrypto {
  392. text = decrypt(ret.Data.(string), appSecret)
  393. } else {
  394. tmp, _ := json.Marshal(ret.Data)
  395. text = string(tmp)
  396. }
  397. ret.Data = text
  398. bytes, _ := json.Marshal(ret)
  399. item.Response = string(bytes)
  400. }
  401. }
  402. reply.Params = append(reply.Params, item)
  403. ret[index] = item
  404. wg.Done()
  405. }(i, pa)
  406. }
  407. wg.Wait()
  408. reply.Params = ret[:]
  409. return
  410. }
  411. // parseBatchAndCall 跑批顺序调接口
  412. func parseBatchAndCall(reqstring string, req *apis.ManagementBatchTryApiReq, reply *apis.ManagementBatchTryApiReply) (stop bool) {
  413. reqstruct := []apis.ManagementBaseApiParam{}
  414. json.Unmarshal([]byte(reqstring), &reqstruct)
  415. for _, v := range req.Params {
  416. // 准备参数
  417. data := map[string]interface{}{}
  418. m := map[string]string{}
  419. json.Unmarshal([]byte(v), &m)
  420. for _, p := range reqstruct {
  421. if value, ok := m[p.Name]; ok {
  422. data[p.Name] = convertType(p.Type, value)
  423. }
  424. }
  425. // 调用接口
  426. resp, err := batchCallApi(req, data)
  427. item := apis.BatchTryApiParams{}
  428. item.Requset = v
  429. // 响应结果处理
  430. if err != nil {
  431. item.OriginResponse = err.Error()
  432. } else {
  433. ret := ApiResponse{}
  434. err := json.Unmarshal(resp, &ret)
  435. if err != nil {
  436. item.OriginResponse = string(resp)
  437. } else {
  438. // 通用错误表示后续数据不续再传递
  439. if ret.Code == 10019 ||
  440. ret.Code == 10016 ||
  441. ret.Code == 10017 ||
  442. (ret.Code >= 10004 && ret.Code <= 10013) {
  443. stop = true
  444. }
  445. // 响应参数解密
  446. appSecret := req.AppSecret
  447. text := ""
  448. if req.IsCrypto {
  449. text = decrypt(ret.Data.(string), appSecret)
  450. } else {
  451. tmp, _ := json.Marshal(ret.Data)
  452. text = string(tmp)
  453. }
  454. ret.Data = text
  455. bytes, _ := json.Marshal(ret)
  456. item.Response = string(bytes)
  457. }
  458. //item.Response = string(resp)
  459. }
  460. reply.Params = append(reply.Params, item)
  461. }
  462. return stop
  463. }
  464. // ManagementBatchTryApi 数据跑批接口
  465. func ManagementBatchTryApi(ctx context.Context, req *apis.ManagementBatchTryApiReq, reply *apis.ManagementBatchTryApiReply) (err error) {
  466. o := orm.NewOrm()
  467. req.Router = strings.TrimPrefix(req.Router, "/")
  468. req.Method = strings.ToUpper(req.Method)
  469. sql := "select request_param from t_gd_api where router =? and method=?"
  470. reqstring := ""
  471. err = o.Raw(sql, "/"+req.Router, req.Method).QueryRow(&reqstring)
  472. if err != nil {
  473. return errors.DataBaseError
  474. }
  475. if req.MultiMode {
  476. reply.Stop = parseBatchAndCallMultiMode(reqstring, req, reply)
  477. } else {
  478. reply.Stop = parseBatchAndCall(reqstring, req, reply)
  479. }
  480. return nil
  481. }