package dadaapi import ( "bytes" "crypto/md5" "fmt" "net/http" "sort" "git.rosy.net.cn/baseapi/platformapi" "git.rosy.net.cn/baseapi/utils" ) const ( sandboxURL = "http://newopen.qa.imdada.cn" prodURL = "http://newopen.imdada.cn" signKey = "signature" ) const ( ResponseCodeException = -1 ResponseCodeSuccess = 0 ResponseCodeSignErr = 2003 ResponseCodeRetryLater = 2012 ResponseCodeShopNotExist = 2402 ResponseCodeShopAlreadyExist = 2403 ResponseCodeNetworkErr = 2455 ) type API struct { appKey string appSecret string sourceID string url string callbackURL string client *http.Client config *platformapi.APIConfig } type ResponseResult struct { Status string `json:"status"` Code int `json:"code"` Msg string `json:"msg"` Result interface{} `json:"result"` ErrorCode int `json:"errorCode"` } type City struct { CityName string `json:"cityName"` CityCode string `json:"cityCode"` } type CancelReason struct { ID int `json:"id"` Reason string `json:"reason"` } func New(appKey, appSecret, sourceId, callbackURL string, isProd bool, config ...*platformapi.APIConfig) *API { curConfig := platformapi.DefAPIConfig if len(config) > 0 { curConfig = *config[0] } api := &API{ appKey: appKey, appSecret: appSecret, sourceID: sourceId, callbackURL: callbackURL, client: &http.Client{Timeout: curConfig.ClientTimeout}, config: &curConfig, } if isProd { api.url = prodURL } else { api.url = sandboxURL } return api } func (a *API) signParams(mapData map[string]interface{}) string { keys := make([]string, 0) for k := range mapData { if k != signKey { keys = append(keys, k) } } sort.Strings(keys) finalStr := a.appSecret for _, k := range keys { finalStr += k + fmt.Sprint(mapData[k]) } finalStr += a.appSecret // baseapi.SugarLogger.Debugf("sign str:%v", finalStr) return fmt.Sprintf("%X", md5.Sum([]byte(finalStr))) } func (a *API) AccessAPI(action string, params interface{}) (retVal *ResponseResult, err error) { params2 := make(map[string]interface{}) params2["app_key"] = a.appKey params2["timestamp"] = utils.Int64ToStr(utils.GetCurTimestamp()) params2["format"] = "json" params2["v"] = "1.0" params2["source_id"] = a.sourceID if params == nil { params2["body"] = "" } else { params2["body"] = string(utils.MustMarshal(params)) } params2[signKey] = a.signParams(params2) params2Bytes := utils.MustMarshal(params2) err = platformapi.AccessPlatformAPIWithRetry(a.client, func() *http.Request { request, _ := http.NewRequest(http.MethodPost, a.url+"/"+action, bytes.NewReader(params2Bytes)) request.Header.Set("Content-Type", "application/json") return request }, a.config, func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) { if jsonResult1 == nil { return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil") } code := int(utils.MustInterface2Int64(jsonResult1["code"])) retVal = &ResponseResult{ Code: code, ErrorCode: code, Msg: jsonResult1["msg"].(string), Status: jsonResult1["status"].(string), } retVal.Result = jsonResult1["result"] if code == ResponseCodeSuccess { return platformapi.ErrLevelSuccess, nil } newErr := utils.NewErrorIntCode(retVal.Msg, code) if code == ResponseCodeRetryLater || code == ResponseCodeNetworkErr { return platformapi.ErrLevelRecoverableErr, newErr } return platformapi.ErrLevelCodeIsNotOK, newErr }) return retVal, err } func (a *API) GetCities() (retVal []City, err error) { result, err := a.AccessAPI("api/cityCode/list", nil) if err != nil { return nil, err } cites := result.Result.([]interface{}) for _, v := range cites { v2 := v.(map[string]interface{}) city := City{ CityName: v2["cityName"].(string), CityCode: v2["cityCode"].(string), } retVal = append(retVal, city) } return retVal, nil } func (a *API) GetCancelReasons() (retVal []CancelReason, err error) { result, err := a.AccessAPI("api/order/cancel/reasons", nil) if err != nil { return nil, err } cites := result.Result.([]interface{}) for _, v := range cites { v2 := v.(map[string]interface{}) reason := CancelReason{ ID: int(utils.MustInterface2Int64(v2["id"])), Reason: v2["reason"].(string), } retVal = append(retVal, reason) } return retVal, nil } func IsErrShopNotExist(err error) bool { if err != nil { if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == ResponseCodeShopNotExist { return true } } return false } func IsErrShopExist(err error) bool { if err != nil { if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == ResponseCodeShopAlreadyExist { return true } } return false }