tencent-im/internal/core/client.go

147 lines
4.2 KiB
Go
Raw Normal View History

2022-09-27 11:31:23 +08:00
/**
* @Author: Echo
* @Email:1711788888@qq.com
* @Date: 2021/8/27 11:31 上午
* @Desc: TODO
*/
package core
import (
"fmt"
"math/rand"
"time"
"git.echol.cn/loser/http"
"git.echol.cn/loser/tencent-im/internal/enum"
"git.echol.cn/loser/tencent-im/internal/sign"
"git.echol.cn/loser/tencent-im/internal/types"
)
const (
defaultBaseUrl = "https://console.tim.qq.com"
defaultVersion = "v4"
defaultContentType = "json"
defaultExpiration = 3600
)
var invalidResponse = NewError(enum.InvalidResponseCode, "invalid response")
type Client interface {
// Get GET请求
Get(serviceName string, command string, data interface{}, resp interface{}) error
// Post POST请求
Post(serviceName string, command string, data interface{}, resp interface{}) error
// Put PUT请求
Put(serviceName string, command string, data interface{}, resp interface{}) error
// Patch PATCH请求
Patch(serviceName string, command string, data interface{}, resp interface{}) error
// Delete DELETE请求
Delete(serviceName string, command string, data interface{}, resp interface{}) error
}
type client struct {
client *http.Client
opt *Options
userSig string
userSigExpireAt int64
}
type Options struct {
AppId int // 应用SDKAppID可在即时通信 IM 控制台 的应用卡片中获取。
AppSecret string // 密钥信息,可在即时通信 IM 控制台 的应用详情页面中获取,具体操作请参见 获取密钥
UserId string // 用户ID
Expiration int // UserSig过期时间
}
func NewClient(opt *Options) Client {
rand.Seed(time.Now().UnixNano())
c := new(client)
c.opt = opt
c.client = http.NewClient()
c.client.SetContentType(http.ContentTypeJson)
c.client.SetBaseUrl(defaultBaseUrl)
return c
}
// Get GET请求
func (c *client) Get(serviceName string, command string, data interface{}, resp interface{}) error {
return c.request(http.MethodGet, serviceName, command, data, resp)
}
// Post POST请求
func (c *client) Post(serviceName string, command string, data interface{}, resp interface{}) error {
return c.request(http.MethodPost, serviceName, command, data, resp)
}
// Put PUT请求
func (c *client) Put(serviceName string, command string, data interface{}, resp interface{}) error {
return c.request(http.MethodPut, serviceName, command, data, resp)
}
// Patch PATCH请求
func (c *client) Patch(serviceName string, command string, data interface{}, resp interface{}) error {
return c.request(http.MethodPatch, serviceName, command, data, resp)
}
// Delete DELETE请求
func (c *client) Delete(serviceName string, command string, data interface{}, resp interface{}) error {
return c.request(http.MethodDelete, serviceName, command, data, resp)
}
// request Request请求
func (c *client) request(method, serviceName, command string, data, resp interface{}) error {
res, err := c.client.Request(method, c.buildUrl(serviceName, command), data)
if err != nil {
return err
}
if err = res.Scan(resp); err != nil {
return err
}
if r, ok := resp.(types.ActionBaseRespInterface); ok {
if r.GetActionStatus() == enum.FailActionStatus {
return NewError(r.GetErrorCode(), r.GetErrorInfo())
}
if r.GetErrorCode() != enum.SuccessCode {
return NewError(r.GetErrorCode(), r.GetErrorInfo())
}
} else if r, ok := resp.(types.BaseRespInterface); ok {
if r.GetErrorCode() != enum.SuccessCode {
return NewError(r.GetErrorCode(), r.GetErrorInfo())
}
} else {
return invalidResponse
}
return nil
}
// buildUrl 构建一个请求URL
func (c *client) buildUrl(serviceName string, command string) string {
format := "/%s/%s/%s?sdkappid=%d&identifier=%s&usersig=%s&random=%d&contenttype=%s"
random := rand.Int31()
userSig := c.getUserSig()
return fmt.Sprintf(format, defaultVersion, serviceName, command, c.opt.AppId, c.opt.UserId, userSig, random, defaultContentType)
}
// getUserSig 获取签名
func (c *client) getUserSig() string {
now, expiration := time.Now(), c.opt.Expiration
if expiration <= 0 {
expiration = defaultExpiration
}
if c.userSig == "" || c.userSigExpireAt <= now.Unix() {
c.userSig, _ = sign.GenUserSig(c.opt.AppId, c.opt.AppSecret, c.opt.UserId, expiration)
c.userSigExpireAt = now.Add(time.Duration(expiration) * time.Second).Unix()
}
return c.userSig
}