123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- // Copyright 2019 getensh.com. All rights reserved.
- // Use of this source code is governed by getensh.com.
- package base_api
- import (
- "context"
- "encoding/hex"
- "encoding/json"
- "fmt"
- "gd_management/apis"
- "gd_management/common.in/config"
- "gd_management/common.in/httpClient"
- "gd_management/common.in/utils"
- "gd_management/consts"
- "gd_management/errors"
- "github.com/astaxie/beego/orm"
- "github.com/tidwall/gjson"
- "strconv"
- "strings"
- "sync"
- )
- // convertParam 将value转为ptype指定的数据类型, 返回值依次为转换后的数据,是否是struct nil, 错误信息
- func convertParam(value string, ptype string, child []apis.ManagementBaseApiParam) (interface{}, bool, error) {
- ptype = strings.ToLower(ptype)
- if strings.Contains(ptype, "int") {
- v, _ := strconv.Atoi(value)
- return v, false, nil
- }
- if strings.Contains(ptype, "float") {
- v, _ := strconv.ParseFloat(value, 64)
- return v, false, nil
- }
- if strings.Contains(ptype, "bool") {
- if value == "true" {
- return true, false, nil
- }
- return false, false, nil
- }
- if strings.Contains(ptype, "list") {
- v := []interface{}{}
- if value == "" {
- return nil, true, nil
- }
- err := json.Unmarshal([]byte(value), &v)
- if err != nil {
- return nil, false, errors.ArgsError
- }
- return v, false, nil
- }
- if ptype == "struct" {
- if len(child) == 0 {
- return nil, true, nil
- }
- v, err := parseStructParam(child)
- if err != nil {
- return nil, false, err
- }
- return v, false, nil
- }
- return value, false, nil
- }
- func encrypt(src string, secret string,encryptType int,head map[string]string) []byte {
- var retMap = map[string]string{}
- json.Unmarshal([]byte(src),&retMap)
- // AES
- if encryptType == consts.AESCRYPTO{
- for k,v := range retMap{
- bytes, _ := config.AesEncrypt(v, secret)
- ret := hex.EncodeToString(bytes)
- retMap[k] = ret
- }
- head["encrypt_type"] = "AES"
- // MD5
- }else if encryptType == 3{
- //head["encrypt_type"] = "MD5"
- }
- rByte ,_ :=json.Marshal(retMap)
- /*bytes, _ := config.AesEncrypt(src, secret)
- ret := hex.EncodeToString(bytes)
- return ret*/
- return rByte
- }
- func decrypt(src string, secret string) string {
- if src == "" {
- return ""
- }
- bytes, err := hex.DecodeString(src)
- if err != nil {
- return src
- }
- ret, err := config.AesDecrypt(bytes, []byte(secret))
- if err != nil {
- return src
- }
- return string(ret)
- }
- // parseStructParam 解析结构体数据
- func parseStructParam(params []apis.ManagementBaseApiParam) (map[string]interface{}, error) {
- var m = map[string]interface{}{}
- for _, v := range params {
- value := strings.Replace(v.Value, "\r\n", "", -1)
- realValue, isStructNil, err := convertParam(value, v.Type, v.Child)
- if err != nil {
- return nil, err
- }
- if isStructNil == false {
- if v.In != "" {
- m[v.In] = realValue
- } else {
- m[v.Name] = realValue
- }
- }
- }
- return m, nil
- }
- // parseParam 解析数据查询入参为json字节流
- func parseParam(req *apis.ManagementTryBaseApiReq) ([]byte, error) {
- var m = map[string]interface{}{}
- if len(req.Params) == 0 {
- return nil, nil
- }
- m, err := parseStructParam(req.Params)
- if err != nil {
- return nil, err
- }
- bytes, _ := json.Marshal(m)
- return bytes, nil
- }
- func getSign(ts string, key string, secret string, param string) string {
- signtext := fmt.Sprintf("%s%s%s%s", ts, param, key, secret)
- signcomput := utils.MD5(signtext)
- return signcomput
- }
- type ApiResponse struct {
- Code int `json:"code" description:"返回码"`
- Msg string `json:"msg" description:"错误消息" default:""`
- Data interface{} `json:"data"`
- OrderNo string `json:"order_no,omitempty"`
- }
- // getUrl 组装api url
- func getUrl(host string, router string) string {
- return strings.TrimRight(host, "/") + "/" +
- strings.TrimPrefix(router, "/")
- }
- func getToken(user, password string) (string, error) {
- url := getUrl(config.Conf.GdApiHost, "/api/v1/token")
- apiParam := map[string]string{
- "user": user,
- "password": password,
- }
- resp, err := httpClient.HttpGetWithHead(url, map[string]string{}, apiParam)
- // 响应结果处理
- if err != nil {
- return "", err
- }
- token := gjson.GetBytes(resp, "token").String()
- if token == "" {
- return "", errors.LoginTokenFail
- }
- return token, nil
- }
- // ManagementTryBaseApi 数据查询接口
- func ManagementTryBaseApi(ctx context.Context, req *apis.ManagementTryBaseApiReq, reply *apis.ManagementTryBaseApiReply) (err error) {
- //ts := fmt.Sprintf("%d", time.Now().Unix())
- // 参数转换
- param, err := parseParam(req)
- if err != nil {
- return err
- }
- // 通用参数检查
- if req.Method == "" {
- return errors.ArgsError
- }
- if config.Conf.GdApiHost == "" {
- return errors.EtcdError
- }
- if req.AppSecret == "" || req.AppKey == "" || req.AppPassword == "" {
- return errors.ArgsError
- }
- token, err := getToken(req.AppKey, req.AppPassword)
- if err != nil {
- reply.Data = err.Error()
- if strings.Contains(reply.Data, "\"code\"") == false {
- m := map[string]interface{}{
- "code": 10002,
- "msg": reply.Data,
- "data": "",
- }
- bytes, _ := json.Marshal(m)
- reply.Data = string(bytes)
- }
- return nil
- }
- // url, 签名,header 准备
- url := getUrl(config.Conf.GdApiHost, req.Router)
- //appKey := req.AppKey
- appSecret := req.AppSecret
- method := strings.ToUpper(req.Method)
- //en := string(param)
- head := map[string]string{
- "token": token,
- }
- param = encrypt(string(param), appSecret,req.EncryptoType,head)
- //sign := getSign(ts, appKey, appSecret, en)
- if !req.MerchantAccount {
- if config.Conf.GdInnerAccount == "" {
- return errors.EtcdError
- }
- head["replace_app_key"] = config.Conf.GdInnerAccount
- }
- apiParam := map[string]string{}
- m := map[string]interface{}{}
- json.Unmarshal(param, &m)
- for k, v := range m {
- apiParam[k] = fmt.Sprintf("%v", v)
- }
- // 调用api
- var resp []byte
- if method == "GET" {
- resp, err = httpClient.HttpGetWithHead(url, head, apiParam)
- }
- if method == "DELETE" {
- resp, err = httpClient.HttpDeleteWithHead(url, head, apiParam)
- }
- if method == "POST" {
- bytes, _ := json.Marshal(apiParam)
- resp, err = httpClient.HttpPostWithHead(url, head, nil, bytes)
- }
- if method == "PUT" {
- bytes, _ := json.Marshal(apiParam)
- resp, err = httpClient.HttpPutWithHead(url, head, nil, bytes)
- }
- // 响应结果处理
- if err != nil {
- reply.Data = err.Error()
- if strings.Contains(reply.Data, "\"code\"") == false {
- m := map[string]interface{}{
- "code": 10002,
- "msg": reply.Data,
- "data": "",
- }
- bytes, _ := json.Marshal(m)
- reply.Data = string(bytes)
- }
- return nil
- }
- if len(resp) > 0 {
- ret := ApiResponse{}
- err := json.Unmarshal(resp, &ret)
- if err != nil {
- reply.Data = string(resp)
- return nil
- }
- if ret.Data == nil{
- ret.Data = ""
- }
- text := ""
- // AES加密
- if req.EncryptoType == consts.AESCRYPTO {
- text = decrypt(ret.Data.(string), appSecret)
- } else {
- tmpbytes, _ := json.Marshal(ret.Data)
- text = string(tmpbytes)
- }
- ret.Data = text
- bytes, _ := json.Marshal(ret)
- reply.Data = string(bytes)
- reply.OrderNo = ret.OrderNo
- }
- return err
- }
- // convertType 将字符串数据value,转化为ptype指定的类型
- func convertType(ptype string, value string) interface{} {
- ptype = strings.ToLower(ptype)
- if ptype == "" || strings.Contains(ptype, "string") {
- return value
- }
- if strings.Contains(ptype, "bool") {
- if value == "0" || value == "false" || value == "FALSE" {
- return false
- }
- return true
- }
- if strings.Contains(ptype, "int") && strings.Contains(ptype, "[") == false {
- ret, _ := strconv.Atoi(value)
- return ret
- }
- if strings.Contains(ptype, "float") && strings.Contains(ptype, "[") == false {
- ret, _ := strconv.ParseFloat(value, 64)
- return ret
- }
- return value
- }
- // batchCallApi 跑批调用api
- func batchCallApi(req *apis.ManagementBatchTryApiReq, m map[string]interface{}) ([]byte, error) {
- //ts := fmt.Sprintf("%d", time.Now().Unix())
- param, _ := json.Marshal(m)
- //config.Conf.GdApiHost = "http://192.168.1.40:61001"
- if config.Conf.GdApiHost == "" {
- return nil, errors.EtcdError
- }
- if req.AppKey == "" || req.AppSecret == "" || req.AppPassword == "" {
- return nil, errors.ArgsError
- }
- token, err := getToken(req.AppKey, req.AppPassword)
- if err != nil {
- return nil, err
- }
- url := getUrl(config.Conf.GdApiHost, req.Router)
- //appKey := req.AppKey
- appSecret := req.AppSecret
- method := strings.ToUpper(req.Method)
- //en := string(param)
- head := map[string]string{
- //"app_key": appKey,
- //: ts,
- //"sign": sign,
- "token": token,
- }
- param = encrypt(string(param), appSecret,req.EncryptoType,head)
- //sign := getSign(ts, appKey, appSecret, en)
- if !req.MerchantAccount {
- if config.Conf.GdInnerAccount == "" {
- return nil, errors.EtcdError
- }
- head["replace_app_key"] = config.Conf.GdInnerAccount
- }
- apiParam := map[string]string{}
- m1 := map[string]interface{}{}
- json.Unmarshal(param, &m1)
- for k, v := range m1 {
- apiParam[k] = fmt.Sprintf("%v", v)
- }
- if method == "GET" {
- return httpClient.HttpGetWithHead(url, head, apiParam)
- }
- if method == "DELETE" {
- return httpClient.HttpDeleteWithHead(url, head, apiParam)
- }
- if method == "POST" {
- bytes, _ := json.Marshal(apiParam)
- return httpClient.HttpPostWithHead(url, head, nil, bytes)
- }
- if method == "PUT" {
- bytes, _ := json.Marshal(apiParam)
- return httpClient.HttpPutWithHead(url, head, nil, bytes)
- }
- return nil, nil
- }
- // parseBatchAndCallMultiMode 跑批并发调接口
- func parseBatchAndCallMultiMode(reqstring string, req *apis.ManagementBatchTryApiReq, reply *apis.ManagementBatchTryApiReply) (stop bool) {
- reqstruct := []apis.ManagementBaseApiParam{}
- json.Unmarshal([]byte(reqstring), &reqstruct)
- var wg sync.WaitGroup
- wg.Add(len(req.Params))
- ret := make([]apis.BatchTryApiParams, len(req.Params))
- var mu sync.Mutex
- for i, pa := range req.Params {
- // index 为参数顺序,并发执行后响应结果需和请求参数顺序一致
- go func(index int, v string) {
- // 准备参数
- data := map[string]interface{}{}
- m := map[string]string{}
- json.Unmarshal([]byte(v), &m)
- for _, p := range reqstruct {
- if value, ok := m[p.Name]; ok {
- data[p.Name] = convertType(p.Type, value)
- }
- }
- resp, err := batchCallApi(req, data)
- item := apis.BatchTryApiParams{}
- item.Requset = v
- if err != nil {
- item.OriginResponse = err.Error()
- } else {
- ret := ApiResponse{}
- err := json.Unmarshal(resp, &ret)
- if err != nil {
- item.OriginResponse = string(resp)
- } else {
- // 通用错误表示后续数据不续再传递
- if ret.Code == 10019 ||
- ret.Code == 10016 ||
- ret.Code == 10017 ||
- (ret.Code >= 10004 && ret.Code <= 10013) {
- mu.Lock()
- stop = true
- mu.Unlock()
- }
- appSecret := req.AppSecret
- text := ""
- if req.IsCrypto {
- text = decrypt(ret.Data.(string), appSecret)
- } else {
- tmp, _ := json.Marshal(ret.Data)
- text = string(tmp)
- }
- ret.Data = text
- bytes, _ := json.Marshal(ret)
- item.Response = string(bytes)
- }
- }
- reply.Params = append(reply.Params, item)
- ret[index] = item
- wg.Done()
- }(i, pa)
- }
- wg.Wait()
- reply.Params = ret[:]
- return
- }
- // parseBatchAndCall 跑批顺序调接口
- func parseBatchAndCall(reqstring string, req *apis.ManagementBatchTryApiReq, reply *apis.ManagementBatchTryApiReply) (stop bool) {
- reqstruct := []apis.ManagementBaseApiParam{}
- json.Unmarshal([]byte(reqstring), &reqstruct)
- for _, v := range req.Params {
- // 准备参数
- data := map[string]interface{}{}
- m := map[string]string{}
- json.Unmarshal([]byte(v), &m)
- for _, p := range reqstruct {
- if value, ok := m[p.Name]; ok {
- data[p.Name] = convertType(p.Type, value)
- }
- }
- // 调用接口
- resp, err := batchCallApi(req, data)
- item := apis.BatchTryApiParams{}
- item.Requset = v
- // 响应结果处理
- if err != nil {
- item.OriginResponse = err.Error()
- } else {
- ret := ApiResponse{}
- err := json.Unmarshal(resp, &ret)
- if err != nil {
- item.OriginResponse = string(resp)
- } else {
- // 通用错误表示后续数据不续再传递
- if ret.Code == 10019 ||
- ret.Code == 10016 ||
- ret.Code == 10017 ||
- (ret.Code >= 10004 && ret.Code <= 10013) {
- stop = true
- }
- // 响应参数解密
- appSecret := req.AppSecret
- text := ""
- if req.IsCrypto {
- text = decrypt(ret.Data.(string), appSecret)
- } else {
- tmp, _ := json.Marshal(ret.Data)
- text = string(tmp)
- }
- ret.Data = text
- bytes, _ := json.Marshal(ret)
- item.Response = string(bytes)
- }
- //item.Response = string(resp)
- }
- reply.Params = append(reply.Params, item)
- }
- return stop
- }
- // ManagementBatchTryApi 数据跑批接口
- func ManagementBatchTryApi(ctx context.Context, req *apis.ManagementBatchTryApiReq, reply *apis.ManagementBatchTryApiReply) (err error) {
- o := orm.NewOrm()
- req.Router = strings.TrimPrefix(req.Router, "/")
- req.Method = strings.ToUpper(req.Method)
- sql := "select request_param from t_gd_api where router =? and method=?"
- reqstring := ""
- err = o.Raw(sql, "/"+req.Router, req.Method).QueryRow(&reqstring)
- if err != nil {
- return errors.DataBaseError
- }
- if req.MultiMode {
- reply.Stop = parseBatchAndCallMultiMode(reqstring, req, reply)
- } else {
- reply.Stop = parseBatchAndCall(reqstring, req, reply)
- }
- return nil
- }
|