Files
baseapi/platformapi/elmapi/elmapi.go
2018-06-22 22:26:12 +08:00

156 lines
4.0 KiB
Go

package elmapi
import (
"crypto/md5"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strings"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
)
const (
sandboxURL = "https://open-api-sandbox.shop.ele.me/api/v1/"
prodURL = "https://open-api.shop.ele.me/api/v1/"
signKey = "signature"
)
type ResponseResult struct {
ID string
Result interface{}
Error map[string]interface{}
}
type API struct {
token string
appKey string
secret string
url *url.URL
client *http.Client
config *platformapi.APIConfig
}
type payload struct {
Token string `json:"token"`
Nop string `json:"nop"`
Metas map[string]interface{} `json:"metas"`
Params map[string]interface{} `json:"params"`
Action string `json:"action"`
ID string `json:"id"`
Signature string `json:"signature"`
}
func New(token, appKey, secret string, isProd bool, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
api := &API{
token: token,
appKey: appKey,
secret: secret,
client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig,
}
if isProd {
api.url, _ = url.Parse(prodURL)
} else {
api.url, _ = url.Parse(sandboxURL)
}
return api
}
func (a *API) signParamsMap(mapData map[string]interface{}, prefix string) string {
keyValues := make([]string, 0)
for k, v := range mapData {
if k != signKey {
vStr := ""
if prefix == "" { // callback sign
vStr = fmt.Sprint(v)
} else { // call sign
vBytes := utils.MustMarshal(v)
vStr = string(vBytes)
}
keyValues = append(keyValues, k+"="+vStr)
}
}
sort.Strings(keyValues)
finalStr := prefix + strings.Join(keyValues, "") + a.secret
// baseapi.SugarLogger.Debugf("sign str:%v", finalStr)
return fmt.Sprintf("%X", md5.Sum([]byte(finalStr)))
}
func (a *API) signParams(action string, pl *payload) string {
mapData := utils.MergeMaps(pl.Metas, pl.Params)
return a.signParamsMap(mapData, action+a.token)
}
func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal *ResponseResult, err error) {
if params == nil {
params = make(map[string]interface{}, 0)
}
metas := map[string]interface{}{
"app_key": a.appKey,
"timestamp": utils.GetCurTimestamp(),
}
pl := &payload{
Token: a.token,
Nop: "1.0.0",
Metas: metas,
Params: params,
Action: action,
ID: utils.GetUUID(),
}
pl.Signature = a.signParams(action, pl)
request := &http.Request{
Method: "POST",
URL: a.url,
Header: http.Header{
"Content-Type": []string{"application/json; charset=utf-8"},
"Content-Encoding": []string{"gzip, deflate"},
"User-Agent": []string{"eleme-golang-api"},
// "x-eleme-requestid": []string{payload.Id},
},
Body: ioutil.NopCloser(strings.NewReader(string(utils.MustMarshal(pl)))),
}
err = platformapi.AccessPlatformAPIWithRetry(a.client, request, a.config, func(response *http.Response) (result string, err error) {
jsonResult1, err := utils.HTTPResponse2Json(response)
if err != nil {
return platformapi.ErrLevelGeneralFail, err
}
resultError, _ := jsonResult1["error"].(map[string]interface{})
retVal = &ResponseResult{
ID: jsonResult1["id"].(string),
Error: resultError,
Result: jsonResult1["result"],
}
errinfoMap := retVal.Error
if errinfoMap == nil {
return platformapi.ErrLevelSuccess, nil
}
code := errinfoMap["code"].(string)
baseapi.SugarLogger.Warnf("response business code is not ok, data:%v, code:%v", jsonResult1, code)
newErr := utils.NewErrorCode(errinfoMap["message"].(string), code)
if code == "EXCEED_LIMIT" {
return platformapi.ErrLevelExceedLimit, newErr
} else if code == "SERVER_ERROR" || code == "BIZ_SYSTEM_ERROR" || code == "BIZ_1006" || code == "BUSINESS_ERROR" {
return platformapi.ErrLevelRecoverableErr, newErr
} else {
return platformapi.ErrLevelCodeIsNotOK, newErr
}
})
return retVal, err
}