package api3th import ( "bytes" "encoding/json" "errors" "fmt" "github.com/cihub/seelog" "github.com/google/go-querystring/query" "io" "mongo.games.com/game/common" "net/http" "strings" "sync" "sync/atomic" "time" ) const ( // 智能机器人接口 APITypeAI = 0 // 智能化运营接口 APITypeSmart = 1 ) type BaseConfig struct { sync.Once methods map[string]string urlNames map[string]string seqNo uint64 // 日志序号 IPAddr string AuthKey string // 接口认证秘钥 TimeoutDuration time.Duration // 请求超时时长 Name string // 游戏名称 ApiType int // 接口类型 } func (c *BaseConfig) LogName() string { return fmt.Sprint(c.Name, "Logger") } func (c *BaseConfig) Log() seelog.LoggerInterface { return common.GetLoggerInstanceByName(c.LogName()) } func (c *BaseConfig) OrderNum() uint64 { return atomic.AddUint64(&c.seqNo, 1) } func (c *BaseConfig) Register(method, name, urlName string) { if method == "" { method = "POST" } if _, ok := c.urlNames[name]; ok { panic(fmt.Sprintf("api3th registered name:%s urlName:%s", name, urlName)) } c.urlNames[name] = urlName c.methods[name] = method } func (c *BaseConfig) Do(name string, req interface{}, args ...time.Duration) (resp []byte, err error) { // 加载配置 c.Once.Do(func() { c.AuthKey = common.CustomConfig.GetString(fmt.Sprintf("%sApiKey", c.Name)) c.TimeoutDuration = time.Duration(common.CustomConfig.GetInt(fmt.Sprintf("%sApi3thTimeout", c.Name))) * time.Second }) timeout := time.Duration(-1) if len(args) > 0 { timeout = args[0] } url, ok := c.urlNames[name] if !ok { return nil, errors.New(fmt.Sprintf("api3th no register %s", name)) } var code int method := strings.ToUpper(c.methods[name]) switch method { case "POST": code, resp, err = c.Post(url, req, timeout) case "POSTFORM": code, resp, err = c.PostForm(url, req) case "POSTFORMTIMEOUT": code, resp, err = c.PostFormTimeOut(url, req, timeout) default: err = errors.New(fmt.Sprintf("api3th method error %s", c.methods[name])) } if code != http.StatusOK { err = errors.New(fmt.Sprint("error code ", code)) } return } func (c *BaseConfig) Post(url string, req interface{}, timeout time.Duration) (int, []byte, error) { logger := c.Log() data, err := json.Marshal(req) if err != nil { logger.Error("json.Marshal() error ", err) return 0, nil, err } seqNo := c.OrderNum() logger.Tracef("%s PostRequest[%d] Url %s Param: %s", c.Name, seqNo, fmt.Sprint(c.IPAddr, url), string(data)) r, err := http.NewRequest("POST", fmt.Sprint(c.IPAddr, url), bytes.NewBuffer(data)) if err != nil { logger.Errorf("%s PostRequest[%d] http.NewRequest() error: %v", c.Name, seqNo, err) return 0, nil, err } r.Header.Set("Content-Type", "application/json") if c.AuthKey != "" { r.Header.Set("Ocp-Apim-Subscription-Key", c.AuthKey) } cli := http.Client{} if timeout >= 0 { cli.Timeout = timeout } else { cli.Timeout = c.TimeoutDuration } resp, err := cli.Do(r) if err != nil { logger.Errorf("%s PostRequest[%d] httpClient.Do() error: %v", c.Name, seqNo, err) return 0, nil, err } defer resp.Body.Close() respBytes, err := io.ReadAll(resp.Body) if err != nil { logger.Errorf("%s PostRequest[%d] io.ReadAll() error: %v", c.Name, seqNo, err) return 0, nil, err } logger.Tracef("%s PostRequest[%d] StatusCode=%d Body=%s", c.Name, seqNo, resp.StatusCode, string(respBytes)) return resp.StatusCode, respBytes, nil } func (c *BaseConfig) PostFormTimeOut(url string, req interface{}, timeout time.Duration) (int, []byte, error) { logger := c.Log() data, err := json.Marshal(req) if err != nil { logger.Error("json.Marshal() error ", err) return 0, nil, err } seqNo := c.OrderNum() logger.Tracef("%s PostRequest[%d] Url %s Param: %s", c.Name, seqNo, fmt.Sprint(c.IPAddr, url), string(data)) params, query_err := query.Values(req) if query_err != nil { logger.Errorf("(c *BaseConfig) PostForm query.Values %v", query_err) return 0, nil, query_err } rp := strings.NewReader(params.Encode()) r, err := http.NewRequest("POST", fmt.Sprint(c.IPAddr, url), rp) if err != nil { logger.Errorf("%s PostRequest[%d] http.NewRequest() error: %v", c.Name, seqNo, err) return 0, nil, err } r.Header.Set("Content-Type", "application/x-www-form-urlencoded") if c.AuthKey != "" { r.Header.Set("Ocp-Apim-Subscription-Key", c.AuthKey) } cli := http.Client{} if timeout >= 0 { cli.Timeout = timeout } else { cli.Timeout = c.TimeoutDuration } resp, err := cli.Do(r) if err != nil { //logger.Errorf("%s PostRequest[%d] httpClient.Do() error: %v", c.Name, seqNo, err) return 0, nil, err } defer resp.Body.Close() respBytes, err := io.ReadAll(resp.Body) if err != nil { logger.Errorf("%s PostRequest[%d] io.ReadAll() error: %v", c.Name, seqNo, err) return 0, nil, err } logger.Tracef("%s PostRequest[%d] StatusCode=%d Body=%s", c.Name, seqNo, resp.StatusCode, string(respBytes)) return resp.StatusCode, respBytes, nil } func (c *BaseConfig) PostForm(url1 string, req interface{}) (int, []byte, error) { logger := c.Log() data, err := json.Marshal(req) if err != nil { logger.Error("json.Marshal() error ", err) return 0, nil, err } c.Log().Info(fmt.Sprint(c.IPAddr, url1), string(data)) params, query_err := query.Values(req) if query_err != nil { logger.Errorf("(c *BaseConfig) PostForm query.Values %v", query_err) return 0, nil, query_err } //c.Log().Info(fmt.Sprint(c.IPAddr, url1),params.Encode()) //fmt.Println(vals.Encode()) // //params := req.(url.Values) res, err := http.PostForm(fmt.Sprint(c.IPAddr, url1), params) if err != nil { logger.Errorf("(c *BaseConfig) PostForm http.PostForm %v", err) return 0, nil, err } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { logger.Errorf("(c *BaseConfig) PostForm io.ReadAll %v", err) return 0, nil, err } //println(url, " ret:", string(body[:])) //result := make(map[string]interface{}) //json.Unmarshal(body, &result) return http.StatusOK, body, err } func (c *BaseConfig) Switch() bool { switch c.ApiType { case 1: // 智能化运营 return common.CustomConfig.GetBool(fmt.Sprintf("Use%sSmartApi3th", c.Name)) default: // ai return common.CustomConfig.GetBool(fmt.Sprintf("Use%sRobotApi3th", c.Name)) } } func NewBaseConfig(name string, apiType int) *BaseConfig { ret := new(BaseConfig) ret.methods = make(map[string]string) ret.urlNames = make(map[string]string) ret.Name = name ret.ApiType = apiType return ret }