- basic mtps api added.
This commit is contained in:
83
platform/common/common.go
Normal file
83
platform/common/common.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AccessPlatformAPIWithRetryParams struct {
|
||||||
|
MaxExceedLimitRetryCount int
|
||||||
|
MaxRecoverableRetryCount int
|
||||||
|
SleepSecondWhenExceedLimit time.Duration
|
||||||
|
Client *http.Client
|
||||||
|
Request *http.Request
|
||||||
|
SugarLogger *zap.SugaredLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PAErrorLevelSuccess = 0
|
||||||
|
PAErrorLevelExceedLimit = 1
|
||||||
|
PAErrorLevelRecoverable = 2
|
||||||
|
PAErrorLevelFailed = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrRecoverableErrMaxRetry = errors.New("recoverable error reach max retry count!")
|
||||||
|
ErrLimitReachMaxRetry = errors.New("Reach max retry count!")
|
||||||
|
ErrHttpCode = errors.New("HTTP Code is not 200")
|
||||||
|
ErrBusinessCode = errors.New("Business code is not ok")
|
||||||
|
)
|
||||||
|
|
||||||
|
func AccessPlatformAPIWithRetry(params *AccessPlatformAPIWithRetryParams, handleResponse func(response *http.Response) (int, error)) error {
|
||||||
|
exceedLimitRetryCount := 0
|
||||||
|
recoverableErrorRetryCount := 0
|
||||||
|
for {
|
||||||
|
response, err := params.Client.Do(params.Request)
|
||||||
|
if err != nil {
|
||||||
|
params.SugarLogger.Debugf("client.Get return err:%v", err)
|
||||||
|
err, ok := err.(net.Error)
|
||||||
|
recoverableErrorRetryCount++
|
||||||
|
if ok && err.Timeout() && recoverableErrorRetryCount <= params.MaxRecoverableRetryCount {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
params.SugarLogger.Debugf("http code is:%d", response.StatusCode)
|
||||||
|
recoverableErrorRetryCount++
|
||||||
|
if recoverableErrorRetryCount <= params.MaxRecoverableRetryCount {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrHttpCode
|
||||||
|
}
|
||||||
|
|
||||||
|
errLevel, err := handleResponse(response)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if errLevel == PAErrorLevelSuccess {
|
||||||
|
return nil
|
||||||
|
} else if errLevel == PAErrorLevelExceedLimit {
|
||||||
|
exceedLimitRetryCount++
|
||||||
|
if exceedLimitRetryCount <= params.MaxExceedLimitRetryCount {
|
||||||
|
time.Sleep(params.SleepSecondWhenExceedLimit)
|
||||||
|
} else {
|
||||||
|
return ErrLimitReachMaxRetry
|
||||||
|
}
|
||||||
|
} else if errLevel == PAErrorLevelRecoverable {
|
||||||
|
if recoverableErrorRetryCount <= params.MaxRecoverableRetryCount {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return ErrRecoverableErrMaxRetry
|
||||||
|
} else {
|
||||||
|
return ErrBusinessCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,36 +2,29 @@ package elmapi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/platform/common"
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ELM_API_URL_SANDBOX = "https://open-api-sandbox.shop.ele.me/api/v1/"
|
clientTimeout = time.Second * 10
|
||||||
ELM_API_URL_PROD = "https://open-api.shop.ele.me/api/v1/"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
sleepSecondWhenLimited = 6 * time.Second
|
sleepSecondWhenLimited = 6 * time.Second
|
||||||
maxRetryCountWhenNetworkException = 3
|
maxRetryCountWhenNetworkException = 3
|
||||||
maxRetryCountWhenReachLimited = 10
|
maxRetryCountWhenReachLimited = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
const (
|
||||||
ErrSystemErrMaxRetry = errors.New("ELM System error reach max retry count!")
|
ELM_API_URL_SANDBOX = "https://open-api-sandbox.shop.ele.me/api/v1/"
|
||||||
ErrLimitReachMaxRetry = errors.New("ELM Reach max retry count!")
|
ELM_API_URL_PROD = "https://open-api.shop.ele.me/api/v1/"
|
||||||
ErrHttpCode = errors.New("ELM HTTP Code is not 200")
|
|
||||||
ErrELMCode = errors.New("ELM code is not 0")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ELMResult struct {
|
type ELMResult struct {
|
||||||
@@ -46,7 +39,7 @@ type ELMAPI struct {
|
|||||||
secret string
|
secret string
|
||||||
sugarLogger *zap.SugaredLogger
|
sugarLogger *zap.SugaredLogger
|
||||||
url *url.URL
|
url *url.URL
|
||||||
client http.Client
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type ELMPayload struct {
|
type ELMPayload struct {
|
||||||
@@ -65,7 +58,7 @@ func NewELMAPI(token, appKey, secret string, sugarLogger *zap.SugaredLogger, isP
|
|||||||
appKey: appKey,
|
appKey: appKey,
|
||||||
secret: secret,
|
secret: secret,
|
||||||
sugarLogger: sugarLogger,
|
sugarLogger: sugarLogger,
|
||||||
client: http.Client{Timeout: time.Second * 10},
|
client: &http.Client{Timeout: clientTimeout},
|
||||||
}
|
}
|
||||||
|
|
||||||
if isProd {
|
if isProd {
|
||||||
@@ -95,7 +88,7 @@ func (e *ELMAPI) signParams(action string, payload *ELMPayload) string {
|
|||||||
return fmt.Sprintf("%X", md5.Sum([]byte(finalStr)))
|
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 {
|
if params == nil {
|
||||||
params = make(map[string]interface{}, 0)
|
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)
|
payload.Signature = e.signParams(action, payload)
|
||||||
dataBytes := utils.MustMarshal(payload)
|
|
||||||
|
|
||||||
dataStr := string(dataBytes)
|
apiAccess := &common.AccessPlatformAPIWithRetryParams{
|
||||||
exceedLimitRetryCount := 0
|
MaxExceedLimitRetryCount: maxRetryCountWhenReachLimited,
|
||||||
systemErrorRetryCount := 0
|
MaxRecoverableRetryCount: maxRetryCountWhenNetworkException,
|
||||||
|
SleepSecondWhenExceedLimit: sleepSecondWhenLimited,
|
||||||
for {
|
Client: e.client,
|
||||||
request := &http.Request{
|
Request: &http.Request{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
URL: e.url,
|
URL: e.url,
|
||||||
Header: http.Header{
|
Header: http.Header{
|
||||||
@@ -131,64 +123,37 @@ func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (*ELMRe
|
|||||||
// "x-eleme-requestid": []string{payload.Id},
|
// "x-eleme-requestid": []string{payload.Id},
|
||||||
},
|
},
|
||||||
|
|
||||||
Body: ioutil.NopCloser(strings.NewReader(dataStr)),
|
Body: ioutil.NopCloser(strings.NewReader(string(utils.MustMarshal(payload)))),
|
||||||
}
|
},
|
||||||
response, err := e.client.Do(request)
|
SugarLogger: e.sugarLogger,
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result int, err error) {
|
||||||
jsonResult1, err := utils.HttpResponse2Json(response)
|
jsonResult1, err := utils.HttpResponse2Json(response)
|
||||||
|
if err != nil {
|
||||||
|
e.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
resultError, _ := jsonResult1["error"].(map[string]interface{})
|
resultError, _ := jsonResult1["error"].(map[string]interface{})
|
||||||
jsonResult := &ELMResult{
|
retVal = &ELMResult{
|
||||||
Id: jsonResult1["id"].(string),
|
Id: jsonResult1["id"].(string),
|
||||||
Error: resultError,
|
Error: resultError,
|
||||||
Result: jsonResult1["result"],
|
Result: jsonResult1["result"],
|
||||||
}
|
}
|
||||||
if err != nil {
|
errinfoMap := retVal.Error
|
||||||
e.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
errinfoMap := jsonResult.Error
|
|
||||||
if errinfoMap == nil {
|
if errinfoMap == nil {
|
||||||
return jsonResult, nil
|
return common.PAErrorLevelSuccess, nil
|
||||||
}
|
}
|
||||||
errCode := errinfoMap["code"].(string)
|
errCode := errinfoMap["code"].(string)
|
||||||
|
|
||||||
if errCode == "EXCEED_LIMIT" {
|
if errCode == "EXCEED_LIMIT" {
|
||||||
exceedLimitRetryCount++
|
return common.PAErrorLevelExceedLimit, nil
|
||||||
if exceedLimitRetryCount <= maxRetryCountWhenReachLimited {
|
|
||||||
time.Sleep(sleepSecondWhenLimited)
|
|
||||||
} else {
|
|
||||||
return jsonResult, ErrLimitReachMaxRetry
|
|
||||||
}
|
|
||||||
} else if errCode == "SERVER_ERROR" || errCode == "BIZ_SYSTEM_ERROR" || errCode == "BIZ_1006" || errCode == "BUSINESS_ERROR" {
|
} else if errCode == "SERVER_ERROR" || errCode == "BIZ_SYSTEM_ERROR" || errCode == "BIZ_1006" || errCode == "BUSINESS_ERROR" {
|
||||||
if systemErrorRetryCount <= maxRetryCountWhenNetworkException {
|
return common.PAErrorLevelRecoverable, nil
|
||||||
continue
|
|
||||||
}
|
|
||||||
return jsonResult, ErrSystemErrMaxRetry
|
|
||||||
} else {
|
} else {
|
||||||
e.sugarLogger.Debug(jsonResult)
|
return common.PAErrorLevelFailed, nil
|
||||||
return jsonResult, ErrELMCode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return retVal, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package elmapi
|
package elmapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"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)
|
t.Fatalf("Error when accessing AccessJDQuery result:%v, error:%v", result, err)
|
||||||
} else {
|
} else {
|
||||||
mapResult := result.Result.(map[string]interface{})
|
mapResult := result.Result.(map[string]interface{})
|
||||||
userIdNumber := mapResult["userId"].(json.Number)
|
userId := utils.MustInterface2Int64(mapResult["userId"])
|
||||||
userId, err := userIdNumber.Int64()
|
|
||||||
if userId != 336072266326420104 || err != nil {
|
if userId != 336072266326420104 || err != nil {
|
||||||
t.Fatalf("userId is not correct:%v", userIdNumber)
|
t.Fatalf("userId is not correct:%v", mapResult["userId"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
package elmapi
|
package elmapi
|
||||||
|
|
||||||
type ELMOrderInfo map[string]interface{}
|
func (e *ELMAPI) GetOrder(orderId string) (map[string]interface{}, error) {
|
||||||
|
|
||||||
func (e *ELMAPI) GetOrder(orderId string) (ELMOrderInfo, error) {
|
|
||||||
result, err := e.AccessELM("eleme.order.getOrder", map[string]interface{}{
|
result, err := e.AccessELM("eleme.order.getOrder", map[string]interface{}{
|
||||||
"orderId": orderId,
|
"orderId": orderId,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
innerResult := ELMOrderInfo(result.Result.(map[string]interface{}))
|
innerResult := map[string]interface{}(result.Result.(map[string]interface{}))
|
||||||
return innerResult, nil
|
return innerResult, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -5,17 +5,25 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/platform/common"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
clientTimeout = time.Second * 10
|
||||||
|
sleepSecondWhenLimited = 6 * time.Second
|
||||||
|
maxRetryCountWhenNetworkException = 3
|
||||||
|
maxRetryCountWhenReachLimited = 10
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// JDErrorCodeSuccess 操作成功
|
// JDErrorCodeSuccess 操作成功
|
||||||
JDErrorCodeSuccess = "0"
|
JDErrorCodeSuccess = "0"
|
||||||
@@ -37,29 +45,22 @@ const (
|
|||||||
JDErrorCodeLoadUnexpected = "100024"
|
JDErrorCodeLoadUnexpected = "100024"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
jdAPIURL = "https://openo2o.jd.com/djapi/%s"
|
||||||
|
AllPage = 0
|
||||||
|
DefaultPageSize = 50
|
||||||
|
)
|
||||||
|
|
||||||
type JDAPI struct {
|
type JDAPI struct {
|
||||||
token string
|
token string
|
||||||
appKey string
|
appKey string
|
||||||
appSecret string
|
appSecret string
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
sugarLogger *zap.SugaredLogger
|
sugarLogger *zap.SugaredLogger
|
||||||
client http.Client
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
sleepSecondWhenLimited = 6 * time.Second
|
|
||||||
maxRetryCountWhenNetworkException = 3
|
|
||||||
maxRetryCountWhenReachLimited = 10
|
|
||||||
jdAPIURL = "https://openo2o.jd.com/djapi/%s"
|
|
||||||
AllPage = 0
|
|
||||||
DefaultPageSize = 50
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrSystemErrMaxRetry = errors.New("JD System error reach max retry count!")
|
|
||||||
ErrLimitReachMaxRetry = errors.New("JD Reach max retry count!")
|
|
||||||
ErrHttpCode = errors.New("JD HTTP Code is not 200")
|
|
||||||
ErrJDCode = errors.New("JD code is not 0")
|
|
||||||
ErrInnerCodeIsNotOk = errors.New("JD result inner code is not ok")
|
ErrInnerCodeIsNotOk = errors.New("JD result inner code is not ok")
|
||||||
|
|
||||||
exceedLimitCodes = map[string]int{
|
exceedLimitCodes = map[string]int{
|
||||||
@@ -82,6 +83,7 @@ var (
|
|||||||
"None": 1,
|
"None": 1,
|
||||||
"0": 1,
|
"0": 1,
|
||||||
"1": 1,
|
"1": 1,
|
||||||
|
"200": 1,
|
||||||
"190005": 1, // 部分失败
|
"190005": 1, // 部分失败
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,10 +130,10 @@ func genGetURL(baseURL, apiStr string, params map[string]string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewJDAPI(token, appKey, appSecret string, logger *zap.Logger) *JDAPI {
|
func NewJDAPI(token, appKey, appSecret string, logger *zap.Logger) *JDAPI {
|
||||||
return &JDAPI{token, appKey, appSecret, logger, logger.Sugar(), http.Client{Timeout: time.Second * 10}}
|
return &JDAPI{token, appKey, appSecret, logger, logger.Sugar(), &http.Client{Timeout: clientTimeout}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JDAPI) AccessJDQuery(apiStr string, jdParams map[string]string) (map[string]interface{}, error) {
|
func (j *JDAPI) AccessJDQuery(apiStr string, jdParams map[string]string) (retVal map[string]interface{}, err error) {
|
||||||
params := make(map[string]string)
|
params := make(map[string]string)
|
||||||
params["v"] = "1.0"
|
params["v"] = "1.0"
|
||||||
params["format"] = "json"
|
params["format"] = "json"
|
||||||
@@ -152,62 +154,45 @@ func (j *JDAPI) AccessJDQuery(apiStr string, jdParams map[string]string) (map[st
|
|||||||
sign := signParams(params)
|
sign := signParams(params)
|
||||||
params["sign"] = sign
|
params["sign"] = sign
|
||||||
|
|
||||||
exceedLimitRetryCount := 0
|
url, _ := url.Parse(genGetURL(jdAPIURL, apiStr, params))
|
||||||
systemErrorRetryCount := 0
|
|
||||||
for {
|
|
||||||
fullURL := genGetURL(jdAPIURL, apiStr, params)
|
|
||||||
j.sugarLogger.Debugf("fullURL:%v", fullURL)
|
|
||||||
response, err := j.client.Get(fullURL)
|
|
||||||
if err != nil {
|
|
||||||
j.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 {
|
apiAccess := &common.AccessPlatformAPIWithRetryParams{
|
||||||
j.sugarLogger.Debugf("http code is:%d", response.StatusCode)
|
MaxExceedLimitRetryCount: maxRetryCountWhenReachLimited,
|
||||||
systemErrorRetryCount++
|
MaxRecoverableRetryCount: maxRetryCountWhenNetworkException,
|
||||||
if systemErrorRetryCount <= maxRetryCountWhenNetworkException {
|
SleepSecondWhenExceedLimit: sleepSecondWhenLimited,
|
||||||
continue
|
Client: j.client,
|
||||||
|
Request: &http.Request{
|
||||||
|
Method: "GET",
|
||||||
|
URL: url,
|
||||||
|
},
|
||||||
|
SugarLogger: j.sugarLogger,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrHttpCode
|
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (errLevel int, err error) {
|
||||||
}
|
jsonResult1, err := utils.HttpResponse2Json(response)
|
||||||
|
|
||||||
jsonResult, err := utils.HttpResponse2Json(response)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
j.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
|
j.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
|
||||||
return nil, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
code := jsonResult["code"].(string)
|
code := jsonResult1["code"].(string)
|
||||||
if code == "0" {
|
if code == "0" {
|
||||||
return jsonResult, nil
|
retVal = jsonResult1
|
||||||
|
return common.PAErrorLevelSuccess, nil
|
||||||
}
|
}
|
||||||
j.sugarLogger.Debugf("jd code is:%s", code)
|
j.sugarLogger.Debugf("jd code is:%s", code)
|
||||||
if _, ok := exceedLimitCodes[code]; ok {
|
if _, ok := exceedLimitCodes[code]; ok {
|
||||||
exceedLimitRetryCount++
|
return common.PAErrorLevelExceedLimit, nil
|
||||||
if exceedLimitRetryCount <= maxRetryCountWhenReachLimited {
|
|
||||||
time.Sleep(sleepSecondWhenLimited)
|
|
||||||
} else {
|
|
||||||
return jsonResult, ErrLimitReachMaxRetry
|
|
||||||
}
|
|
||||||
} else if _, ok := canRetryCodes[code]; ok {
|
} else if _, ok := canRetryCodes[code]; ok {
|
||||||
systemErrorRetryCount++
|
return common.PAErrorLevelRecoverable, nil
|
||||||
if systemErrorRetryCount > maxRetryCountWhenNetworkException {
|
|
||||||
return jsonResult, ErrSystemErrMaxRetry
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return jsonResult, ErrJDCode
|
return common.PAErrorLevelFailed, nil
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return retVal, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JDAPI) AccessJDQueryNoPage(apiStr string, jdParams map[string]string, keyToRemove, keyToKeep []string) (interface{}, error) {
|
func (j *JDAPI) AccessJDQueryNoPage(apiStr string, jdParams map[string]string, keyToRemove, keyToKeep []string) (interface{}, error) {
|
||||||
@@ -226,7 +211,7 @@ func (j *JDAPI) AccessJDQueryNoPage(apiStr string, jdParams map[string]string, k
|
|||||||
innerCode := ""
|
innerCode := ""
|
||||||
for _, innerCodeKey := range jdResultInnerCodeKeys {
|
for _, innerCodeKey := range jdResultInnerCodeKeys {
|
||||||
if innerCode2, ok := data[innerCodeKey]; ok {
|
if innerCode2, ok := data[innerCodeKey]; ok {
|
||||||
innerCode = innerCode2.(string)
|
innerCode = forceInnerCode2Str(innerCode2)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,7 +318,7 @@ func (j *JDAPI) AccessJDQueryHavePage(apiStr string, jdParams map[string]string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
innerCode := data["code"].(string)
|
innerCode := forceInnerCode2Str(data["code"])
|
||||||
if innerCode != "0" && innerCode != "200" {
|
if innerCode != "0" && innerCode != "200" {
|
||||||
return nil, ErrInnerCodeIsNotOk
|
return nil, ErrInnerCodeIsNotOk
|
||||||
}
|
}
|
||||||
@@ -352,3 +337,10 @@ func (j *JDAPI) AccessJDQueryHavePage(apiStr string, jdParams map[string]string,
|
|||||||
|
|
||||||
return retVal, nil
|
return retVal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func forceInnerCode2Str(innerCode interface{}) string {
|
||||||
|
if innerCodeStr, ok := innerCode.(string); ok {
|
||||||
|
return innerCodeStr
|
||||||
|
}
|
||||||
|
return string(utils.MustInterface2Int64(innerCode))
|
||||||
|
}
|
||||||
|
|||||||
142
platform/mtpsapi/mtpsapi.go
Normal file
142
platform/mtpsapi/mtpsapi.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
package mtpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"fmt"
|
||||||
|
"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 (
|
||||||
|
clientTimeout = time.Second * 10
|
||||||
|
sleepSecondWhenLimited = 6 * time.Second
|
||||||
|
maxRetryCountWhenNetworkException = 3
|
||||||
|
maxRetryCountWhenReachLimited = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
mtpsAPIURL = "https://peisongopen.meituan.com/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
mtpsStatusSuccess = 0
|
||||||
|
mtpsStatusSystemError = 1
|
||||||
|
mtpsStatusMissingSystemParams = 2
|
||||||
|
mtpsStatusMissingBusinessParams = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type MTPSResult struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Data map[string]interface{} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MTPSAPI struct {
|
||||||
|
appKey string
|
||||||
|
secret string
|
||||||
|
sugarLogger *zap.SugaredLogger
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// type MTPSOderStatus struct {
|
||||||
|
// DeliveryId int64 `json:"delivery_id"`
|
||||||
|
// MtPeiSongId string `json:"mt_peisong_id"`
|
||||||
|
// OrderId string `json:"order_id"`
|
||||||
|
// Status int `json:"status"`
|
||||||
|
// OperateTime int `json:"operate_time"`
|
||||||
|
// CourierName string `json:"courier_name"`
|
||||||
|
// CourierPhone string `json:"courier_phone"`
|
||||||
|
// CancelReasonId int `json:"cancel_reason_id"`
|
||||||
|
// CancelReason string `json:"cancel_reason"`
|
||||||
|
// }
|
||||||
|
|
||||||
|
func NewMTPSAPI(appKey, secret string, sugarLogger *zap.SugaredLogger) *MTPSAPI {
|
||||||
|
api := &MTPSAPI{
|
||||||
|
appKey: appKey,
|
||||||
|
secret: secret,
|
||||||
|
sugarLogger: sugarLogger,
|
||||||
|
client: &http.Client{Timeout: clientTimeout},
|
||||||
|
}
|
||||||
|
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MTPSAPI) signParams(params url.Values) string {
|
||||||
|
keyValues := make([]string, 0)
|
||||||
|
for k, v := range params {
|
||||||
|
valStr := strings.Join(v, "")
|
||||||
|
if valStr != "" {
|
||||||
|
keyValues = append(keyValues, k+valStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keyValues)
|
||||||
|
finalStr := m.secret + strings.Join(keyValues, "")
|
||||||
|
// e.sugarLogger.Debugf("sign str:%v", finalStr)
|
||||||
|
return fmt.Sprintf("%x", sha1.Sum([]byte(finalStr)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MTPSAPI) AccessMTPS(action string, params map[string]interface{}) (retVal *MTPSResult, err error) {
|
||||||
|
if params == nil {
|
||||||
|
panic("params is nil!")
|
||||||
|
}
|
||||||
|
params["appkey"] = m.appKey
|
||||||
|
params["timestamp"] = utils.GetCurTimestamp()
|
||||||
|
params["version"] = "1.0"
|
||||||
|
|
||||||
|
params2 := make(url.Values)
|
||||||
|
for k, v := range params {
|
||||||
|
params2[k] = []string{fmt.Sprint(v)}
|
||||||
|
}
|
||||||
|
params2["sign"] = []string{m.signParams(params2)}
|
||||||
|
|
||||||
|
request, _ := http.NewRequest("POST", mtpsAPIURL+"/"+action, strings.NewReader(string(params2.Encode())))
|
||||||
|
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
apiAccess := &common.AccessPlatformAPIWithRetryParams{
|
||||||
|
MaxExceedLimitRetryCount: maxRetryCountWhenReachLimited,
|
||||||
|
MaxRecoverableRetryCount: maxRetryCountWhenNetworkException,
|
||||||
|
SleepSecondWhenExceedLimit: sleepSecondWhenLimited,
|
||||||
|
Client: m.client,
|
||||||
|
Request: request,
|
||||||
|
SugarLogger: m.sugarLogger,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result int, err error) {
|
||||||
|
jsonResult1, err := utils.HttpResponse2Json(response)
|
||||||
|
if err != nil {
|
||||||
|
m.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
code := int(utils.MustInterface2Int64(jsonResult1["code"]))
|
||||||
|
retVal = &MTPSResult{
|
||||||
|
Code: code,
|
||||||
|
}
|
||||||
|
if code == mtpsStatusSuccess {
|
||||||
|
retVal.Data = jsonResult1["data"].(map[string]interface{})
|
||||||
|
return common.PAErrorLevelSuccess, nil
|
||||||
|
}
|
||||||
|
retVal.Message = jsonResult1["message"].(string)
|
||||||
|
return common.PAErrorLevelFailed, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MTPSAPI) QueryOrderStatus(deliveryId int64, MtPeiSongId string) (retVal map[string]interface{}, err error) {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"delivery_id": deliveryId,
|
||||||
|
"mt_peisong_id": MtPeiSongId,
|
||||||
|
}
|
||||||
|
if result, err := m.AccessMTPS("order/status/query", params); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return result.Data, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
40
platform/mtpsapi/mtpsapi_test.go
Normal file
40
platform/mtpsapi/mtpsapi_test.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package mtpsapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mtpsapi *MTPSAPI
|
||||||
|
sugarLogger *zap.SugaredLogger
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logger, _ := zap.NewDevelopment()
|
||||||
|
sugarLogger = logger.Sugar()
|
||||||
|
mtpsapi = NewMTPSAPI("3c0a05d464c247c19d7ec13accc78605", "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE", sugarLogger)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTest(t *testing.T) {
|
||||||
|
sugarLogger.Debug(utils.GetCurTimeStr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessMTPS(t *testing.T) {
|
||||||
|
mtPeiSongId := "1528955769086020"
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"delivery_id": 378194,
|
||||||
|
"mt_peisong_id": mtPeiSongId,
|
||||||
|
}
|
||||||
|
result, err := mtpsapi.AccessMTPS("order/status/query", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error when accessing AccessMTPS result:%v, error:%v", result, err)
|
||||||
|
} else {
|
||||||
|
getMtPsId := result.Data["mt_peisong_id"].(string)
|
||||||
|
if getMtPsId != mtPeiSongId {
|
||||||
|
t.Fatalf("mt_peisong_id is not same, %v vs %v", mtPeiSongId, getMtPsId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user