diff --git a/platform/common/common.go b/platform/common/common.go index d44856b7..8bddf6e3 100644 --- a/platform/common/common.go +++ b/platform/common/common.go @@ -6,6 +6,7 @@ import ( "net/http" "time" + "git.rosy.net.cn/baseapi/utils" "go.uber.org/zap" ) @@ -19,17 +20,20 @@ type AccessPlatformAPIWithRetryParams struct { } const ( - PAErrorLevelSuccess = 0 - PAErrorLevelExceedLimit = 1 - PAErrorLevelRecoverable = 2 - PAErrorLevelFailed = 3 + PAErrorLevelSuccess = "JXC4_SUCCESS" + PAErrorLevelExceedLimit = "JXC4_EXCEED_LIMIT" + PAErrorLevelRecoverable = "JXC4_RECOVERABLE" + PAErrorLevelGeneralFail = "JXC4_GENERAL_FAIL" ) 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") +) + +var ( + ErrStrHttpCode = "HTTP Code is not 200" + ErrStrBusinessCode = "Business code is not ok" ) var ( @@ -37,7 +41,7 @@ var ( 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 recoverableErrorRetryCount := 0 for { @@ -60,29 +64,29 @@ func AccessPlatformAPIWithRetry(params *AccessPlatformAPIWithRetryParams, handle continue } - return ErrHttpCode + return utils.NewErrorIntCode(ErrStrHttpCode, response.StatusCode) } - errLevel, err := handleResponse(response) + errCode, err := handleResponse(response) if err != nil { return err } - if errLevel == PAErrorLevelSuccess { + if errCode == PAErrorLevelSuccess { return nil - } else if errLevel == PAErrorLevelExceedLimit { + } else if errCode == PAErrorLevelExceedLimit { exceedLimitRetryCount++ if exceedLimitRetryCount <= params.MaxExceedLimitRetryCount { time.Sleep(params.SleepSecondWhenExceedLimit) } else { return ErrLimitReachMaxRetry } - } else if errLevel == PAErrorLevelRecoverable { + } else if errCode == PAErrorLevelRecoverable { if recoverableErrorRetryCount <= params.MaxRecoverableRetryCount { continue } return ErrRecoverableErrMaxRetry } else { - return ErrBusinessCode + return utils.NewErrorCode(ErrStrBusinessCode, errCode) } } } diff --git a/platform/elmapi/callback.go b/platform/elmapi/callback.go index b83f121f..41c0ee43 100644 --- a/platform/elmapi/callback.go +++ b/platform/elmapi/callback.go @@ -1,10 +1,11 @@ package elmapi import ( - "encoding/json" "fmt" "git.rosy.net.cn/baseapi/platform/common" + "git.rosy.net.cn/baseapi/utils" + "github.com/fatih/structs" ) const ( @@ -36,7 +37,7 @@ var ( ) func (e *ELMAPI) unmarshalData(data []byte, msg interface{}) (callbackResponse *ELMCallbackResponse) { - err := json.Unmarshal(data, msg) + err := utils.UnmarshalUseNumber(data, msg) if err != nil { return &ELMCallbackResponse{ Message: fmt.Sprintf(common.CBErrMsgUnmarshal, data, err), @@ -45,11 +46,22 @@ func (e *ELMAPI) unmarshalData(data []byte, msg interface{}) (callbackResponse * 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) { msg = new(ELMCallbackMsg) callbackResponse = e.unmarshalData(data, msg) if callbackResponse != nil { return nil, callbackResponse } - return msg, nil + + mapData := structs.Map(msg) + callbackResponse = e.CheckRequestValidation(mapData) + return msg, callbackResponse } diff --git a/platform/elmapi/elmapi.go b/platform/elmapi/elmapi.go index 47059502..ce370425 100644 --- a/platform/elmapi/elmapi.go +++ b/platform/elmapi/elmapi.go @@ -25,6 +25,7 @@ const ( 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/" + signKey = "signature" ) type ELMResult struct { @@ -69,25 +70,26 @@ func NewELMAPI(token, appKey, secret string, sugarLogger *zap.SugaredLogger, isP 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) - allData := []map[string]interface{}{ - payload.Metas, - payload.Params, - } - for _, data := range allData { - for k, v := range data { + for k, v := range mapData { + if k != signKey { vBytes := utils.MustMarshal(v) keyValues = append(keyValues, k+"="+string(vBytes)) } } 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) 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) { if params == nil { params = make(map[string]interface{}, 0) @@ -128,11 +130,11 @@ func (e *ELMAPI) AccessELM(action string, params map[string]interface{}) (retVal 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) if err != nil { e.sugarLogger.Warnf("HttpResponse2Json return:%v", err) - return 0, err + return common.PAErrorLevelGeneralFail, err } resultError, _ := jsonResult1["error"].(map[string]interface{}) 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" { return common.PAErrorLevelRecoverable, nil } else { - return common.PAErrorLevelFailed, nil + return errCode, nil } }) diff --git a/platform/jdapi/callback.go b/platform/jdapi/callback.go index 56e0c787..21f7322e 100644 --- a/platform/jdapi/callback.go +++ b/platform/jdapi/callback.go @@ -1,12 +1,12 @@ package jdapi import ( - "encoding/json" "fmt" "net/http" "net/url" "git.rosy.net.cn/baseapi/platform/common" + "git.rosy.net.cn/baseapi/utils" ) type JDCallbackResponse struct { @@ -43,7 +43,7 @@ var ( ) 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 { return &JDCallbackResponse{ Code: JDerrorCodeAbnormalParam, @@ -54,7 +54,32 @@ func (j *JDAPI) unmarshalData(strData string, msg interface{}) (callbackResponse 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) { + if callbackResponse = j.CheckRequestValidation(request); callbackResponse != nil { + return nil, callbackResponse + } + msg = new(JDOrderMsg) jdParamJSON := request.FormValue(JD_PARAM_JSON) 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) { - msg = new(JDDeliveryStatusMsg) + if callbackResponse = j.CheckRequestValidation(request); callbackResponse != nil { + return nil, callbackResponse + } + msg = new(JDDeliveryStatusMsg) jdParamJSON := request.FormValue(JD_PARAM_JSON) jdParamJSON2, err := url.QueryUnescape(jdParamJSON) if err != nil { diff --git a/platform/jdapi/jdapi.go b/platform/jdapi/jdapi.go index 83d67c2f..1e27e47d 100644 --- a/platform/jdapi/jdapi.go +++ b/platform/jdapi/jdapi.go @@ -3,7 +3,6 @@ package jdapi import ( "crypto/md5" "encoding/json" - "errors" "fmt" "net/http" "net/url" @@ -51,6 +50,7 @@ const ( const ( jdAPIURL = "https://openo2o.jd.com/djapi/%s" + signKey = "sign" AllPage = 0 DefaultPageSize = 50 ) @@ -64,7 +64,7 @@ type JDAPI struct { } var ( - ErrInnerCodeIsNotOk = errors.New("JD result inner code is not ok") + ErrStrInnerCodeIsNotOk = "JD result inner code is not ok" exceedLimitCodes = map[string]int{ JDErrorCodeExceedLimit: 1, @@ -97,10 +97,10 @@ var ( 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 for k := range jdParams { - if k != "app_secret" { + if k != "app_secret" && k != signKey { 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["timestamp"] = utils.GetCurTimeStr() - sign := signParams(params) - params["sign"] = sign + sign := j.signParams(params) + params[signKey] = sign 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, } - 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) if err != nil { j.sugarLogger.Warnf("HttpResponse2Json return:%v", err) - return 0, err + return common.PAErrorLevelGeneralFail, err } code := jsonResult1["code"].(string) - if code == "0" { + if code == JDErrorCodeSuccess { retVal = jsonResult1 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 { return common.PAErrorLevelRecoverable, nil } 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") } 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"]) if innerCode != "0" && innerCode != "200" { - return nil, ErrInnerCodeIsNotOk + return nil, utils.NewErrorCode(ErrStrInnerCodeIsNotOk, innerCode) } inResult, totalCount2 := pageResultParser(data, totalCount) diff --git a/platform/mtpsapi/callback.go b/platform/mtpsapi/callback.go index ee72e725..0b376289 100644 --- a/platform/mtpsapi/callback.go +++ b/platform/mtpsapi/callback.go @@ -1,14 +1,13 @@ package mtpsapi import ( - "fmt" "net/http" "git.rosy.net.cn/baseapi/utils" ) type MtpsCallbackResponse struct { - Code string `json:"code"` + Code int `json:"code"` } type MtpsCallbackCommon struct { @@ -35,14 +34,21 @@ type MtpsCallbackOrderExceptionMsg struct { } var ( - SuccessResponse = &MtpsCallbackResponse{Code: "0"} + SuccessResponse = &MtpsCallbackResponse{Code: 0} + SignatureIsNotOk = &MtpsCallbackResponse{Code: -1} ) 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"} { if request.FormValue(valueKey) == "" { return &MtpsCallbackResponse{ - Code: fmt.Sprintf("missing param:%s", valueKey), + Code: -1, } } } diff --git a/platform/mtpsapi/mtpsapi.go b/platform/mtpsapi/mtpsapi.go index a915889f..449082cf 100644 --- a/platform/mtpsapi/mtpsapi.go +++ b/platform/mtpsapi/mtpsapi.go @@ -24,13 +24,56 @@ const ( const ( mtpsAPIURL = "https://peisongopen.meituan.com/api" + signKey = "sign" ) const ( - mtpsStatusSuccess = 0 - mtpsStatusSystemError = 1 - mtpsStatusMissingSystemParams = 2 - mtpsStatusMissingBusinessParams = 3 + OrderStatusWaitingForSchedule = 0 + OrderStatusAccepted = 20 + OrderStatusPickedUp = 30 + 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 { @@ -61,27 +104,6 @@ type MTPSResult struct { 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 { DeliveryId int64 OrderId string @@ -118,17 +140,23 @@ func NewMTPSAPI(appKey, secret string, sugarLogger *zap.SugaredLogger) *MTPSAPI } 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) + keys := make([]string, 0) + for k := range params { + if k != signKey { + keys = append(keys, k) } } - sort.Strings(keyValues) - finalStr := m.secret + strings.Join(keyValues, "") - // e.sugarLogger.Debugf("sign str:%v", finalStr) + sort.Strings(keys) + finalStr := m.secret + 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))) } @@ -144,8 +172,8 @@ func (m *MTPSAPI) AccessMTPS(action string, params map[string]interface{}) (retV params2["appkey"] = []string{m.appKey} params2["timestamp"] = []string{utils.Int64ToStr(utils.GetCurTimestamp())} 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.Header.Set("Content-Type", "application/x-www-form-urlencoded") apiAccess := &common.AccessPlatformAPIWithRetryParams{ @@ -157,30 +185,38 @@ func (m *MTPSAPI) AccessMTPS(action string, params map[string]interface{}) (retV 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) if err != nil { m.sugarLogger.Warnf("HttpResponse2Json return:%v", err) - return 0, err + return common.PAErrorLevelGeneralFail, err } code := int(utils.MustInterface2Int64(jsonResult1["code"])) retVal = &MTPSResult{ Code: code, } m.sugarLogger.Debug(jsonResult1) - if code == mtpsStatusSuccess { + if code == ResponseCodeSuccess { if innerData, ok := jsonResult1["data"]; ok { retVal.Data, _ = innerData.(map[string]interface{}) } return common.PAErrorLevelSuccess, nil } retVal.Message = jsonResult1["message"].(string) - return common.PAErrorLevelFailed, nil + return common.PAErrorLevelGeneralFail, utils.NewErrorIntCode(retVal.Message, code) }) 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) { params := make(map[string]interface{}) 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 { m.sugarLogger.Debugf("result:%v", result) - return nil, err + return nil, utils.NewErrorIntCode(err.Error(), result.Code) } else { - 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, nil + return m.result2OrderResponse(result), 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) { params := map[string]interface{}{ "delivery_id": deliveryId, diff --git a/platform/mtpsapi/mtpsapi_test.go b/platform/mtpsapi/mtpsapi_test.go index 8809754e..414264b1 100644 --- a/platform/mtpsapi/mtpsapi_test.go +++ b/platform/mtpsapi/mtpsapi_test.go @@ -19,6 +19,12 @@ func init() { // 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) { sugarLogger.Debug(utils.GetCurTimeStr()) } @@ -59,11 +65,39 @@ func TestCreateOrderByShop(t *testing.T) { } order, err := mtpsapi.CreateOrderByShop(basicParams, nil) + handleError(t, err) if order != nil { 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) } diff --git a/utils/errorwithcode.go b/utils/errorwithcode.go new file mode 100644 index 00000000..3251908d --- /dev/null +++ b/utils/errorwithcode.go @@ -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 +} diff --git a/utils/utils.go b/utils/utils.go index 6010f1ab..72ab7672 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -173,3 +173,15 @@ func MustInterface2Int64(data interface{}) int64 { } 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 +} diff --git a/utils/utils_test.go b/utils/utils_test.go index a7b06e89..f48ba419 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -1,6 +1,7 @@ package utils import ( + "fmt" "testing" ) @@ -29,3 +30,47 @@ func TestDictKeysMan(t *testing.T) { 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) +}