- basic mtps api added.

This commit is contained in:
gazebo
2018-06-14 14:45:19 +08:00
parent 9696e142ee
commit 4f1a2bc950
7 changed files with 355 additions and 137 deletions

View File

@@ -2,36 +2,29 @@ package elmapi
import (
"crypto/md5"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"sort"
"strings"
"time"
"git.rosy.net.cn/baseapi/platform/common"
"git.rosy.net.cn/baseapi/utils"
"go.uber.org/zap"
)
const (
ELM_API_URL_SANDBOX = "https://open-api-sandbox.shop.ele.me/api/v1/"
ELM_API_URL_PROD = "https://open-api.shop.ele.me/api/v1/"
)
const (
clientTimeout = time.Second * 10
sleepSecondWhenLimited = 6 * time.Second
maxRetryCountWhenNetworkException = 3
maxRetryCountWhenReachLimited = 10
)
var (
ErrSystemErrMaxRetry = errors.New("ELM System error reach max retry count!")
ErrLimitReachMaxRetry = errors.New("ELM Reach max retry count!")
ErrHttpCode = errors.New("ELM HTTP Code is not 200")
ErrELMCode = errors.New("ELM code is not 0")
const (
ELM_API_URL_SANDBOX = "https://open-api-sandbox.shop.ele.me/api/v1/"
ELM_API_URL_PROD = "https://open-api.shop.ele.me/api/v1/"
)
type ELMResult struct {
@@ -46,7 +39,7 @@ type ELMAPI struct {
secret string
sugarLogger *zap.SugaredLogger
url *url.URL
client http.Client
client *http.Client
}
type ELMPayload struct {
@@ -65,7 +58,7 @@ func NewELMAPI(token, appKey, secret string, sugarLogger *zap.SugaredLogger, isP
appKey: appKey,
secret: secret,
sugarLogger: sugarLogger,
client: http.Client{Timeout: time.Second * 10},
client: &http.Client{Timeout: clientTimeout},
}
if isProd {
@@ -95,7 +88,7 @@ func (e *ELMAPI) signParams(action string, payload *ELMPayload) string {
return fmt.Sprintf("%X", md5.Sum([]byte(finalStr)))
}
func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (*ELMResult, error) {
func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (retVal *ELMResult, err error) {
if params == nil {
params = make(map[string]interface{}, 0)
}
@@ -114,14 +107,13 @@ func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (*ELMRe
}
payload.Signature = e.signParams(action, payload)
dataBytes := utils.MustMarshal(payload)
dataStr := string(dataBytes)
exceedLimitRetryCount := 0
systemErrorRetryCount := 0
for {
request := &http.Request{
apiAccess := &common.AccessPlatformAPIWithRetryParams{
MaxExceedLimitRetryCount: maxRetryCountWhenReachLimited,
MaxRecoverableRetryCount: maxRetryCountWhenNetworkException,
SleepSecondWhenExceedLimit: sleepSecondWhenLimited,
Client: e.client,
Request: &http.Request{
Method: "POST",
URL: e.url,
Header: http.Header{
@@ -131,64 +123,37 @@ func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (*ELMRe
// "x-eleme-requestid": []string{payload.Id},
},
Body: ioutil.NopCloser(strings.NewReader(dataStr)),
}
response, err := e.client.Do(request)
if err != nil {
e.sugarLogger.Debugf("client.Get return err:%v", err)
err, ok := err.(net.Error)
systemErrorRetryCount++
if ok && err.Timeout() && systemErrorRetryCount <= maxRetryCountWhenNetworkException {
continue
} else {
return nil, err
}
}
defer response.Body.Close()
if response.StatusCode != 200 {
e.sugarLogger.Debugf("http code is:%d", response.StatusCode)
systemErrorRetryCount++
if systemErrorRetryCount <= maxRetryCountWhenNetworkException {
continue
}
return nil, ErrHttpCode
}
Body: ioutil.NopCloser(strings.NewReader(string(utils.MustMarshal(payload)))),
},
SugarLogger: e.sugarLogger,
}
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result int, err error) {
jsonResult1, err := utils.HttpResponse2Json(response)
if err != nil {
e.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
return 0, err
}
resultError, _ := jsonResult1["error"].(map[string]interface{})
jsonResult := &ELMResult{
retVal = &ELMResult{
Id: jsonResult1["id"].(string),
Error: resultError,
Result: jsonResult1["result"],
}
if err != nil {
e.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
return nil, err
}
errinfoMap := jsonResult.Error
errinfoMap := retVal.Error
if errinfoMap == nil {
return jsonResult, nil
return common.PAErrorLevelSuccess, nil
}
errCode := errinfoMap["code"].(string)
if errCode == "EXCEED_LIMIT" {
exceedLimitRetryCount++
if exceedLimitRetryCount <= maxRetryCountWhenReachLimited {
time.Sleep(sleepSecondWhenLimited)
} else {
return jsonResult, ErrLimitReachMaxRetry
}
return common.PAErrorLevelExceedLimit, nil
} else if errCode == "SERVER_ERROR" || errCode == "BIZ_SYSTEM_ERROR" || errCode == "BIZ_1006" || errCode == "BUSINESS_ERROR" {
if systemErrorRetryCount <= maxRetryCountWhenNetworkException {
continue
}
return jsonResult, ErrSystemErrMaxRetry
return common.PAErrorLevelRecoverable, nil
} else {
e.sugarLogger.Debug(jsonResult)
return jsonResult, ErrELMCode
return common.PAErrorLevelFailed, nil
}
}
})
return retVal, err
}

View File

@@ -1,7 +1,6 @@
package elmapi
import (
"encoding/json"
"testing"
"git.rosy.net.cn/baseapi/utils"
@@ -29,10 +28,9 @@ func TestAccessELM(t *testing.T) {
t.Fatalf("Error when accessing AccessJDQuery result:%v, error:%v", result, err)
} else {
mapResult := result.Result.(map[string]interface{})
userIdNumber := mapResult["userId"].(json.Number)
userId, err := userIdNumber.Int64()
userId := utils.MustInterface2Int64(mapResult["userId"])
if userId != 336072266326420104 || err != nil {
t.Fatalf("userId is not correct:%v", userIdNumber)
t.Fatalf("userId is not correct:%v", mapResult["userId"])
}
}
}

View File

@@ -1,14 +1,12 @@
package elmapi
type ELMOrderInfo map[string]interface{}
func (e *ELMAPI) GetOrder(orderId string) (ELMOrderInfo, error) {
func (e *ELMAPI) GetOrder(orderId string) (map[string]interface{}, error) {
result, err := e.AccessELM("eleme.order.getOrder", map[string]interface{}{
"orderId": orderId,
})
if err == nil {
innerResult := ELMOrderInfo(result.Result.(map[string]interface{}))
innerResult := map[string]interface{}(result.Result.(map[string]interface{}))
return innerResult, nil
}
return nil, err