- add callback sign check.

This commit is contained in:
gazebo
2018-06-19 18:41:58 +08:00
parent 143a929c8c
commit 27919a36fc
11 changed files with 324 additions and 95 deletions

View File

@@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"time" "time"
"git.rosy.net.cn/baseapi/utils"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -19,17 +20,20 @@ type AccessPlatformAPIWithRetryParams struct {
} }
const ( const (
PAErrorLevelSuccess = 0 PAErrorLevelSuccess = "JXC4_SUCCESS"
PAErrorLevelExceedLimit = 1 PAErrorLevelExceedLimit = "JXC4_EXCEED_LIMIT"
PAErrorLevelRecoverable = 2 PAErrorLevelRecoverable = "JXC4_RECOVERABLE"
PAErrorLevelFailed = 3 PAErrorLevelGeneralFail = "JXC4_GENERAL_FAIL"
) )
var ( var (
ErrRecoverableErrMaxRetry = errors.New("recoverable error reach max retry count!") ErrRecoverableErrMaxRetry = errors.New("recoverable error reach max retry count!")
ErrLimitReachMaxRetry = errors.New("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")
var (
ErrStrHttpCode = "HTTP Code is not 200"
ErrStrBusinessCode = "Business code is not ok"
) )
var ( var (
@@ -37,7 +41,7 @@ var (
CBErrMsgUnmarshal = "can not unmarshal data:%v, data:%v" CBErrMsgUnmarshal = "can not unmarshal data:%v, data:%v"
) )
func AccessPlatformAPIWithRetry(params *AccessPlatformAPIWithRetryParams, handleResponse func(response *http.Response) (int, error)) error { func AccessPlatformAPIWithRetry(params *AccessPlatformAPIWithRetryParams, handleResponse func(response *http.Response) (string, error)) error {
exceedLimitRetryCount := 0 exceedLimitRetryCount := 0
recoverableErrorRetryCount := 0 recoverableErrorRetryCount := 0
for { for {
@@ -60,29 +64,29 @@ func AccessPlatformAPIWithRetry(params *AccessPlatformAPIWithRetryParams, handle
continue continue
} }
return ErrHttpCode return utils.NewErrorIntCode(ErrStrHttpCode, response.StatusCode)
} }
errLevel, err := handleResponse(response) errCode, err := handleResponse(response)
if err != nil { if err != nil {
return err return err
} }
if errLevel == PAErrorLevelSuccess { if errCode == PAErrorLevelSuccess {
return nil return nil
} else if errLevel == PAErrorLevelExceedLimit { } else if errCode == PAErrorLevelExceedLimit {
exceedLimitRetryCount++ exceedLimitRetryCount++
if exceedLimitRetryCount <= params.MaxExceedLimitRetryCount { if exceedLimitRetryCount <= params.MaxExceedLimitRetryCount {
time.Sleep(params.SleepSecondWhenExceedLimit) time.Sleep(params.SleepSecondWhenExceedLimit)
} else { } else {
return ErrLimitReachMaxRetry return ErrLimitReachMaxRetry
} }
} else if errLevel == PAErrorLevelRecoverable { } else if errCode == PAErrorLevelRecoverable {
if recoverableErrorRetryCount <= params.MaxRecoverableRetryCount { if recoverableErrorRetryCount <= params.MaxRecoverableRetryCount {
continue continue
} }
return ErrRecoverableErrMaxRetry return ErrRecoverableErrMaxRetry
} else { } else {
return ErrBusinessCode return utils.NewErrorCode(ErrStrBusinessCode, errCode)
} }
} }
} }

View File

