- weimob api
This commit is contained in:
20
platformapi/weimobapi/goods.go
Normal file
20
platformapi/weimobapi/goods.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package weimobapi
|
||||
|
||||
import (
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func (a *API) QueryGoodsList(pageNum, pageSize int) (retVal []map[string]interface{}, totalCount int, err error) {
|
||||
result, err := a.AccessAPI("goods/queryGoodsList", map[string]interface{}{
|
||||
"pageNum": pageNum,
|
||||
"pageSize": pageSize,
|
||||
})
|
||||
if err == nil {
|
||||
if pageList, ok := result["pageList"].([]interface{}); ok {
|
||||
retVal = utils.Slice2MapSlice(pageList)
|
||||
}
|
||||
totalCount = int(utils.MustInterface2Int64(result["totalCount"]))
|
||||
return retVal, totalCount, nil
|
||||
}
|
||||
return nil, 0, err
|
||||
}
|
||||
17
platformapi/weimobapi/goods_test.go
Normal file
17
platformapi/weimobapi/goods_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package weimobapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestQueryGoodsList(t *testing.T) {
|
||||
result, totalCount, err := api.QueryGoodsList(1, 20)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
baseapi.SugarLogger.Debug(totalCount)
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
}
|
||||
209
platformapi/weimobapi/weimobapi.go
Normal file
209
platformapi/weimobapi/weimobapi.go
Normal file
@@ -0,0 +1,209 @@
|
||||
package weimobapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
ResponseCodeSuccess = "0"
|
||||
ResponseCodeExceedCallFrequency = "8000103"
|
||||
)
|
||||
|
||||
const (
|
||||
prodURL = "https://dopen.weimob.com/api/1_0/ec"
|
||||
authURL = "https://dopen.weimob.com/fuwu/b"
|
||||
accessTokenAPI = "oauth2/token"
|
||||
)
|
||||
|
||||
type TokenInfo struct {
|
||||
TokenType string `json:"token_type"`
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
RefreshTokenExpiresIn int `json:"refresh_token_expires_in"`
|
||||
Scope string `json:"scope"`
|
||||
PublicAccountID string `json:"public_account_id"`
|
||||
BusinessID string `json:"business_id"`
|
||||
}
|
||||
|
||||
type API struct {
|
||||
token *TokenInfo
|
||||
appID string
|
||||
appSecret string
|
||||
client *http.Client
|
||||
config *platformapi.APIConfig
|
||||
|
||||
locker sync.RWMutex
|
||||
}
|
||||
|
||||
var (
|
||||
exceedLimitCodes = map[string]int{
|
||||
ResponseCodeExceedCallFrequency: 1,
|
||||
}
|
||||
|
||||
canRetryCodes = map[string]int{}
|
||||
)
|
||||
|
||||
func New(token *TokenInfo, appID, appSecret string, config ...*platformapi.APIConfig) *API {
|
||||
curConfig := platformapi.DefAPIConfig
|
||||
if len(config) > 0 {
|
||||
curConfig = *config[0]
|
||||
}
|
||||
return &API{
|
||||
token: token,
|
||||
appID: appID,
|
||||
appSecret: appSecret,
|
||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||
config: &curConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *API) SetToken(newToken *TokenInfo) (retVal bool) {
|
||||
a.locker.Lock()
|
||||
defer a.locker.Unlock()
|
||||
a.token = newToken
|
||||
retVal = true
|
||||
return retVal
|
||||
}
|
||||
|
||||
func (a *API) GetToken() *TokenInfo {
|
||||
a.locker.RLock()
|
||||
defer a.locker.RUnlock()
|
||||
return a.token
|
||||
}
|
||||
|
||||
func (a *API) MustGetToken() *TokenInfo {
|
||||
token := a.GetToken()
|
||||
if token == nil {
|
||||
panic("token is nil")
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
func (a *API) AccessAPI(apiStr string, apiParams map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
var request *http.Request
|
||||
if apiStr == accessTokenAPI {
|
||||
fullURL := utils.GenerateGetURL(authURL, apiStr, utils.MergeMaps(apiParams, map[string]interface{}{
|
||||
"client_id": a.appID,
|
||||
"client_secret": a.appSecret,
|
||||
}))
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, nil)
|
||||
} else {
|
||||
fullURL := utils.GenerateGetURL(prodURL, apiStr, utils.Params2Map("accesstoken", a.MustGetToken().AccessToken))
|
||||
var body io.Reader
|
||||
if apiParams != nil {
|
||||
apiParamsBytes, err := json.Marshal(apiParams)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Error when marshal %v, error:%v", apiParams, err))
|
||||
}
|
||||
body = bytes.NewReader(apiParamsBytes)
|
||||
}
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, body)
|
||||
request.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||
request.Header.Set("Content-Encoding", "gzip, deflate")
|
||||
request.Header.Set("User-Agent", "weimob-golang-api")
|
||||
// request.Close = true //todo 为了性能考虑还是不要关闭
|
||||
}
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(jsonResult1, false))
|
||||
code := ResponseCodeSuccess
|
||||
errMsg := ""
|
||||
if apiStr == accessTokenAPI {
|
||||
// token相关出错到不了这里,因为当取token发生错误时,HTTP CODE不是200
|
||||
if errCode, ok := jsonResult1["error"]; ok {
|
||||
code = getStringCode(errCode)
|
||||
errMsg = jsonResult1["error_description"].(string)
|
||||
}
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
}
|
||||
} else {
|
||||
if errMap, ok := jsonResult1["code"].(map[string]interface{}); ok {
|
||||
code = getStringCode(errMap["errcode"])
|
||||
errMsg = errMap["errmsg"].(string)
|
||||
}
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1["data"].(map[string]interface{})
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
}
|
||||
}
|
||||
newErr := utils.NewErrorCode(errMsg, code)
|
||||
if _, ok := exceedLimitCodes[code]; ok {
|
||||
return platformapi.ErrLevelExceedLimit, newErr
|
||||
} else if _, ok := canRetryCodes[code]; ok {
|
||||
return platformapi.ErrLevelRecoverableErr, newErr
|
||||
} else {
|
||||
baseapi.SugarLogger.Debugf("weimob AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||
}
|
||||
})
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func getStringCode(code interface{}) string {
|
||||
if codeStr, ok := code.(string); ok {
|
||||
return codeStr
|
||||
}
|
||||
return utils.Int64ToStr(utils.Interface2Int64WithDefault(code, 0))
|
||||
}
|
||||
|
||||
// redirectURL只是作为校验,要求转入得到此CODE时给的redirectURL,不包括参数部分
|
||||
func (a *API) RefreshTokenByCode(code, redirectURL string) (retVal *TokenInfo, err error) {
|
||||
result, err := a.AccessAPI(accessTokenAPI, map[string]interface{}{
|
||||
"grant_type": "authorization_code",
|
||||
"code": code,
|
||||
"redirect_uri": redirectURL,
|
||||
})
|
||||
if err == nil {
|
||||
retVal = map2TokenInfo(result)
|
||||
a.SetToken(retVal)
|
||||
return retVal, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) RefreshTokenByRefreshToken() (retVal *TokenInfo, err error) {
|
||||
curToken := a.GetToken()
|
||||
if curToken != nil {
|
||||
result, err := a.AccessAPI(accessTokenAPI, map[string]interface{}{
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": curToken.RefreshToken,
|
||||
})
|
||||
if err == nil {
|
||||
retVal = map2TokenInfo(result)
|
||||
a.SetToken(retVal)
|
||||
return retVal, nil
|
||||
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("刷新TOKEN要求已经有TOKEN")
|
||||
}
|
||||
|
||||
func map2TokenInfo(mapData map[string]interface{}) *TokenInfo {
|
||||
return &TokenInfo{
|
||||
TokenType: utils.Interface2String(mapData["token_type"]),
|
||||
AccessToken: utils.Interface2String(mapData["access_token"]),
|
||||
ExpiresIn: int(utils.MustInterface2Int64(mapData["expires_in"])),
|
||||
RefreshToken: utils.Interface2String(mapData["refresh_token"]),
|
||||
RefreshTokenExpiresIn: int(utils.MustInterface2Int64(mapData["refresh_token_expires_in"])),
|
||||
Scope: utils.Interface2String(mapData["scope"]),
|
||||
PublicAccountID: utils.Interface2String(mapData["public_account_id"]),
|
||||
BusinessID: utils.Interface2String(mapData["business_id"]),
|
||||
}
|
||||
}
|
||||
54
platformapi/weimobapi/weimobapi_test.go
Normal file
54
platformapi/weimobapi/weimobapi_test.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package weimobapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
api *API
|
||||
sugarLogger *zap.SugaredLogger
|
||||
)
|
||||
|
||||
func init() {
|
||||
logger, _ := zap.NewDevelopment()
|
||||
sugarLogger = logger.Sugar()
|
||||
baseapi.Init(sugarLogger)
|
||||
|
||||
tokenStr := `
|
||||
{
|
||||
"token_type": "bearer",
|
||||
"access_token": "db2f4a02-2097-4636-8c8a-cc5576f402cf",
|
||||
"expires_in": 7199,
|
||||
"refresh_token": "7b961b6b-0dc4-43e1-8c38-a9a10e2e130d",
|
||||
"refresh_token_expires_in": 604799,
|
||||
"scope": "default",
|
||||
"public_account_id": "100000386048",
|
||||
"business_id": "1224609670"
|
||||
}`
|
||||
var token *TokenInfo
|
||||
if err := utils.UnmarshalUseNumber([]byte(tokenStr), &token); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// prod
|
||||
api = New(token, "319F5E7FB6784DFCA3684C9333EB7744", "7267AA7F58261F6965599218F5A1D592")
|
||||
}
|
||||
|
||||
func TestRefreshTokenByCode(t *testing.T) {
|
||||
result, err := api.RefreshTokenByCode("6Stxtw", "http://callback.test.jxc4.com/weimob/coded")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRefreshTokenByRefreshToken(t *testing.T) {
|
||||
result, err := api.RefreshTokenByRefreshToken()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
}
|
||||
Reference in New Issue
Block a user