package dadaapi import ( "bytes" "crypto/md5" "fmt" "net/http" "sort" "time" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/platform/common" "git.rosy.net.cn/baseapi/utils" ) const ( dadaSandboxURL = "http://newopen.qa.imdada.cn/" dadaProdURL = "http://newopen.imdada.cn/" signKey = "signature" ) const ( clientTimeout = time.Second * 10 sleepSecondWhenLimited = 6 * time.Second maxRetryCountWhenNetworkException = 3 maxRetryCountWhenReachLimited = 10 ) const ( DadaCodeException = -1 DadaCodeSuccess = 0 DadaCodeSignErr = 2003 DadaCodeRetryLater = 2012 DadaCodeNetworkErr = 2455 ) type DadaAPI struct { appKey string appSecret string sourceId string url string callbackURL string client *http.Client } type DadaResult struct { Status string `json:"status"` Code int `json:"code"` Msg string `json:"msg"` Result interface{} `json:"result"` ErrorCode int `json:"errorCode"` } type DadaCity struct { CityName string `json:"cityName"` CityCode string `json:"cityCode"` } type CancelReason struct { Id int `json:"id"` Reason string `json:"reason"` } func NewDadaAPI(appKey, appSecret, sourceId, callbackURL string, isProd bool) *DadaAPI { api := &DadaAPI{ appKey: appKey, appSecret: appSecret, sourceId: sourceId, callbackURL: callbackURL, client: &http.Client{Timeout: clientTimeout}, } if isProd { api.url = dadaProdURL } else { api.url = dadaSandboxURL } return api } func (d *DadaAPI) 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 := d.appSecret for _, k := range keys { finalStr += k + fmt.Sprint(mapData[k]) } finalStr += d.appSecret // baseapi.SugarLogger.Debugf("sign str:%v", finalStr) return fmt.Sprintf("%X", md5.Sum([]byte(finalStr))) } func (d *DadaAPI) AccessDada(action string, params map[string]interface{}) (retVal *DadaResult, err error) { params2 := make(map[string]interface{}) params2["app_key"] = d.appKey params2["timestamp"] = utils.Int64ToStr(utils.GetCurTimestamp()) params2["format"] = "json" params2["v"] = "1.0" params2["source_id"] = d.sourceId if params == nil { params2["body"] = "" } else { params2["body"] = string(utils.MustMarshal(params)) } params2[signKey] = d.signParams(params2) params2Bytes := utils.MustMarshal(params2) request, _ := http.NewRequest("POST", d.url+action, bytes.NewReader(params2Bytes)) request.Header.Set("Content-Type", "application/json") apiAccess := &common.AccessPlatformAPIWithRetryParams{ MaxExceedLimitRetryCount: maxRetryCountWhenReachLimited, MaxRecoverableRetryCount: maxRetryCountWhenNetworkException, SleepSecondWhenExceedLimit: sleepSecondWhenLimited, Client: d.client, Request: request, } err = common.AccessPlatformAPIWithRetry(apiAccess, func(response *http.Response) (result string, err error) { jsonResult1, err := utils.HttpResponse2Json(response) if err != nil { baseapi.SugarLogger.Warnf("HttpResponse2Json return:%v", err) return common.PAErrorLevelGeneralFail, err } code := int(utils.MustInterface2Int64(jsonResult1["code"])) retVal = &DadaResult{ Code: code, ErrorCode: code, Msg: jsonResult1["msg"].(string), Status: jsonResult1["status"].(string), } if code == DadaCodeSuccess { retVal.Result = jsonResult1["result"] return common.PAErrorLevelSuccess, nil } baseapi.SugarLogger.Debug(jsonResult1) if code == DadaCodeRetryLater || code == DadaCodeNetworkErr { return common.PAErrorLevelRecoverable, nil } return common.PAErrorLevelGeneralFail, utils.NewErrorIntCode(retVal.Msg, code) }) return retVal, err } func (d *DadaAPI) GetCities() (retVal []DadaCity, err error) { result, err := d.AccessDada("api/cityCode/list", nil) if err != nil { return nil, err } cites := result.Result.([]interface{}) for _, v := range cites { v2 := v.(map[string]interface{}) city := DadaCity{ CityName: v2["cityName"].(string), CityCode: v2["cityCode"].(string), } retVal = append(retVal, city) } return retVal, nil } func (d *DadaAPI) GetCancelReasons() (retVal []CancelReason, err error) { result, err := d.AccessDada("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 }