@@ -1,10 +1,11 @@
package elmapi package elmapi
import ( import (
"encoding/json"
"fmt" "fmt"
"git.rosy.net.cn/baseapi/platform/common" "git.rosy.net.cn/baseapi/platform/common"
"git.rosy.net.cn/baseapi/utils"
"github.com/fatih/structs"
) )
const ( const (
@@ -36,7 +37,7 @@ var (
) )
func (e *ELMAPI) unmarshalData(data []byte, msg interface{}) (callbackResponse *ELMCallbackResponse) { func (e *ELMAPI) unmarshalData(data []byte, msg interface{}) (callbackResponse *ELMCallbackResponse) {
err := json.Unmarshal(data, msg) err := utils.UnmarshalUseNumber(data, msg)
if err != nil { if err != nil {
return &ELMCallbackResponse{ return &ELMCallbackResponse{
Message: fmt.Sprintf(common.CBErrMsgUnmarshal, data, err), Message: fmt.Sprintf(common.CBErrMsgUnmarshal, data, err),
@@ -45,11 +46,22 @@ func (e *ELMAPI) unmarshalData(data []byte, msg interface{}) (callbackResponse *
return nil return nil
} }
func (e *ELMAPI) CheckRequestValidation(mapData map[string]interface{}) (callbackResponse *ELMCallbackResponse) {
sign := e.signParamsMap(mapData, "")
if sign != mapData[signKey].(string) {
return &ELMCallbackResponse{Message: "signature is invalid"}
}
return nil
}
func (e *ELMAPI) GetMsgFromData(data []byte) (msg *ELMCallbackMsg, callbackResponse *ELMCallbackResponse) { func (e *ELMAPI) GetMsgFromData(data []byte) (msg *ELMCallbackMsg, callbackResponse *ELMCallbackResponse) {
msg = new(ELMCallbackMsg) msg = new(ELMCallbackMsg)
callbackResponse = e.unmarshalData(data, msg) callbackResponse = e.unmarshalData(data, msg)
if callbackResponse != nil { if callbackResponse != nil {
return nil, callbackResponse return nil, callbackResponse
} }
return msg, nil
mapData := structs.Map(msg)
callbackResponse = e.CheckRequestValidation(mapData)
return msg, callbackResponse
} }

View File

@@ -25,6 +25,7 @@ const (
const ( const (
ELM_API_URL_SANDBOX = "https://open-api-sandbox.shop.ele.me/api/v1/" 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/" ELM_API_URL_PROD = "https://open-api.shop.ele.me/api/v1/"
signKey = "signature"
) )
type ELMResult struct { type ELMResult struct {
@@ -69,25 +70,26 @@ func NewELMAPI(token, appKey, secret string, sugarLogger *zap.SugaredLogger, isP
return api return api
} }
func (e *ELMAPI) signParams(action string, payload *ELMPayload) string { func (e *ELMAPI) signParamsMap(mapData map[string]interface{}, prefix string) string {
keyValues := make([]string, 0) keyValues := make([]string, 0)
allData := []map[string]interface{}{ for k, v := range mapData {
payload.Metas, if k != signKey {
payload.Params,
}
for _, data := range allData {
for k, v := range data {
vBytes := utils.MustMarshal(v) vBytes := utils.MustMarshal(v)
keyValues = append(keyValues, k+"="+string(vBytes)) keyValues = append(keyValues, k+"="+string(vBytes))
} }
} }
sort.Strings(keyValues) sort.Strings(keyValues)
finalStr := action + e.token + strings.Join(keyValues, "") + e.secret finalStr := prefix + strings.Join(keyValues, "") + e.secret
// e.sugarLogger.Debugf("sign str:%v", finalStr) // e.sugarLogger.Debugf("sign str:%v", finalStr)
return fmt.Sprintf("%X", md5.Sum([]byte(finalStr))) return fmt.Sprintf("%X", md5.Sum([]byte(finalStr)))
} }
func (e *ELMAPI) signParams(action string, payload *ELMPayload) string {
mapData := utils.MergeMaps(payload.Metas, payload.Params)
return e.signParamsMap(mapData, action+e.token)
}
func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (retVal *ELMResult, err 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)
@@ -128,11 +130,11 @@ func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (retVal
SugarLogger: e.sugarLogger, SugarLogger: e.sugarLogger,
} }
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result int, err error) { err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result string, err error) {
jsonResult1, err := utils.HttpResponse2Json(response) jsonResult1, err := utils.HttpResponse2Json(response)
if err != nil { if err != nil {
e.sugarLogger.Warnf("HttpResponse2Json return:%v", err) e.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
return 0, err return common.PAErrorLevelGeneralFail, err
} }
resultError, _ := jsonResult1["error"].(map[string]interface{}) resultError, _ := jsonResult1["error"].(map[string]interface{})
retVal = &ELMResult{ retVal = &ELMResult{
@@ -151,7 +153,7 @@ func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (retVal
} 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" {
return common.PAErrorLevelRecoverable, nil return common.PAErrorLevelRecoverable, nil
} else { } else {
return common.PAErrorLevelFailed, nil return errCode, nil
} }
}) })

View File

@@ -1,12 +1,12 @@
package jdapi package jdapi
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"git.rosy.net.cn/baseapi/platform/common" "git.rosy.net.cn/baseapi/platform/common"
"git.rosy.net.cn/baseapi/utils"
) )
type JDCallbackResponse struct { type JDCallbackResponse struct {
@@ -43,7 +43,7 @@ var (
) )
func (j *JDAPI) unmarshalData(strData string, msg interface{}) (callbackResponse *JDCallbackResponse) { func (j *JDAPI) unmarshalData(strData string, msg interface{}) (callbackResponse *JDCallbackResponse) {
err := json.Unmarshal([]byte(strData), msg) err := utils.UnmarshalUseNumber([]byte(strData), msg)
if err != nil { if err != nil {
return &JDCallbackResponse{ return &JDCallbackResponse{
Code: JDerrorCodeAbnormalParam, Code: JDerrorCodeAbnormalParam,
@@ -54,7 +54,32 @@ func (j *JDAPI) unmarshalData(strData string, msg interface{}) (callbackResponse
return nil return nil
} }
func (j *JDAPI) CheckRequestValidation(request *http.Request) (callbackResponse *JDCallbackResponse) {
mapData := make(map[string]string)
mapData["token"] = request.FormValue("token")
mapData["app_key"] = request.FormValue("app_key")
mapData["timestamp"] = request.FormValue("timestamp")
mapData["format"] = request.FormValue("format")
mapData["app_secret"] = j.appSecret
mapData["v"] = request.FormValue("token")
mapData[JD_PARAM_JSON] = request.FormValue(JD_PARAM_JSON)
sign := j.signParams(mapData)
if sign != request.FormValue(signKey) {
return &JDCallbackResponse{
Code: JDerrorCodeInvalidSign,
Msg: "signature is invalid",
Data: string(utils.MustMarshal(mapData)),
}
}
return nil
}
func (j *JDAPI) GetOrderMsg(request *http.Request) (msg *JDOrderMsg, callbackResponse *JDCallbackResponse) { func (j *JDAPI) GetOrderMsg(request *http.Request) (msg *JDOrderMsg, callbackResponse *JDCallbackResponse) {
if callbackResponse = j.CheckRequestValidation(request); callbackResponse != nil {
return nil, callbackResponse
}
msg = new(JDOrderMsg) msg = new(JDOrderMsg)
jdParamJSON := request.FormValue(JD_PARAM_JSON) jdParamJSON := request.FormValue(JD_PARAM_JSON)
callbackResponse = j.unmarshalData(jdParamJSON, msg) callbackResponse = j.unmarshalData(jdParamJSON, msg)
@@ -65,8 +90,11 @@ func (j *JDAPI) GetOrderMsg(request *http.Request) (msg *JDOrderMsg, callbackRes
} }
func (j *JDAPI) GetOrderDeliveryMsg(request *http.Request) (msg *JDDeliveryStatusMsg, callbackResponse *JDCallbackResponse) { func (j *JDAPI) GetOrderDeliveryMsg(request *http.Request) (msg *JDDeliveryStatusMsg, callbackResponse *JDCallbackResponse) {
msg = new(JDDeliveryStatusMsg) if callbackResponse = j.CheckRequestValidation(request); callbackResponse != nil {
return nil, callbackResponse
}
msg = new(JDDeliveryStatusMsg)
jdParamJSON := request.FormValue(JD_PARAM_JSON) jdParamJSON := request.FormValue(JD_PARAM_JSON)
jdParamJSON2, err := url.QueryUnescape(jdParamJSON) jdParamJSON2, err := url.QueryUnescape(jdParamJSON)
if err != nil { if err != nil {

View File

@@ -3,7 +3,6 @@ package jdapi
import ( import (
"crypto/md5" "crypto/md5"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
@@ -51,6 +50,7 @@ const (
const ( const (
jdAPIURL = "https://openo2o.jd.com/djapi/%s" jdAPIURL = "https://openo2o.jd.com/djapi/%s"
signKey = "sign"
AllPage = 0 AllPage = 0
DefaultPageSize = 50 DefaultPageSize = 50
) )
@@ -64,7 +64,7 @@ type JDAPI struct {
} }
var ( var (
ErrInnerCodeIsNotOk = errors.New("JD result inner code is not ok") ErrStrInnerCodeIsNotOk = "JD result inner code is not ok"
exceedLimitCodes = map[string]int{ exceedLimitCodes = map[string]int{
JDErrorCodeExceedLimit: 1, JDErrorCodeExceedLimit: 1,
@@ -97,10 +97,10 @@ var (
type PageResultParser func(map[string]interface{}, int) ([]interface{}, int) type PageResultParser func(map[string]interface{}, int) ([]interface{}, int)
func signParams(jdParams map[string]string) string { func (j *JDAPI) signParams(jdParams map[string]string) string {
var keys []string var keys []string
for k := range jdParams { for k := range jdParams {
if k != "app_secret" { if k != "app_secret" && k != signKey {
keys = append(keys, k) keys = append(keys, k)
} }
} }
@@ -154,8 +154,8 @@ func (j *JDAPI) AccessJDQuery(apiStr string, jdParams map[string]string) (retVal
} }
params["jd_param_json"] = string(jdParamStr) params["jd_param_json"] = string(jdParamStr)
params["timestamp"] = utils.GetCurTimeStr() params["timestamp"] = utils.GetCurTimeStr()
sign := signParams(params) sign := j.signParams(params)
params["sign"] = sign params[signKey] = sign
url, _ := url.Parse(genGetURL(jdAPIURL, apiStr, params)) url, _ := url.Parse(genGetURL(jdAPIURL, apiStr, params))
@@ -171,16 +171,16 @@ func (j *JDAPI) AccessJDQuery(apiStr string, jdParams map[string]string) (retVal
SugarLogger: j.sugarLogger, SugarLogger: j.sugarLogger,
} }
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (errLevel int, err error) { err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (errLevel string, err error) {
jsonResult1, err := utils.HttpResponse2Json(response) jsonResult1, 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 0, err return common.PAErrorLevelGeneralFail, err
} }
code := jsonResult1["code"].(string) code := jsonResult1["code"].(string)
if code == "0" { if code == JDErrorCodeSuccess {
retVal = jsonResult1 retVal = jsonResult1
return common.PAErrorLevelSuccess, nil return common.PAErrorLevelSuccess, nil
} }
@@ -190,7 +190,7 @@ func (j *JDAPI) AccessJDQuery(apiStr string, jdParams map[string]string) (retVal
} else if _, ok := canRetryCodes[code]; ok { } else if _, ok := canRetryCodes[code]; ok {
return common.PAErrorLevelRecoverable, nil return common.PAErrorLevelRecoverable, nil
} else { } else {
return common.PAErrorLevelFailed, nil return code, nil
} }
}) })
@@ -227,7 +227,7 @@ func (j *JDAPI) AccessJDQueryNoPage(apiStr string, jdParams map[string]string, k
} }
panic("Can not find inner data") panic("Can not find inner data")
} else { } else {
return jsonResult, ErrInnerCodeIsNotOk return jsonResult, utils.NewErrorCode(ErrStrInnerCodeIsNotOk, innerCode)
} }
} }
@@ -323,7 +323,7 @@ func (j *JDAPI) AccessJDQueryHavePage(apiStr string, jdParams map[string]string,
innerCode := forceInnerCode2Str(data["code"]) innerCode := forceInnerCode2Str(data["code"])
if innerCode != "0" && innerCode != "200" { if innerCode != "0" && innerCode != "200" {
return nil, ErrInnerCodeIsNotOk return nil, utils.NewErrorCode(ErrStrInnerCodeIsNotOk, innerCode)
} }
inResult, totalCount2 := pageResultParser(data, totalCount) inResult, totalCount2 := pageResultParser(data, totalCount)

View File

@@ -1,14 +1,13 @@
package mtpsapi package mtpsapi
import ( import (
"fmt"
"net/http" "net/http"
"git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils"
) )
type MtpsCallbackResponse struct { type MtpsCallbackResponse struct {
Code string `json:"code"` Code int `json:"code"`
} }
type MtpsCallbackCommon struct { type MtpsCallbackCommon struct {
@@ -35,14 +34,21 @@ type MtpsCallbackOrderExceptionMsg struct {
} }
var ( var (
SuccessResponse = &MtpsCallbackResponse{Code: "0"} SuccessResponse = &MtpsCallbackResponse{Code: 0}
SignatureIsNotOk = &MtpsCallbackResponse{Code: -1}
) )
func (m *MTPSAPI) CheckRequestValidation(request *http.Request) (callbackResponse *MtpsCallbackResponse) { func (m *MTPSAPI) CheckRequestValidation(request *http.Request) (callbackResponse *MtpsCallbackResponse) {
request.ParseForm()
sign := m.signParams(request.PostForm)
if sign != request.FormValue(signKey) {
return SignatureIsNotOk
}
for _, valueKey := range []string{"delivery_id", "mt_peisong_id", "order_id"} { for _, valueKey := range []string{"delivery_id", "mt_peisong_id", "order_id"} {
if request.FormValue(valueKey) == "" { if request.FormValue(valueKey) == "" {
return &MtpsCallbackResponse{ return &MtpsCallbackResponse{
Code: fmt.Sprintf("missing param:%s", valueKey), Code: -1,
} }
} }
} }

View File

@@ -24,13 +24,56 @@ const (
const ( const (
mtpsAPIURL = "https://peisongopen.meituan.com/api" mtpsAPIURL = "https://peisongopen.meituan.com/api"
signKey = "sign"
) )
const ( const (
mtpsStatusSuccess = 0 OrderStatusWaitingForSchedule = 0
mtpsStatusSystemError = 1 OrderStatusAccepted = 20
mtpsStatusMissingSystemParams = 2 OrderStatusPickedUp = 30
mtpsStatusMissingBusinessParams = 3 OrderStatusDeliverred = 50
OrderStatusCanceled = 99
)
const (
DSCRapid = 4011
DSCIntime = 4012
DSCTogether = 4013
)
const (
PickupTypeClientSendToStation = 1
PickupTypeMtPick = 2
)
const (
OrderTypeASAP = 0
OrderTypeBook = 1
)
const (
CoordinateTypeMars = 0
CoordinateTypeBaidu = 1
)
// 错误码
const (
ResponseCodeSuccess = 0
)
// 取消原因
const (
CancelReasonClientActive = 101
CancelReasonClientChangeTimeOrAddress = 102
CancelReasonGoodRelated = 103
CancelReasonMerchantOther = 199
CancelReasonMtpsAttitude = 201
CancelReasonRidderSendNotIntime = 202
CancelReasonRideerGetGoodNotIntime = 203
CancelReasonRideerMtpsOther = 299
CancelReasonRideerOther = 399
) )
type MtpsOrderInfoCommon struct { type MtpsOrderInfoCommon struct {
@@ -61,27 +104,6 @@ type MTPSResult struct {
Data map[string]interface{} `json:"data"` Data map[string]interface{} `json:"data"`
} }
const (
DSCRapid = 4011
DSCIntime = 4012
DSCTogether = 403
)
const (
PickupTypeClientSendToStation = 1
PickupTypeMtPick = 2
)
const (
OrderTypeASAP = 0
OrderTypeBook = 1
)
const (
CoordinateTypeMars = 0
CoordinateTypeBaidu = 1
)
type MtpsCreateOrderByShopInfo struct { type MtpsCreateOrderByShopInfo struct {
DeliveryId int64 DeliveryId int64
OrderId string OrderId string
@@ -118,17 +140,23 @@ func NewMTPSAPI(appKey, secret string, sugarLogger *zap.SugaredLogger) *MTPSAPI
} }
func (m *MTPSAPI) signParams(params url.Values) string { func (m *MTPSAPI) signParams(params url.Values) string {
keyValues := make([]string, 0) keys := make([]string, 0)
for k, v := range params { for k := range params {
valStr := strings.Join(v, "") if k != signKey {
if valStr != "" { keys = append(keys, k)
keyValues = append(keyValues, k+valStr)
} }
} }
sort.Strings(keyValues) sort.Strings(keys)
finalStr := m.secret + strings.Join(keyValues, "") finalStr := m.secret
// e.sugarLogger.Debugf("sign str:%v", finalStr) for _, key := range keys {
valStr := strings.Join(params[key], "")
if valStr != "" {
finalStr += key + valStr
}
}
// m.sugarLogger.Debug(finalStr)
return fmt.Sprintf("%x", sha1.Sum([]byte(finalStr))) return fmt.Sprintf("%x", sha1.Sum([]byte(finalStr)))
} }
@@ -144,8 +172,8 @@ func (m *MTPSAPI) AccessMTPS(action string, params map[string]interface{}) (retV
params2["appkey"] = []string{m.appKey} params2["appkey"] = []string{m.appKey}
params2["timestamp"] = []string{utils.Int64ToStr(utils.GetCurTimestamp())} params2["timestamp"] = []string{utils.Int64ToStr(utils.GetCurTimestamp())}
params2["version"] = []string{"1.0"} params2["version"] = []string{"1.0"}
params2["sign"] = []string{m.signParams(params2)} params2[signKey] = []string{m.signParams(params2)}
// m.sugarLogger.Debug(params2.Encode())
request, _ := http.NewRequest("POST", mtpsAPIURL+"/"+action, strings.NewReader(params2.Encode())) request, _ := http.NewRequest("POST", mtpsAPIURL+"/"+action, strings.NewReader(params2.Encode()))
request.Header.Set("Content-Type", "application/x-www-form-urlencoded") request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
apiAccess := &common.AccessPlatformAPIWithRetryParams{ apiAccess := &common.AccessPlatformAPIWithRetryParams{
@@ -157,30 +185,38 @@ func (m *MTPSAPI) AccessMTPS(action string, params map[string]interface{}) (retV
SugarLogger: m.sugarLogger, SugarLogger: m.sugarLogger,
} }
err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result int, err error) { err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result string, err error) {
jsonResult1, err := utils.HttpResponse2Json(response) jsonResult1, err := utils.HttpResponse2Json(response)
if err != nil { if err != nil {
m.sugarLogger.Warnf("HttpResponse2Json return:%v", err) m.sugarLogger.Warnf("HttpResponse2Json return:%v", err)
return 0, err return common.PAErrorLevelGeneralFail, err
} }
code := int(utils.MustInterface2Int64(jsonResult1["code"])) code := int(utils.MustInterface2Int64(jsonResult1["code"]))
retVal = &MTPSResult{ retVal = &MTPSResult{
Code: code, Code: code,
} }
m.sugarLogger.Debug(jsonResult1) m.sugarLogger.Debug(jsonResult1)
if code == mtpsStatusSuccess { if code == ResponseCodeSuccess {
if innerData, ok := jsonResult1["data"]; ok { if innerData, ok := jsonResult1["data"]; ok {
retVal.Data, _ = innerData.(map[string]interface{}) retVal.Data, _ = innerData.(map[string]interface{})
} }
return common.PAErrorLevelSuccess, nil return common.PAErrorLevelSuccess, nil
} }
retVal.Message = jsonResult1["message"].(string) retVal.Message = jsonResult1["message"].(string)
return common.PAErrorLevelFailed, nil return common.PAErrorLevelGeneralFail, utils.NewErrorIntCode(retVal.Message, code)
}) })
return retVal, err return retVal, err
} }
func (m *MTPSAPI) result2OrderResponse(result *MTPSResult) (order *MtpsOrderResponse) {
order = new(MtpsOrderResponse)
order.MtPeisongId = result.Data["mt_peisong_id"].(string)
order.DeliveryId = utils.MustInterface2Int64(result.Data["delivery_id"])
order.OrderId = result.Data["order_id"].(string)
return order
}
func (m *MTPSAPI) CreateOrderByShop(basicParams *MtpsCreateOrderByShopInfo, addParams map[string]interface{}) (order *MtpsOrderResponse, err error) { func (m *MTPSAPI) CreateOrderByShop(basicParams *MtpsCreateOrderByShopInfo, addParams map[string]interface{}) (order *MtpsOrderResponse, err error) {
params := make(map[string]interface{}) params := make(map[string]interface{})
params["delivery_id"] = utils.Int64ToStr(basicParams.DeliveryId) params["delivery_id"] = utils.Int64ToStr(basicParams.DeliveryId)
@@ -207,13 +243,9 @@ func (m *MTPSAPI) CreateOrderByShop(basicParams *MtpsCreateOrderByShopInfo, addP
} }
if result, err := m.AccessMTPS("order/createByShop", params); err != nil { if result, err := m.AccessMTPS("order/createByShop", params); err != nil {
m.sugarLogger.Debugf("result:%v", result) m.sugarLogger.Debugf("result:%v", result)
return nil, err return nil, utils.NewErrorIntCode(err.Error(), result.Code)
} else { } else {
order = new(MtpsOrderResponse) return m.result2OrderResponse(result), nil
order.MtPeisongId = result.Data["mt_peisong_id"].(string)
order.DeliveryId = utils.MustInterface2Int64(result.Data["delivery_id"])
order.OrderId = result.Data["order_id"].(string)
return order, nil
} }
} }
@@ -229,6 +261,22 @@ func (m *MTPSAPI) QueryOrderStatus(deliveryId int64, mtPeiSongId string) (retVal
} }
} }
func (m *MTPSAPI) CancelOrder(deliveryId int64, mtPeiSongId string, cancelReasonId int, cancelReason string) (result *MtpsOrderResponse, err error) {
params := map[string]interface{}{
"delivery_id": deliveryId,
"mt_peisong_id": mtPeiSongId,
"cancel_reason_id": cancelReasonId,
"cancel_reason": cancelReason,
}
if result, err := m.AccessMTPS("order/delete", params); err != nil {
m.sugarLogger.Debugf("result:%v", result)
return nil, err
} else {
return m.result2OrderResponse(result), nil
}
}
func (m *MTPSAPI) simulateOrderBehavior(action string, deliveryId int64, mtPeiSongId string) (err error) { func (m *MTPSAPI) simulateOrderBehavior(action string, deliveryId int64, mtPeiSongId string) (err error) {
params := map[string]interface{}{ params := map[string]interface{}{
"delivery_id": deliveryId, "delivery_id": deliveryId,

View File

@@ -19,6 +19,12 @@ func init() {
// mtpsapi = NewMTPSAPI("3c0a05d464c247c19d7ec13accc78605", "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE", sugarLogger) // mtpsapi = NewMTPSAPI("3c0a05d464c247c19d7ec13accc78605", "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE", sugarLogger)
} }
func handleError(t *testing.T, err error) {
if err != nil {
sugarLogger.Debug(err)
t.Fatal(err.Error())
}
}
func TestTest(t *testing.T) { func TestTest(t *testing.T) {
sugarLogger.Debug(utils.GetCurTimeStr()) sugarLogger.Debug(utils.GetCurTimeStr())
} }
@@ -59,11 +65,39 @@ func TestCreateOrderByShop(t *testing.T) {
} }
order, err := mtpsapi.CreateOrderByShop(basicParams, nil) order, err := mtpsapi.CreateOrderByShop(basicParams, nil)
handleError(t, err)
if order != nil { if order != nil {
sugarLogger.Debugf("order:%v", order) sugarLogger.Debugf("order:%v", order)
} }
}
if err != nil {
sugarLogger.Debugf("err:%s", err.Error()) func TestSimulateArrange(t *testing.T) {
} err := mtpsapi.SimulateArrange(123456789, "1529387562097059")
handleError(t, err)
}
func TestSimulatePickup(t *testing.T) {
err := mtpsapi.SimulatePickup(123456789, "1529387562097059")
handleError(t, err)
}
func TestSimulateRearrange(t *testing.T) {
err := mtpsapi.SimulateRearrange(123456789, "1529387562097059")
handleError(t, err)
}
func TestSimulateDeliver(t *testing.T) {
err := mtpsapi.SimulateDeliver(123456789, "1529387562097059")
handleError(t, err)
}
func TestSimulateReportException(t *testing.T) {
err := mtpsapi.SimulateReportException(123456789, "1529387562097059")
handleError(t, err)
}
func TestCancelOrder(t *testing.T) {
result, err := mtpsapi.CancelOrder(123456789, "1529387562097059", CancelReasonMerchantOther, "just a test")
handleError(t, err)
sugarLogger.Debug(result)
} }

38
utils/errorwithcode.go Normal file
View File

@@ -0,0 +1,38 @@
package utils
import (
"fmt"
)
type ErrorWithCode struct {
str string
code string
intCode int
}
func NewErrorCode(err, code string) *ErrorWithCode {
return &ErrorWithCode{
str: err,
code: code,
intCode: Str2Int(code),
}
}
func NewErrorIntCode(err string, code int) *ErrorWithCode {
return &ErrorWithCode{
str: err,
code: Int2Str(code),
intCode: code,
}
}
func (e *ErrorWithCode) Error() string {
return fmt.Sprintf("%s, code:%s", e.str, e.code)
}
func (e *ErrorWithCode) Code() string {
return e.code
}
func (e *ErrorWithCode) IntCode() int {
return e.intCode
}

View File

@@ -173,3 +173,15 @@ func MustInterface2Int64(data interface{}) int64 {
} }
return retVal return retVal
} }
func MergeMaps(firstMap map[string]interface{}, otherMaps ...map[string]interface{}) (retVal map[string]interface{}) {
retVal = make(map[string]interface{})
allMaps := append(otherMaps, firstMap)
for _, oneMap := range allMaps {
for k, v := range oneMap {
retVal[k] = v
}
}
return retVal
}

View File

@@ -1,6 +1,7 @@
package utils package utils
import ( import (
"fmt"
"testing" "testing"
) )
@@ -29,3 +30,47 @@ func TestDictKeysMan(t *testing.T) {
t.Error("Params keysToKeep keep wrong key!") t.Error("Params keysToKeep keep wrong key!")
} }
} }
type TestModel struct {
IntData int
Int64Data int64
FloatData float64
StrData string
}
type TestModel2 struct {
IntData int
Int64Data int64
FloatData float64
AddData string
}
func unmarshStr(t *testing.T, jsonStr string, obj interface{}) {
err := UnmarshalUseNumber([]byte(jsonStr), obj)
if err != nil {
t.Fatal(err)
} else {
fmt.Println(obj)
}
}
func TestJson(t *testing.T) {
jsonStr := `
{
"IntData": 1,
"Int64Data": 1234567890123456,
"FloatData": 1234.5678,
"StrData": "str"
}
`
obj1 := make(map[string]interface{})
var obj2 interface{}
var obj3 TestModel
var obj4 TestModel2
unmarshStr(t, jsonStr, &obj1)
unmarshStr(t, jsonStr, &obj2)
unmarshStr(t, jsonStr, &obj3)
unmarshStr(t, jsonStr, &obj4)
}