package uinapp import ( "crypto/sha256" "encoding/hex" "encoding/json" "errors" "fmt" "git.rosy.net.cn/baseapi/platformapi" "git.rosy.net.cn/baseapi/utils" "net/http" "strings" "sync" "time" ) type API struct { appId string `json:"app_id"` appKey string `json:"app_key"` appSecret string `json:"app_secret"` masterSecret string `json:"master_secret"` token string `json:"token"` expireTime string `json:"expire_time"` locker sync.RWMutex client *http.Client config *platformapi.APIConfig } func NewUinappApi(appId, appKey, appSecret, masterSecret string, config ...*platformapi.APIConfig) *API { curConfig := platformapi.DefAPIConfig if len(config) > 0 { curConfig = *config[0] } if appId == "" || masterSecret == "" { return nil } return &API{ appId: appId, appKey: appKey, appSecret: appSecret, masterSecret: masterSecret, token: "", expireTime: "", locker: sync.RWMutex{}, client: &http.Client{Timeout: curConfig.ClientTimeout}, config: &curConfig, } } func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) { // 序列化 data, err := json.Marshal(bizParams) if err != nil { return nil, err } // 全路径请求参数 fullURL := utils.GenerateGetURL(baseUrl, actionApi, nil) // 发送请求 sendUrl := func() *http.Request { var request *http.Request if http.MethodPost == method { request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data))) } else { request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil) } if actionApi != GetTokenInterface { request.Header.Set("token", a.token) } request.Header.Set("Content-Type", "application/json;charset=utf-8") return request } // 数据解析 dataMarshal := func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { if jsonResult1 == nil { return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") } if err != nil { return "", err } if utils.MustInterface2Int64(jsonResult1["code"]) != 200 { errLevel = platformapi.ErrLevelGeneralFail err = utils.NewErrorCode(jsonResult1["msg"].(string), utils.Int64ToStr(utils.MustInterface2Int64(jsonResult1["code"]))) } retVal = jsonResult1 return errLevel, err } err = platformapi.AccessPlatformAPIWithRetry(a.client, sendUrl, a.config, dataMarshal) return retVal, err } func (a *API) signParam(timestamp string) (sig string) { sig = a.appKey + timestamp + a.masterSecret signature := sha256.Sum256([]byte(sig)) return hex.EncodeToString(signature[:]) } // GetUinAppToken 获取token func (a *API) GetUinAppToken() error { timestamp := utils.Int64ToStr(time.Now().UnixNano() / 1e6) sign := a.signParam(timestamp) result, err := a.AccessAPI(BaseUrl+a.appId, GetTokenInterface, http.MethodPost, map[string]interface{}{"timestamp": timestamp, "sign": sign, "appkey": a.appKey}) fmt.Println(err.Error()) if err != nil && !strings.Contains(err.Error(), "success") { return err } var appToken *AppTokenRes if err := utils.Map2StructByJson(result, &appToken, false); err != nil { return err } if appToken.Code != 0 && appToken.Msg != "success" { return errors.New(appToken.Msg) } a.token = appToken.Data.Token a.expireTime = appToken.Data.ExpireTime return nil } // CheckTokenIsExpire 校验头肯是否过期 // 注:鉴权接口每分钟最大调用量为100次,每天最大调用量为10万次,建议开发者妥善管理token,以免达到限制,影响推送.感觉不做缓存也够用了! func (a *API) CheckTokenIsExpire() error { // 没有token或者token过期了 if a.token == "" || a.expireTime == "" || utils.Str2Int64(a.expireTime) < (time.Now().UnixNano()/1e6) { return a.GetUinAppToken() } return nil }