package yilianyunapi import ( "crypto/md5" "fmt" "net/http" "strings" "sync" "time" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/platformapi" "git.rosy.net.cn/baseapi/utils" ) const ( prodURL = "https://open-api.10ss.net" signKey = "sign" timestampKey = "timestamp" oathApiPath = "oauth/oauth" ) const ( // ResponseCodeSuccess 操作成功 ResponseCodeSuccess = "0" ) const ( PrintStatusOffline = 0 PrintStatusOnline = 1 PrintStatusLackPaper = 2 ) var ( exceedLimitCodes = map[string]int{} canRetryCodes = map[string]int{} ) type API struct { locker sync.RWMutex accessToken string clientID string clientSecret string client *http.Client config *platformapi.APIConfig } type TokenInfo struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` ExpiresIn int64 `json:"expires_in"` Scope string `json:"scope"` } func New(clientID, clientSecret string, config ...*platformapi.APIConfig) *API { curConfig := platformapi.DefAPIConfig if len(config) > 0 { curConfig = *config[0] } return &API{ clientID: clientID, clientSecret: clientSecret, client: &http.Client{Timeout: curConfig.ClientTimeout}, config: &curConfig, } } func (a *API) signParams(timestamp int64) string { return fmt.Sprintf("%x", md5.Sum([]byte(a.clientID+utils.Int64ToStr(timestamp)+a.clientSecret))) } func (a *API) AccessAPI(apiName string, apiParams map[string]interface{}) (retVal map[string]interface{}, err error) { err = platformapi.AccessPlatformAPIWithRetry(a.client, func() *http.Request { timestamp := time.Now().Unix() params := utils.MergeMaps(map[string]interface{}{ timestampKey: timestamp, signKey: a.signParams(timestamp), "client_id": a.clientID, "id": utils.GetUpperUUID(), }, apiParams) if oathApiPath != apiName { params["access_token"] = a.GetToken() } request, _ := http.NewRequest(http.MethodPost, utils.GenerateGetURL(prodURL, apiName, nil), strings.NewReader(utils.Map2URLValues(params).Encode())) request.Header.Set("charset", "UTF-8") request.Header.Set("Content-Type", "application/x-www-form-urlencoded") // request.Close = true //todo 为了性能考虑还是不要关闭 return request }, a.config, func(jsonResult1 map[string]interface{}) (errLevel string, err error) { code := utils.Interface2String(jsonResult1["error"]) if code == ResponseCodeSuccess { retVal, _ = jsonResult1["body"].(map[string]interface{}) return platformapi.ErrLevelSuccess, nil } newErr := utils.NewErrorCode(jsonResult1["error_description"].(string), code) if _, ok := exceedLimitCodes[code]; ok { return platformapi.ErrLevelExceedLimit, newErr } else if _, ok := canRetryCodes[code]; ok { return platformapi.ErrLevelRecoverableErr, newErr } else { baseapi.SugarLogger.Debugf("yilianyun AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true)) return platformapi.ErrLevelCodeIsNotOK, newErr } }) return retVal, err } func (a *API) SetToken(newToken string) bool { curToken := a.GetToken() if curToken != newToken { a.locker.Lock() defer a.locker.Unlock() a.accessToken = newToken return true } return false } func (a *API) GetToken() string { a.locker.RLock() defer a.locker.RUnlock() return a.accessToken } func (a *API) RetrieveToken() (tokenInfo *TokenInfo, err error) { result, err := a.AccessAPI(oathApiPath, map[string]interface{}{ "grant_type": "client_credentials", "scope": "all", }) if err != nil { return nil, err } tokenInfo = &TokenInfo{} if err = utils.Map2StructByJson(result, tokenInfo, false); err == nil { a.SetToken(tokenInfo.AccessToken) } return tokenInfo, err } func (a *API) AddPrinter(machineCode, msign, printerName string) (err error) { _, err = a.AccessAPI("printer/addprinter", map[string]interface{}{ "machine_code": machineCode, "msign": msign, "print_name": printerName, }) return err } func (a *API) DeletePrinter(machineCode string) (err error) { _, err = a.AccessAPI("printer/deleteprinter", map[string]interface{}{ "machine_code": machineCode, }) return err } func (a *API) PrintMsg(machineCode, orderID, content string) (err error) { if orderID == "" { orderID = utils.GetUUID() } _, err = a.AccessAPI("print/index", map[string]interface{}{ "machine_code": machineCode, "origin_id": orderID, "content": content, }) return err } func (a *API) GetPrintStatus(machineCode string) (state int, err error) { result, err := a.AccessAPI("printer/getprintstatus", map[string]interface{}{ "machine_code": machineCode, }) if err != nil { return 0, err } return int(utils.Str2Int64(utils.Interface2String(result["state"]))), nil }