Merge branch 'master' of e.coding.net:rosydev/baseapi
This commit is contained in:
@@ -43,6 +43,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
FakeDistrictPadding = 9000000
|
FakeDistrictPadding = 9000000
|
||||||
|
MaxConvertCount = 40
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -89,6 +90,11 @@ type District struct {
|
|||||||
Districts []*District `json:"districts"`
|
Districts []*District `json:"districts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Coordinate struct {
|
||||||
|
Lng float64 `json:"lng"`
|
||||||
|
Lat float64 `json:"lat"`
|
||||||
|
}
|
||||||
|
|
||||||
type ResponseResult map[string]interface{}
|
type ResponseResult map[string]interface{}
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
@@ -127,6 +133,10 @@ func (a *API) signParams(mapData map[string]interface{}) string {
|
|||||||
return fmt.Sprintf("%X", md5.Sum([]byte(finalStr)))
|
return fmt.Sprintf("%X", md5.Sum([]byte(finalStr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func coordinate2String(lng, lat float64) (str string) {
|
||||||
|
return fmt.Sprintf("%.6f,%.6f", lng, lat)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal ResponseResult, err error) {
|
func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal ResponseResult, err error) {
|
||||||
params2 := utils.MergeMaps(utils.Params2Map("key", a.key, "output", "json"), params)
|
params2 := utils.MergeMaps(utils.Params2Map("key", a.key, "output", "json"), params)
|
||||||
params2[signKey] = a.signParams(params2)
|
params2[signKey] = a.signParams(params2)
|
||||||
@@ -161,6 +171,15 @@ func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal Re
|
|||||||
|
|
||||||
// 为了方便调用者编码,如果失败,也会返回未转换的原始值
|
// 为了方便调用者编码,如果失败,也会返回未转换的原始值
|
||||||
func (a *API) CoordinateConvert(lng, lat float64, coordsys string) (retLng, retLat float64, err error) {
|
func (a *API) CoordinateConvert(lng, lat float64, coordsys string) (retLng, retLat float64, err error) {
|
||||||
|
// outCoords, err := a.BatchCoordinateConvert([]*Coordinate{
|
||||||
|
// &Coordinate{
|
||||||
|
// Lng: lng,
|
||||||
|
// Lat: lat,
|
||||||
|
// },
|
||||||
|
// }, coordsys)
|
||||||
|
// if err == nil {
|
||||||
|
// retLng, retLat = outCoords[0].Lng, outCoords[0].Lat
|
||||||
|
// }
|
||||||
if coordsys == "" || coordsys == CoordSysAutonavi {
|
if coordsys == "" || coordsys == CoordSysAutonavi {
|
||||||
return lng, lat, nil
|
return lng, lat, nil
|
||||||
}
|
}
|
||||||
@@ -168,7 +187,7 @@ func (a *API) CoordinateConvert(lng, lat float64, coordsys string) (retLng, retL
|
|||||||
return 0.0, 0.0, nil
|
return 0.0, 0.0, nil
|
||||||
}
|
}
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"locations": fmt.Sprintf("%.6f,%.6f", lng, lat),
|
"locations": coordinate2String(lng, lat),
|
||||||
"coordsys": coordsys,
|
"coordsys": coordsys,
|
||||||
}
|
}
|
||||||
result, err := a.AccessAPI("assistant/coordinate/convert", params)
|
result, err := a.AccessAPI("assistant/coordinate/convert", params)
|
||||||
@@ -180,6 +199,33 @@ func (a *API) CoordinateConvert(lng, lat float64, coordsys string) (retLng, retL
|
|||||||
return lng, lat, err
|
return lng, lat, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) BatchCoordinateConvert(coords []*Coordinate, coordsys string) (outCoords []*Coordinate, err error) {
|
||||||
|
if coordsys == "" || coordsys == CoordSysAutonavi {
|
||||||
|
return coords, nil
|
||||||
|
}
|
||||||
|
var coordsStrList []string
|
||||||
|
for _, v := range coords {
|
||||||
|
coordsStrList = append(coordsStrList, coordinate2String(v.Lng, v.Lat))
|
||||||
|
}
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"locations": strings.Join(coordsStrList, "|"),
|
||||||
|
"coordsys": coordsys,
|
||||||
|
}
|
||||||
|
result, err := a.AccessAPI("assistant/coordinate/convert", params)
|
||||||
|
if err == nil {
|
||||||
|
coordinate := result["locations"].(string)
|
||||||
|
retCoordsStrList := strings.Split(coordinate, ";")
|
||||||
|
for _, v := range retCoordsStrList {
|
||||||
|
pair := strings.Split(v, ",")
|
||||||
|
outCoords = append(outCoords, &Coordinate{
|
||||||
|
Lng: utils.Str2Float64(pair[0]),
|
||||||
|
Lat: utils.Str2Float64(pair[1]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return outCoords, err
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) GetCoordinateFromAddress(address string, cityInfo string) (lng, lat float64, districtCode int) {
|
func (a *API) GetCoordinateFromAddress(address string, cityInfo string) (lng, lat float64, districtCode int) {
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"address": address,
|
"address": address,
|
||||||
@@ -218,7 +264,7 @@ func (a *API) GetCoordinateDistrictCode(lng, lat float64) (districtCode int) {
|
|||||||
|
|
||||||
func (a *API) GetCoordinateAreaInfo(lng, lat float64) (areaInfo map[string]interface{}, err error) {
|
func (a *API) GetCoordinateAreaInfo(lng, lat float64) (areaInfo map[string]interface{}, err error) {
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"location": fmt.Sprintf("%.6f,%.6f", lng, lat),
|
"location": coordinate2String(lng, lat),
|
||||||
}
|
}
|
||||||
result, err := a.AccessAPI("geocode/regeo", params)
|
result, err := a.AccessAPI("geocode/regeo", params)
|
||||||
return result, err
|
return result, err
|
||||||
@@ -283,3 +329,18 @@ func (a *API) getDistrictsFromInterface(districts interface{}) (districtList []*
|
|||||||
func GetDistrictLevel(levelName string) (level int) {
|
func GetDistrictLevel(levelName string) (level int) {
|
||||||
return levelStr2IntMap[levelName]
|
return levelStr2IntMap[levelName]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 两点之间的步行距离,单位为米
|
||||||
|
func (a *API) WalkingDistance(lng1, lat1, lng2, lat2 float64) (distance float64) {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"origin": coordinate2String(lng1, lat1),
|
||||||
|
"destination": coordinate2String(lng2, lat2),
|
||||||
|
}
|
||||||
|
result, err := a.AccessAPI("direction/walking", params)
|
||||||
|
if err == nil {
|
||||||
|
if paths, _ := result["route"].(map[string]interface{})["paths"].([]interface{}); len(paths) > 0 {
|
||||||
|
distance = utils.Interface2Float64WithDefault(paths[0].(map[string]interface{})["distance"], 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return distance
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func init() {
|
|||||||
sugarLogger = logger.Sugar()
|
sugarLogger = logger.Sugar()
|
||||||
baseapi.Init(sugarLogger)
|
baseapi.Init(sugarLogger)
|
||||||
|
|
||||||
autonaviAPI = New("4427170f870af2110becb8852d36ab08")
|
autonaviAPI = New("ef64f638f31e05cb7bde28790f7309fe")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoordinateConvert(t *testing.T) {
|
func TestCoordinateConvert(t *testing.T) {
|
||||||
@@ -88,3 +88,8 @@ func TestGetCoordinateFromAddress(t *testing.T) {
|
|||||||
lng, lat, districtCode := autonaviAPI.GetCoordinateFromAddress("天府广场", "成都市")
|
lng, lat, districtCode := autonaviAPI.GetCoordinateFromAddress("天府广场", "成都市")
|
||||||
t.Logf("lng:%f, lat:%f, districtCode:%d", lng, lat, districtCode)
|
t.Logf("lng:%f, lat:%f, districtCode:%d", lng, lat, districtCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWalkingDistance(t *testing.T) {
|
||||||
|
distance := autonaviAPI.WalkingDistance(104.057289, 30.694798, 104.066289, 30.695598)
|
||||||
|
t.Logf("distance:%f", distance)
|
||||||
|
}
|
||||||
|
|||||||
168
platformapi/baidunavi/baidunavi.go
Normal file
168
platformapi/baidunavi/baidunavi.go
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
package baidunavi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi/platformapi"
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
signKey = "sn"
|
||||||
|
resultKey = "result"
|
||||||
|
prodURL = "http://api.map.baidu.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusCodeSuccess = 0
|
||||||
|
StatusCodeInternalErr = 1 // 服务器内部错误
|
||||||
|
StatusCodeExceedDailyQuota = 301 // 永久配额超限,限制访问
|
||||||
|
StatusCodeExceedQuota = 302 // 天配额超限,限制访问
|
||||||
|
StatusCodeExceedDailyConcurrentQuota = 401 // 当前并发量已经超过约定并发配额,限制访问
|
||||||
|
StatusCodeExceedConcurrentQuota = 402 // 当前并发量已经超过约定并发配额,并且服务总并发量也已经超过设定的总并发配额,限制访问
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CoordSysWGS84 = 1 // GPS设备获取的角度坐标,WGS84坐标
|
||||||
|
CoordSysGCJ02 = 3 // google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标,国测局(GCJ02)坐标
|
||||||
|
CoordSysBaiDu = 5 // 百度地图采用的经纬度坐标
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MaxCoordsConvBatchSize = 100
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
exceedLimitCodes = map[int]int{
|
||||||
|
StatusCodeExceedDailyQuota: 1,
|
||||||
|
StatusCodeExceedQuota: 1,
|
||||||
|
StatusCodeExceedDailyConcurrentQuota: 1,
|
||||||
|
StatusCodeExceedConcurrentQuota: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
canRetryCodes = map[int]int{
|
||||||
|
StatusCodeInternalErr: 1,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type Coordinate struct {
|
||||||
|
Lng float64 `json:"x"`
|
||||||
|
Lat float64 `json:"y"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type API struct {
|
||||||
|
client *http.Client
|
||||||
|
config *platformapi.APIConfig
|
||||||
|
ak string
|
||||||
|
sk string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ak, sk string, config ...*platformapi.APIConfig) *API {
|
||||||
|
curConfig := platformapi.DefAPIConfig
|
||||||
|
if len(config) > 0 {
|
||||||
|
curConfig = *config[0]
|
||||||
|
}
|
||||||
|
return &API{
|
||||||
|
ak: ak,
|
||||||
|
sk: sk,
|
||||||
|
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||||
|
config: &curConfig,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) signParams(apiStr string, mapData map[string]interface{}) string {
|
||||||
|
keys := make([]string, 0)
|
||||||
|
for k := range mapData {
|
||||||
|
if k != signKey {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
strList := []string{}
|
||||||
|
for _, k := range keys {
|
||||||
|
strList = append(strList, k+"="+url.QueryEscape(fmt.Sprint(mapData[k])))
|
||||||
|
}
|
||||||
|
finalStr := "/" + apiStr + "?" + strings.Join(strList, "&") + a.sk
|
||||||
|
// baseapi.SugarLogger.Debugf("sign str:%v", finalStr)
|
||||||
|
finalStr = url.QueryEscape(finalStr)
|
||||||
|
return fmt.Sprintf("%x", md5.Sum([]byte(finalStr)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func genGetURL(baseURL, apiStr string, params map[string]interface{}) string {
|
||||||
|
keys := make([]string, 0)
|
||||||
|
for k := range params {
|
||||||
|
if k != signKey {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
strList := []string{}
|
||||||
|
for _, k := range keys {
|
||||||
|
strList = append(strList, k+"="+url.QueryEscape(fmt.Sprint(params[k])))
|
||||||
|
}
|
||||||
|
strList = append(strList, signKey+"="+url.QueryEscape(fmt.Sprint(params[signKey])))
|
||||||
|
queryString := "?" + strings.Join(strList, "&")
|
||||||
|
if apiStr != "" {
|
||||||
|
return baseURL + "/" + apiStr + queryString
|
||||||
|
}
|
||||||
|
return baseURL + queryString
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal interface{}, err error) {
|
||||||
|
apiStr += "/"
|
||||||
|
params2 := utils.MergeMaps(utils.Params2Map("ak", a.ak, "output", "json"), params)
|
||||||
|
params2[signKey] = a.signParams(apiStr, params2)
|
||||||
|
|
||||||
|
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||||
|
func() *http.Request {
|
||||||
|
request, _ := http.NewRequest(http.MethodGet, genGetURL(prodURL, apiStr, params2), nil)
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
status := int(utils.MustInterface2Int64(jsonResult1["status"]))
|
||||||
|
if status == StatusCodeSuccess {
|
||||||
|
retVal = jsonResult1[resultKey]
|
||||||
|
return platformapi.ErrLevelSuccess, nil
|
||||||
|
}
|
||||||
|
newErr := utils.NewErrorIntCode(utils.Interface2String(jsonResult1["message"]), status)
|
||||||
|
if _, ok := exceedLimitCodes[status]; ok {
|
||||||
|
return platformapi.ErrLevelExceedLimit, newErr
|
||||||
|
} else if _, ok := canRetryCodes[status]; ok {
|
||||||
|
return platformapi.ErrLevelRecoverableErr, newErr
|
||||||
|
} else {
|
||||||
|
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) BatchCoordinateConvert(coords []*Coordinate, fromCoordSys, toCoordSys int) (outCoords []*Coordinate, err error) {
|
||||||
|
if fromCoordSys == toCoordSys {
|
||||||
|
return coords, nil
|
||||||
|
}
|
||||||
|
var coordsStrList []string
|
||||||
|
for _, v := range coords {
|
||||||
|
coordsStrList = append(coordsStrList, fmt.Sprintf("%.6f,%.6f", v.Lng, v.Lat))
|
||||||
|
}
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"coords": strings.Join(coordsStrList, ";"),
|
||||||
|
"from": fromCoordSys,
|
||||||
|
"to": toCoordSys,
|
||||||
|
}
|
||||||
|
result, err := a.AccessAPI("geoconv/v1", params)
|
||||||
|
if err == nil {
|
||||||
|
err = utils.Map2StructByJson(result, &outCoords, false)
|
||||||
|
}
|
||||||
|
return outCoords, err
|
||||||
|
}
|
||||||
41
platformapi/baidunavi/baidunavi_test.go
Normal file
41
platformapi/baidunavi/baidunavi_test.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package baidunavi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.rosy.net.cn/baseapi"
|
||||||
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
api *API
|
||||||
|
sugarLogger *zap.SugaredLogger
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logger, _ := zap.NewDevelopment()
|
||||||
|
sugarLogger = logger.Sugar()
|
||||||
|
baseapi.Init(sugarLogger)
|
||||||
|
|
||||||
|
api = New("eL94zToVOdGDTkNQxV8dnEQ1ZRcB2UKb", "ZG0OOpOsOVURUwAkkmoHQFKRCbzn0zGb")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBatchCoordinateConvert(t *testing.T) {
|
||||||
|
result, err := api.BatchCoordinateConvert([]*Coordinate{
|
||||||
|
&Coordinate{
|
||||||
|
Lng: 104.057367,
|
||||||
|
Lat: 30.694686,
|
||||||
|
},
|
||||||
|
&Coordinate{
|
||||||
|
Lng: 104.057367,
|
||||||
|
Lat: 30.694686,
|
||||||
|
},
|
||||||
|
}, CoordSysGCJ02, CoordSysBaiDu)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TestCoordinateConvert failed with error:%v", err)
|
||||||
|
} else {
|
||||||
|
t.Log(utils.Format4Output(result, false))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -145,7 +145,7 @@ func (a *API) ActivitySkuAddBatch(activityID int64, shopID string, baiduShopID i
|
|||||||
params[skusKey] = skuList2Str(activityType, skuList, isSkuIDCustom)
|
params[skusKey] = skuList2Str(activityType, skuList, isSkuIDCustom)
|
||||||
result, err := a.AccessAPI("activity.sku.add.batch", params)
|
result, err := a.AccessAPI("activity.sku.add.batch", params)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return strings.Split(result.Data.(string), ","), nil
|
return strings.Split(utils.Interface2String(result.Data), ","), nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -180,7 +180,7 @@ func (a *API) ActivitySkuDeleteBatch(activityID int64, shopID string, baiduShopI
|
|||||||
params[skusKey] = strings.Join(skuIDs, ",")
|
params[skusKey] = strings.Join(skuIDs, ",")
|
||||||
result, err := a.AccessAPI("activity.sku.delete.batch", params)
|
result, err := a.AccessAPI("activity.sku.delete.batch", params)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return strings.Split(result.Data.(string), ","), nil
|
return strings.Split(utils.Interface2String(result.Data), ","), nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ func (a *API) ActivitySkuUpdateBatch(activityID int64, actSkuInfoList []*Activit
|
|||||||
"act_sku_info": actSkuInfoList,
|
"act_sku_info": actSkuInfoList,
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return strings.Split(result.Data.(string), ";"), nil
|
return strings.Split(utils.Interface2String(result.Data), ";"), nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,16 +113,12 @@ func (a *API) unmarshalData(cmd string, data []byte, msg interface{}) (callbackR
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) CheckCallbackValidation(request *http.Request) (callbackResponse *CallbackResponse) {
|
func (a *API) CheckCallbackValidation(cmd string, params url.Values) (callbackResponse *CallbackResponse) {
|
||||||
params := make(url.Values)
|
|
||||||
for k, v := range request.PostForm {
|
|
||||||
params[k] = v
|
|
||||||
}
|
|
||||||
sign := a.signParams(params)
|
sign := a.signParams(params)
|
||||||
if sign != request.FormValue(signKey) {
|
if sign != params.Get(signKey) {
|
||||||
msg := fmt.Sprintf("Signature is not ok, mine:%v, get:%v", sign, request.FormValue(signKey))
|
msg := fmt.Sprintf("Signature is not ok, mine:%v, get:%v", sign, params.Get(signKey))
|
||||||
baseapi.SugarLogger.Info(msg)
|
baseapi.SugarLogger.Info(msg)
|
||||||
return a.Err2CallbackResponse(GetCmd(request), errors.New(msg), nil)
|
return a.Err2CallbackResponse(cmd, errors.New(msg), nil)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -130,15 +126,20 @@ func (a *API) CheckCallbackValidation(request *http.Request) (callbackResponse *
|
|||||||
func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackResponse *CallbackResponse) {
|
func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackResponse *CallbackResponse) {
|
||||||
err := request.ParseForm()
|
err := request.ParseForm()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if callbackResponse = a.CheckCallbackValidation(request); callbackResponse != nil {
|
params := make(url.Values)
|
||||||
return nil, callbackResponse
|
for k := range request.PostForm {
|
||||||
|
decodedValue, _ := url.QueryUnescape(request.PostFormValue(k))
|
||||||
|
params.Set(k, decodedValue)
|
||||||
}
|
}
|
||||||
msg = new(CallbackMsg)
|
msg = new(CallbackMsg)
|
||||||
if callbackResponse = a.unmarshalData(GetCmd(request), []byte(request.FormValue("body")), &msg.Body); callbackResponse != nil {
|
msg.Cmd = GetCmd(request)
|
||||||
|
if callbackResponse = a.CheckCallbackValidation(msg.Cmd, params); callbackResponse != nil {
|
||||||
return nil, callbackResponse
|
return nil, callbackResponse
|
||||||
}
|
}
|
||||||
msg.Cmd = GetCmd(request)
|
if callbackResponse = a.unmarshalData(msg.Cmd, []byte(params.Get("body")), &msg.Body); callbackResponse != nil {
|
||||||
msg.Timestamp = utils.Str2Int64(utils.Interface2String(request.FormValue("timestamp")))
|
return nil, callbackResponse
|
||||||
|
}
|
||||||
|
msg.Timestamp = utils.Str2Int64(utils.Interface2String(params.Get("timestamp")))
|
||||||
var tmpObj interface{}
|
var tmpObj interface{}
|
||||||
switch msg.Cmd {
|
switch msg.Cmd {
|
||||||
case CmdOrderPartRefund:
|
case CmdOrderPartRefund:
|
||||||
@@ -158,6 +159,7 @@ func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackR
|
|||||||
return nil, a.Err2CallbackResponse("", err, nil)
|
return nil, a.Err2CallbackResponse("", err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCmd(request *http.Request) string {
|
func GetCmd(request *http.Request) (cmd string) {
|
||||||
return request.FormValue("cmd")
|
cmd, _ = url.QueryUnescape(request.FormValue("cmd"))
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,18 +15,7 @@ type CityInfo struct {
|
|||||||
func (a *API) CommonShopCities(parentID int) (cityList []*CityInfo, err error) {
|
func (a *API) CommonShopCities(parentID int) (cityList []*CityInfo, err error) {
|
||||||
result, err := a.AccessAPI("common.shopcities", utils.Params2Map("pid", parentID))
|
result, err := a.AccessAPI("common.shopcities", utils.Params2Map("pid", parentID))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
cityMapList := utils.Slice2MapSlice(result.Data.([]interface{}))
|
err = utils.Map2StructByJson(result.Data, &cityList, true)
|
||||||
// baseapi.SugarLogger.Debug(utils.Format4Output(cityMapList, false))
|
|
||||||
cityList = make([]*CityInfo, len(cityMapList))
|
|
||||||
for k, v := range cityMapList {
|
|
||||||
cityList[k] = &CityInfo{
|
|
||||||
ID: int(utils.Str2Int64(utils.Interface2String(v["city_id"]))),
|
|
||||||
Name: utils.Interface2String(v["city_name"]),
|
|
||||||
ParentID: int(utils.Str2Int64(utils.Interface2String(v["parent_id"]))),
|
|
||||||
IsOpen: int(utils.Str2Int64(utils.Interface2String(v["is_open"]))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cityList, nil
|
|
||||||
}
|
}
|
||||||
return nil, err
|
return cityList, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi"
|
"git.rosy.net.cn/baseapi"
|
||||||
"git.rosy.net.cn/baseapi/platformapi"
|
"git.rosy.net.cn/baseapi/platformapi"
|
||||||
@@ -43,9 +42,6 @@ type API struct {
|
|||||||
config *platformapi.APIConfig
|
config *platformapi.APIConfig
|
||||||
speedLimiter *platformapi.Limiter
|
speedLimiter *platformapi.Limiter
|
||||||
supplierID int64
|
supplierID int64
|
||||||
|
|
||||||
locker sync.RWMutex
|
|
||||||
storeCookies map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(source, secret string, config ...*platformapi.APIConfig) *API {
|
func New(source, secret string, config ...*platformapi.APIConfig) *API {
|
||||||
@@ -60,7 +56,6 @@ func New(source, secret string, config ...*platformapi.APIConfig) *API {
|
|||||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||||
config: &curConfig,
|
config: &curConfig,
|
||||||
speedLimiter: platformapi.New(apiLimitConfigs, nil), //defaultAPILimitConfig),
|
speedLimiter: platformapi.New(apiLimitConfigs, nil), //defaultAPILimitConfig),
|
||||||
storeCookies: make(map[string]string),
|
|
||||||
|
|
||||||
supplierID: -1,
|
supplierID: -1,
|
||||||
}
|
}
|
||||||
@@ -155,12 +150,12 @@ func (a *API) AccessAPI(cmd string, body map[string]interface{}) (retVal *Respon
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) GetSupplierID() (supplierID int64) {
|
func (a *API) GetSupplierID() (supplierID int64) {
|
||||||
a.locker.RLock()
|
a.RLock()
|
||||||
supplierID = a.supplierID
|
supplierID = a.supplierID
|
||||||
a.locker.RUnlock()
|
a.RUnlock()
|
||||||
if supplierID < 0 {
|
if supplierID < 0 {
|
||||||
a.locker.Lock()
|
a.Lock()
|
||||||
defer a.locker.Unlock()
|
defer a.Unlock()
|
||||||
|
|
||||||
a.supplierID = 0
|
a.supplierID = 0
|
||||||
if shopList, err := a.ShopList(SysStatusAll); err == nil {
|
if shopList, err := a.ShopList(SysStatusAll); err == nil {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ const (
|
|||||||
WaybillStatusSelfDelivery = "18" // 自行配送
|
WaybillStatusSelfDelivery = "18" // 自行配送
|
||||||
WaybillStatusDontDeliver = "19" // 不再配送
|
WaybillStatusDontDeliver = "19" // 不再配送
|
||||||
WaybillStatusDeliveryRejected = "20" // 配送拒单
|
WaybillStatusDeliveryRejected = "20" // 配送拒单
|
||||||
|
WaybillStatusCourierArrived = "21" // 骑士到店
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -66,8 +67,6 @@ const (
|
|||||||
|
|
||||||
OrderUserCancelTypeBeforeSale = 1 // 表示订单完成前用户全单取消申请流程
|
OrderUserCancelTypeBeforeSale = 1 // 表示订单完成前用户全单取消申请流程
|
||||||
OrderUserCancelTypeAfterSale = 2 // 表示订单完成后用户全单退款申请流程
|
OrderUserCancelTypeAfterSale = 2 // 表示订单完成后用户全单退款申请流程
|
||||||
|
|
||||||
SendImmediatelySelf = 6 // 饿百商家自送的配送状态
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -188,31 +187,31 @@ type OrderDetailInfo struct {
|
|||||||
Ext struct {
|
Ext struct {
|
||||||
TaoxiFlag int `json:"taoxi_flag"`
|
TaoxiFlag int `json:"taoxi_flag"`
|
||||||
} `json:"ext"`
|
} `json:"ext"`
|
||||||
FinishedTime string `json:"finished_time"`
|
FinishedTime string `json:"finished_time"`
|
||||||
InvoiceTitle string `json:"invoice_title"`
|
InvoiceTitle string `json:"invoice_title"`
|
||||||
IsColdBoxOrder int `json:"is_cold_box_order"`
|
IsColdBoxOrder int `json:"is_cold_box_order"`
|
||||||
IsPrivate int `json:"is_private"`
|
IsPrivate int `json:"is_private"`
|
||||||
LatestSendTime int `json:"latest_send_time"`
|
LatestSendTime int `json:"latest_send_time"`
|
||||||
MealNum string `json:"meal_num"`
|
MealNum string `json:"meal_num"`
|
||||||
NeedInvoice int `json:"need_invoice"`
|
NeedInvoice int `json:"need_invoice"`
|
||||||
OrderFlag int `json:"order_flag"`
|
OrderFlag int `json:"order_flag"`
|
||||||
OrderFrom string `json:"order_from"`
|
OrderFrom string `json:"order_from"`
|
||||||
OrderID string `json:"order_id"`
|
OrderID string `json:"order_id"`
|
||||||
OrderIndex string `json:"order_index"`
|
OrderIndex string `json:"order_index"`
|
||||||
PackageFee int `json:"package_fee"`
|
PackageFee int `json:"package_fee"`
|
||||||
PayStatus int `json:"pay_status"`
|
PayStatus int `json:"pay_status"`
|
||||||
PayType int `json:"pay_type"`
|
PayType int `json:"pay_type"`
|
||||||
PickupTime int `json:"pickup_time"`
|
PickupTime int `json:"pickup_time"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
ResponsibleParty string `json:"responsible_party"`
|
// ResponsibleParty string `json:"responsible_party"`
|
||||||
SendFee int `json:"send_fee"`
|
SendFee int `json:"send_fee"`
|
||||||
SendImmediately int `json:"send_immediately"`
|
SendImmediately int `json:"send_immediately"`
|
||||||
SendTime int `json:"send_time"`
|
SendTime int `json:"send_time"`
|
||||||
ShopFee int `json:"shop_fee"`
|
ShopFee int `json:"shop_fee"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
TaxerID string `json:"taxer_id"`
|
TaxerID string `json:"taxer_id"`
|
||||||
TotalFee int `json:"total_fee"`
|
TotalFee int `json:"total_fee"`
|
||||||
UserFee int `json:"user_fee"`
|
UserFee int `json:"user_fee"`
|
||||||
} `json:"order"`
|
} `json:"order"`
|
||||||
Products [][]*OrderProductInfo `json:"products"`
|
Products [][]*OrderProductInfo `json:"products"`
|
||||||
Shop *struct {
|
Shop *struct {
|
||||||
@@ -223,8 +222,8 @@ type OrderDetailInfo struct {
|
|||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
User *struct {
|
User *struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
City string `json:"city"`
|
// City string `json:"city"`
|
||||||
Coord *struct {
|
Coord *struct {
|
||||||
Latitude string `json:"latitude"`
|
Latitude string `json:"latitude"`
|
||||||
Longitude string `json:"longitude"`
|
Longitude string `json:"longitude"`
|
||||||
} `json:"coord"`
|
} `json:"coord"`
|
||||||
@@ -232,13 +231,13 @@ type OrderDetailInfo struct {
|
|||||||
Latitude string `json:"latitude"`
|
Latitude string `json:"latitude"`
|
||||||
Longitude string `json:"longitude"`
|
Longitude string `json:"longitude"`
|
||||||
} `json:"coord_amap"`
|
} `json:"coord_amap"`
|
||||||
District string `json:"district"`
|
// District string `json:"district"`
|
||||||
Gender string `json:"gender"`
|
Gender string `json:"gender"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
PrivacyPhone string `json:"privacy_phone"`
|
PrivacyPhone string `json:"privacy_phone"`
|
||||||
Province string `json:"province"`
|
// Province string `json:"province"`
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
} `json:"user"`
|
} `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,18 @@ const (
|
|||||||
DeliveryTypeElmXingHuoZBKA = 18 // 星火众包KA
|
DeliveryTypeElmXingHuoZBKA = 18 // 星火众包KA
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// https://open-be.ele.me/dev/api/doc/v3/#api-Order_Up-order_get
|
||||||
|
const (
|
||||||
|
DeliveryPartyFengNiao = 1 // 蜂鸟
|
||||||
|
DeliveryPartyFengNiaoSelf = 2 // 蜂鸟自配送
|
||||||
|
DeliveryPartyFengNiaoZB = 3 // 蜂鸟众包
|
||||||
|
DeliveryPartyFengElmZB = 4 // 饿了么众包
|
||||||
|
DeliveryPartyFengNiaoPS = 5 // 蜂鸟配送
|
||||||
|
DeliveryPartyFengElmSelf = 6 // 饿了么自配送,商家自送?
|
||||||
|
DeliveryPartyFullCity = 7 // 全城送
|
||||||
|
DeliveryPartyKuaiDiPS = 8 // 快递配送
|
||||||
|
)
|
||||||
|
|
||||||
type ShopInfo struct {
|
type ShopInfo struct {
|
||||||
ShopID string `json:"shop_id"`
|
ShopID string `json:"shop_id"`
|
||||||
BaiduShopID int64 `json:"baidu_shop_id"`
|
BaiduShopID int64 `json:"baidu_shop_id"`
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ func (a *API) ShopCategoryCreate(shopID string, parentID int64, name string, ran
|
|||||||
func (a *API) ShopCategoryGet(shopID string) (cats []*CategoryInfo, err error) {
|
func (a *API) ShopCategoryGet(shopID string) (cats []*CategoryInfo, err error) {
|
||||||
result, err := a.AccessAPI("sku.shop.category.get", utils.Params2Map(KeyShopID, shopID))
|
result, err := a.AccessAPI("sku.shop.category.get", utils.Params2Map(KeyShopID, shopID))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if inMap, ok := result.Data.(map[string]interface{}); ok { // fuck it
|
if inMap, ok := result.Data.(map[string]interface{}); ok {
|
||||||
cats := interface2CatList(inMap["categorys"], 1)
|
cats := interface2CatList(inMap["categorys"], 1)
|
||||||
return cats, nil
|
return cats, nil
|
||||||
}
|
}
|
||||||
@@ -252,11 +252,6 @@ func (a *API) ShopCategoryUpdate(shopID string, categoryID int64, name string, r
|
|||||||
"name": name,
|
"name": name,
|
||||||
"rank": rank,
|
"rank": rank,
|
||||||
})
|
})
|
||||||
if errWithCode, ok := err.(*utils.ErrorWithCode); ok {
|
|
||||||
if errWithCode.Level() == 0 && errWithCode.IntCode() == 1 { //忽略同名错误
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,8 +362,8 @@ func handleShopSkuBatchErr(err error) (opResult *BatchOpResult, outErr error) {
|
|||||||
var data interface{}
|
var data interface{}
|
||||||
if err2 := utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &data); err2 == nil {
|
if err2 := utils.UnmarshalUseNumber([]byte(errExt.ErrMsg()), &data); err2 == nil {
|
||||||
if err2 = utils.Map2StructByJson(data, &opResult, true); err2 == nil {
|
if err2 = utils.Map2StructByJson(data, &opResult, true); err2 == nil {
|
||||||
// 将以\u表示的字符串标准化
|
// 将以\u表示的字符串标准化,并去掉成功的
|
||||||
errExt.SetErrMsg(string(utils.MustMarshal(opResult)))
|
errExt.SetErrMsg(string(utils.MustMarshal(opResult.FailedList)))
|
||||||
outErr = errExt
|
outErr = errExt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func TestShopCategoryCreate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestShopCategoryGet(t *testing.T) {
|
func TestShopCategoryGet(t *testing.T) {
|
||||||
result, err := api.ShopCategoryGet("102493")
|
result, err := api.ShopCategoryGet("300034")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else {
|
} else {
|
||||||
@@ -69,7 +69,7 @@ func TestSkuUploadRTF(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSkuCreate(t *testing.T) {
|
func TestSkuCreate(t *testing.T) {
|
||||||
result, err := api.SkuCreate(testShopID, 17, map[string]interface{}{
|
result, err := api.SkuCreate("", testShopID, 17, map[string]interface{}{
|
||||||
"name": "测试商品",
|
"name": "测试商品",
|
||||||
"status": SkuStatusOnline,
|
"status": SkuStatusOnline,
|
||||||
"left_num": MaxLeftNum,
|
"left_num": MaxLeftNum,
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ type PageListInnerShopInfo struct {
|
|||||||
ShopLabels string `json:"shop_labels"`
|
ShopLabels string `json:"shop_labels"`
|
||||||
ShopName string `json:"shop_name"`
|
ShopName string `json:"shop_name"`
|
||||||
TakeoutCost float64 `json:"takeout_cost"`
|
TakeoutCost float64 `json:"takeout_cost"`
|
||||||
TakeoutPrice int `json:"takeout_price"`
|
TakeoutPrice float64 `json:"takeout_price"`
|
||||||
Type interface{} `json:"type"`
|
Type interface{} `json:"type"`
|
||||||
WelfareInfo []struct {
|
WelfareInfo []struct {
|
||||||
IconColor struct {
|
IconColor struct {
|
||||||
@@ -263,39 +263,44 @@ type PageShopInfo struct {
|
|||||||
Tag []interface{} `json:"tag"`
|
Tag []interface{} `json:"tag"`
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
} `json:"delivery_mode"`
|
} `json:"delivery_mode"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
DisplayRefundLabel int `json:"display_refund_label"`
|
DisplayRefundLabel int `json:"display_refund_label"`
|
||||||
Distance int `json:"distance"`
|
Distance int `json:"distance"`
|
||||||
EleBusinessState int `json:"ele_business_state"`
|
EleBusinessState int `json:"ele_business_state"`
|
||||||
EleID string `json:"ele_id"`
|
EleID string `json:"ele_id"`
|
||||||
FirstOpenTime *BussinessTimeInfo `json:"first_open_time"`
|
FirstOpenTime *BussinessTimeInfo `json:"first_open_time"`
|
||||||
HitGod int `json:"hit_god"`
|
HitGod int `json:"hit_god"`
|
||||||
ImagePath string `json:"image_path"`
|
ImagePath string `json:"image_path"`
|
||||||
IsColdChain int `json:"is_cold_chain"`
|
IsColdChain int `json:"is_cold_chain"`
|
||||||
IsDoubleTwelve int `json:"is_double_twelve"`
|
IsDoubleTwelve int `json:"is_double_twelve"`
|
||||||
IsMedicineShop int `json:"is_medicine_shop"`
|
IsMedicineShop int `json:"is_medicine_shop"`
|
||||||
IsOwnTheme int `json:"is_own_theme"`
|
IsOwnTheme int `json:"is_own_theme"`
|
||||||
Latitude float64 `json:"latitude"`
|
Latitude float64 `json:"latitude"`
|
||||||
Longitude float64 `json:"longitude"`
|
Longitude float64 `json:"longitude"`
|
||||||
MedicineQualification []interface{} `json:"medicine_qualification"`
|
MedicineQualification []*struct {
|
||||||
Name string `json:"name"`
|
AptitudeName string `json:"aptitude_name"`
|
||||||
NewStyle bool `json:"new_style"`
|
AptitudePhoto []string `json:"aptitude_photo"`
|
||||||
OTakoutCost int `json:"o_takout_cost"`
|
AptitudeType string `json:"aptitude_type"`
|
||||||
OTakoutPrice int `json:"o_takout_price"`
|
LicenseNumber string `json:"license_number"`
|
||||||
OrderLeadTime interface{} `json:"order_lead_time"`
|
} `json:"medicine_qualification"`
|
||||||
Phone string `json:"phone"`
|
Name string `json:"name"`
|
||||||
PromotionInfo string `json:"promotion_info"`
|
NewStyle bool `json:"new_style"`
|
||||||
Qualification string `json:"qualification"`
|
OTakoutCost int `json:"o_takout_cost"`
|
||||||
RecentOrderNum int `json:"recent_order_num"`
|
OTakoutPrice int `json:"o_takout_price"`
|
||||||
ShopID string `json:"shop_id"`
|
OrderLeadTime interface{} `json:"order_lead_time"`
|
||||||
ShopScore float64 `json:"shop_score"`
|
Phone string `json:"phone"`
|
||||||
ShopSourceFrom int `json:"shop_source_from"`
|
PromotionInfo string `json:"promotion_info"`
|
||||||
SkuCount int `json:"sku_count"`
|
Qualification string `json:"qualification"`
|
||||||
TakeoutCost int `json:"takeout_cost"`
|
RecentOrderNum int `json:"recent_order_num"`
|
||||||
TakeoutInvoice int `json:"takeout_invoice"`
|
ShopID string `json:"shop_id"`
|
||||||
TakeoutInvoiceMinPrice string `json:"takeout_invoice_min_price"`
|
ShopScore float64 `json:"shop_score"`
|
||||||
TakeoutOpenTime string `json:"takeout_open_time"`
|
ShopSourceFrom int `json:"shop_source_from"`
|
||||||
TakeoutPrice int `json:"takeout_price"`
|
SkuCount int `json:"sku_count"`
|
||||||
|
TakeoutCost float64 `json:"takeout_cost"`
|
||||||
|
TakeoutInvoice float64 `json:"takeout_invoice"`
|
||||||
|
TakeoutInvoiceMinPrice string `json:"takeout_invoice_min_price"`
|
||||||
|
TakeoutOpenTime string `json:"takeout_open_time"`
|
||||||
|
TakeoutPrice float64 `json:"takeout_price"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) AccessStorePage2(subURL string, params map[string]interface{}, isPost bool, cookies map[string]string) (retVal map[string]interface{}, err error) {
|
func (a *API) AccessStorePage2(subURL string, params map[string]interface{}, isPost bool, cookies map[string]string) (retVal map[string]interface{}, err error) {
|
||||||
@@ -515,22 +520,45 @@ func (a *API) PageGetCustomCatList(baiduShopID int64) (catList []map[string]inte
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) GetStoreList(lng string, lat string) (retVal map[string]interface{}, err error) {
|
func (a *API) GetStoreList(lng string, lat string, pageNo, pageSize int) (shopListInfo *PageListInfo, err error) {
|
||||||
|
if pageNo <= 0 {
|
||||||
|
pageNo = 1
|
||||||
|
}
|
||||||
|
if pageSize > 20 || pageSize <= 0 {
|
||||||
|
pageSize = 20
|
||||||
|
}
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"channel": "kitchen",
|
"channel": "kitchen",
|
||||||
"pn": 1,
|
"rn": pageSize,
|
||||||
"rn": 999,
|
"pn": pageNo,
|
||||||
"lng": lng,
|
"lng": lng,
|
||||||
"lat": lat,
|
"lat": lat,
|
||||||
}
|
}
|
||||||
retVal, err = a.AccessStorePageNoCookie("/newretail/main/shoplist", params)
|
result, err := a.AccessStorePageNoCookie("newretail/main/shoplist", params)
|
||||||
return retVal, err
|
if err == nil && result != nil {
|
||||||
|
err = utils.Map2StructByJson(result, &shopListInfo, true)
|
||||||
|
}
|
||||||
|
return shopListInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) GetStoreList2(lng float64, lat float64) (shopListInfo *PageListInfo, err error) {
|
func (a *API) GetStoreList2(lng float64, lat float64) (shopListInfo *PageListInfo, err error) {
|
||||||
retVal, err := a.GetStoreList(fmt.Sprintf("%.6f", lng), fmt.Sprintf("%.6f", lat))
|
pageSize := 20
|
||||||
if err == nil {
|
pageNo := 1
|
||||||
err = utils.Map2StructByJson(retVal, &shopListInfo, true)
|
for {
|
||||||
|
retVal, err2 := a.GetStoreList(fmt.Sprintf("%.6f", lng), fmt.Sprintf("%.6f", lat), pageNo, pageSize)
|
||||||
|
if err = err2; err == nil {
|
||||||
|
if shopListInfo == nil {
|
||||||
|
shopListInfo = retVal
|
||||||
|
} else {
|
||||||
|
shopListInfo.ShopList = append(shopListInfo.ShopList, retVal.ShopList...)
|
||||||
|
}
|
||||||
|
if len(retVal.ShopList) < pageSize {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
pageNo++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return shopListInfo, err
|
return shopListInfo, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func TestGetShopHealthByDetail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetStoreList(t *testing.T) {
|
func TestGetStoreList(t *testing.T) {
|
||||||
result, err := api.GetStoreList("104.057218", "30.6949")
|
result, err := api.GetStoreList("104.057218", "30.6949", 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ func TestGetStoreList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetStoreList2(t *testing.T) {
|
func TestGetStoreList2(t *testing.T) {
|
||||||
result, err := api.GetStoreList2(120.074911, 29.306863)
|
result, err := api.GetStoreList2(104.010554, 30.637072)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package jdapi
|
package jdapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi"
|
"git.rosy.net.cn/baseapi"
|
||||||
|
|
||||||
@@ -66,9 +66,6 @@ type API struct {
|
|||||||
appSecret string
|
appSecret string
|
||||||
client *http.Client
|
client *http.Client
|
||||||
config *platformapi.APIConfig
|
config *platformapi.APIConfig
|
||||||
|
|
||||||
locker sync.RWMutex
|
|
||||||
storeCookie string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -105,7 +102,8 @@ var (
|
|||||||
KeyOutStationNo,
|
KeyOutStationNo,
|
||||||
KeyStationNo,
|
KeyStationNo,
|
||||||
"StoreNo",
|
"StoreNo",
|
||||||
"outSkuId",
|
KeyOutSkuId,
|
||||||
|
KeySkuId,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -120,13 +118,14 @@ func (a *API) signParams(jdParams map[string]interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
allStr := a.appSecret
|
buf := &bytes.Buffer{}
|
||||||
|
buf.WriteString(a.appSecret)
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
allStr += k + fmt.Sprint(jdParams[k])
|
buf.WriteString(k)
|
||||||
|
buf.WriteString(fmt.Sprint(jdParams[k]))
|
||||||
}
|
}
|
||||||
allStr = allStr + a.appSecret
|
buf.WriteString(a.appSecret)
|
||||||
|
return fmt.Sprintf("%X", md5.Sum(buf.Bytes()))
|
||||||
return fmt.Sprintf("%X", md5.Sum([]byte(allStr)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(token, appKey, appSecret string, config ...*platformapi.APIConfig) *API {
|
func New(token, appKey, appSecret string, config ...*platformapi.APIConfig) *API {
|
||||||
@@ -143,6 +142,13 @@ func New(token, appKey, appSecret string, config ...*platformapi.APIConfig) *API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPageOnly(cookie string, config ...*platformapi.APIConfig) *API {
|
||||||
|
api := New("", "", "", config...)
|
||||||
|
api.SetCookie(accessStorePageCookieName, cookie)
|
||||||
|
api.SetCookie(accessStorePageCookieName2, cookie)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) AccessAPI2(apiStr string, jdParams map[string]interface{}, traceInfo string) (retVal map[string]interface{}, err error) {
|
func (a *API) AccessAPI2(apiStr string, jdParams map[string]interface{}, traceInfo string) (retVal map[string]interface{}, err error) {
|
||||||
params := make(map[string]interface{})
|
params := make(map[string]interface{})
|
||||||
params["v"] = "1.0"
|
params["v"] = "1.0"
|
||||||
@@ -267,59 +273,60 @@ func (a *API) AccessAPINoPage2(apiStr string, jdParams map[string]interface{}, k
|
|||||||
func (a *API) AccessAPINoPage(apiStr string, jdParams map[string]interface{}, keyToRemove, keyToKeep []string, resultParser func(data map[string]interface{}) (interface{}, error)) (interface{}, error) {
|
func (a *API) AccessAPINoPage(apiStr string, jdParams map[string]interface{}, keyToRemove, keyToKeep []string, resultParser func(data map[string]interface{}) (interface{}, error)) (interface{}, error) {
|
||||||
return a.AccessAPINoPage2(apiStr, jdParams, keyToRemove, keyToKeep, resultParser, "")
|
return a.AccessAPINoPage2(apiStr, jdParams, keyToRemove, keyToKeep, resultParser, "")
|
||||||
}
|
}
|
||||||
|
func genNormalHavePageResultParser(dataKey string) (handler PageResultParser) {
|
||||||
|
return func(data map[string]interface{}, totalCount int) ([]interface{}, int, error) {
|
||||||
|
var result map[string]interface{}
|
||||||
|
var retVal []interface{}
|
||||||
|
|
||||||
func normalHavePageResultParser(data map[string]interface{}, totalCount int) ([]interface{}, int, error) {
|
tempResult := data[dataKey]
|
||||||
var result map[string]interface{}
|
if resultStr, ok := tempResult.(string); ok {
|
||||||
var retVal []interface{}
|
if err := utils.UnmarshalUseNumber([]byte(resultStr), &tempResult); err != nil {
|
||||||
|
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
||||||
tempResult := data["result"]
|
|
||||||
if resultStr, ok := tempResult.(string); ok {
|
|
||||||
if err := utils.UnmarshalUseNumber([]byte(resultStr), &tempResult); err != nil {
|
|
||||||
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = tempResult.(map[string]interface{})
|
|
||||||
|
|
||||||
if totalCount == 0 {
|
|
||||||
for _, totalCountKey := range havePageTotalCountKeys {
|
|
||||||
if totalCount2, ok := result[totalCountKey]; ok {
|
|
||||||
totalCountInt64, _ := totalCount2.(json.Number).Int64()
|
|
||||||
totalCount = int(totalCountInt64)
|
|
||||||
if totalCount == 0 {
|
|
||||||
return make([]interface{}, 0), 0, nil
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = tempResult.(map[string]interface{})
|
||||||
|
|
||||||
if totalCount == 0 {
|
if totalCount == 0 {
|
||||||
baseapi.SugarLogger.Errorf("can not find totalCount key, data:%v", result)
|
for _, totalCountKey := range havePageTotalCountKeys {
|
||||||
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
if totalCount2, ok := result[totalCountKey]; ok {
|
||||||
}
|
totalCountInt64, _ := totalCount2.(json.Number).Int64()
|
||||||
}
|
totalCount = int(totalCountInt64)
|
||||||
|
if totalCount == 0 {
|
||||||
for _, inner2ResultKey := range havePageInner2DataKeys {
|
return make([]interface{}, 0), 0, nil
|
||||||
if inner2Result, ok := result[inner2ResultKey]; ok {
|
}
|
||||||
if inner2Result == nil {
|
break
|
||||||
retVal = nil
|
|
||||||
} else if inner2ResultStr, ok := inner2Result.(string); ok {
|
|
||||||
err := utils.UnmarshalUseNumber([]byte(inner2ResultStr), &retVal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
retVal = inner2Result.([]interface{})
|
|
||||||
}
|
}
|
||||||
return retVal, totalCount, nil
|
if totalCount == 0 {
|
||||||
|
baseapi.SugarLogger.Errorf("can not find totalCount key, data:%v", result)
|
||||||
|
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, inner2ResultKey := range havePageInner2DataKeys {
|
||||||
|
if inner2Result, ok := result[inner2ResultKey]; ok {
|
||||||
|
if inner2Result == nil {
|
||||||
|
retVal = nil
|
||||||
|
} else if inner2ResultStr, ok := inner2Result.(string); ok {
|
||||||
|
err := utils.UnmarshalUseNumber([]byte(inner2ResultStr), &retVal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retVal = inner2Result.([]interface{})
|
||||||
|
}
|
||||||
|
return retVal, totalCount, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baseapi.SugarLogger.Errorf("can not find result key, data:%v", result)
|
||||||
|
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
||||||
}
|
}
|
||||||
baseapi.SugarLogger.Errorf("can not find result key, data:%v", result)
|
|
||||||
return nil, 0, platformapi.ErrResponseDataFormatWrong
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) AccessAPIHavePage(apiStr string, jdParams map[string]interface{}, keyToRemove, keyToKeep []string, pageResultParser PageResultParser) ([]interface{}, int, error) {
|
func (a *API) AccessAPIHavePage(apiStr string, jdParams map[string]interface{}, keyToRemove, keyToKeep []string, pageResultParser PageResultParser) ([]interface{}, int, error) {
|
||||||
if pageResultParser == nil {
|
if pageResultParser == nil {
|
||||||
pageResultParser = normalHavePageResultParser
|
pageResultParser = genNormalHavePageResultParser("result")
|
||||||
}
|
}
|
||||||
|
|
||||||
localJdParams := make(map[string]interface{})
|
localJdParams := make(map[string]interface{})
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ func init() {
|
|||||||
// sandbox
|
// sandbox
|
||||||
api = New("df97f334-f7d8-4b36-9664-5784d8ae0baf", "06692746f7224695ad4788ce340bc854", "d6b42a35a7414a5490d811654d745c84")
|
api = New("df97f334-f7d8-4b36-9664-5784d8ae0baf", "06692746f7224695ad4788ce340bc854", "d6b42a35a7414a5490d811654d745c84")
|
||||||
// prod
|
// prod
|
||||||
// api = New("ccb10daf-e6f5-4a58-ada5-b97f9073a137", "1dba76d40cac446ca500c0391a0b6c9d", "a88d031a1e7b462cb1579f12e97fe7f4")
|
// api = New("77e703b7-7997-441b-a12a-2e522efb117a", "1dba76d40cac446ca500c0391a0b6c9d", "a88d031a1e7b462cb1579f12e97fe7f4")
|
||||||
// 天天果园
|
// 天天果园
|
||||||
// api = New("84541069-fbe2-424b-b625-9b2ba1d4c9e6", "5d5577a2506f41b8b4ec520ba83490f5", "0b01b9eeb15b41dab1c3d05d95c17a26")
|
// api = New("84541069-fbe2-424b-b625-9b2ba1d4c9e6", "5d5577a2506f41b8b4ec520ba83490f5", "0b01b9eeb15b41dab1c3d05d95c17a26")
|
||||||
|
|
||||||
const cookieValue = "YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHDYZP7PPVMRGO4VWG2JRBMKFTOGIWZ5L2XHXC3SXQ4OLX7EL4RKUPZQT6GOH63KE3EVK37L5LG7TGSDGXFQP4377YK72UB5YZG6IJH6PY25YLLCJYPMDSHKPGYBUFJ4MMMKGN6MWB37CP7XVDBBZJ3U462ENTEXH744AWCQCIG2AAE2PKYVHC"
|
const cookieValue = "YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHCT3RM3CQG7IJIPUQ3THS5UIUYWMKINM7ETUOQB7OBPOPZVCT3ZJY55243TDVXLO25PP4UYSPTTPMNQ7HPMWOJKJ3BJWGVHD243MXH7NZWW264TKN5UOCJBSSSOKD2QQII"
|
||||||
api.SetCookie(accessStorePageCookieName, cookieValue)
|
api.SetCookie(accessStorePageCookieName, cookieValue)
|
||||||
api.SetCookie(accessStorePageCookieName2, cookieValue)
|
api.SetCookie(accessStorePageCookieName2, cookieValue)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,11 +37,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FreightDiscountTypeByShop = 8 // 8:商家满免运费
|
FreightDiscountTypeByShop = 8 // 8:商家满免运费
|
||||||
FreightDiscountTypeByVip = 7 // 7:VIP免运费
|
FreightDiscountTypeByVip = 7 // 7:VIP免运费
|
||||||
FreightDiscountTypeByActivity = 12 // 12:首单地推满免运费
|
FreightDiscountTypeByActivity = 12 // 12:首单地推满免运费
|
||||||
FreightDiscountTypeByCoupons = 15 // 15:运费券
|
FreightDiscountTypeByCoupons = 15 // 15:运费券
|
||||||
SelfDeliveryCarrierNo = "2938" // 京东配送方式=商家自送
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -59,16 +58,17 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AfsReasonTypeGoodsQuality = 201 // 商品质量问题/做工粗糙/有瑕疵
|
AfsReasonTypeGoodsQuality = 201 // 商品质量问题
|
||||||
AfsReasonTypeWrongGoods = 202 // 发错货
|
AfsReasonTypeWrongGoods = 202 // 送错货
|
||||||
AfsReasonTypeMissingGoods = 203 // 部分商品未收到
|
AfsReasonTypeMissingGoods = 203 // 缺件少件
|
||||||
AfsReasonTypeNoGoods = 501 // 全部商品未收到
|
AfsReasonTypeNoGoods = 501 // 全部商品未收到
|
||||||
AfsReasonTypeDamagedGoods = 208 // 外表损伤(压坏,磕坏等)
|
AfsReasonTypeDamagedGoods = 208 // 包装脏污有破损
|
||||||
AfsReasonTypeGoodsQuantity = 207 // 缺斤少两
|
AfsReasonTypeGoodsQuantity = 207 // 缺斤少两
|
||||||
AfsReasonTypeAgreedByMerchant = 209 // 与商家协商一致
|
// AfsReasonTypeAgreedByMerchant = 209 // 与商家协商一致,2019/09/01取消
|
||||||
|
AfsReasonTypeGoodsAbsent = 210 // 商家通知我缺货
|
||||||
AfsReasonTypeGoodsSizeNoSame = 302 // 大小尺寸与商品描述不符
|
AfsReasonTypeGoodsSizeNoSame = 302 // 大小尺寸与商品描述不符
|
||||||
AfsReasonTypeGoodsColorNoSame = 303 // 颜色/款式/图案与描述不符
|
AfsReasonTypeGoodsColorNoSame = 303 // 实物与原图不符
|
||||||
AfsReasonWrongPurchase = 402 // 误购
|
AfsReasonWrongPurchase = 402 // 不想要了
|
||||||
AfsReasonNotReceivedIntime = 502 // 未在时效内送达
|
AfsReasonNotReceivedIntime = 502 // 未在时效内送达
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -310,6 +310,48 @@ type OrderInfo struct {
|
|||||||
Yn bool `json:"yn"`
|
Yn bool `json:"yn"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrderQueryParam struct {
|
||||||
|
PageNo int64 `json:"pageNo,omitempty"` // 当前页数,默认:1
|
||||||
|
PageSize int `json:"pageSize,omitempty"` // 每页条数,默认:20,最大值100
|
||||||
|
OrderID int64 `json:"orderId,omitempty"`
|
||||||
|
|
||||||
|
OrderPurchaseTimeBegin string `json:"orderPurchaseTime_begin,omitempty"` // 购买成交时间-支付(开始)
|
||||||
|
OrderPurchaseTimeEnd string `json:"orderPurchaseTime_end,omitempty"` // 购买成交时间-支付(结束)
|
||||||
|
OrderStatus int `json:"orderStatus,omitempty"`
|
||||||
|
|
||||||
|
DeliveryStationNo string `json:"deliveryStationNo,omitempty"` // 到家门店编码
|
||||||
|
DeliveryStationNoIsv string `json:"deliveryStationNoIsv,omitempty"` // 商家门店编码
|
||||||
|
}
|
||||||
|
|
||||||
|
type SonTag struct {
|
||||||
|
MqProcessTime string `json:"mqProcessTime"`
|
||||||
|
OperTime string `json:"operTime"`
|
||||||
|
TagCode int `json:"tagCode"`
|
||||||
|
CodeName string `json:"codeName"`
|
||||||
|
OperPin string `json:"operPin"`
|
||||||
|
OperName int `json:"operName"`
|
||||||
|
MsgContent string `json:"msgContent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderTrack struct {
|
||||||
|
SonTagList []*SonTag `json:"sonTagList"`
|
||||||
|
IsThirdCarry int `json:"isThirdCarry"`
|
||||||
|
OperFrom string `json:"operFrom"`
|
||||||
|
MqProcessTime string `json:"mqProcessTime"`
|
||||||
|
TagIcon string `json:"tagIcon"`
|
||||||
|
OperTime string `json:"operTime"`
|
||||||
|
ThirdCarry int `json:"thirdCarry"`
|
||||||
|
TagTitle string `json:"tagTitle"`
|
||||||
|
CodeName string `json:"codeName"`
|
||||||
|
TagCode int `json:"tagCode"`
|
||||||
|
OperPin string `json:"operPin"`
|
||||||
|
OperName string `json:"operName"`
|
||||||
|
Care bool `json:"care"`
|
||||||
|
MsgContent string `json:"msgContent"`
|
||||||
|
MsgContentApp string `json:"msgContentApp"`
|
||||||
|
DoNotCareReason string `json:"doNotCareReason"`
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrCanNotFindOrder = errors.New("can not find order")
|
ErrCanNotFindOrder = errors.New("can not find order")
|
||||||
)
|
)
|
||||||
@@ -336,14 +378,6 @@ func (a *API) OrderQuery(jdParams map[string]interface{}) (retVal []interface{},
|
|||||||
return retVal, totalCount, err
|
return retVal, totalCount, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) OrderQuery2(jdParams map[string]interface{}) (retVal []*OrderInfo, totalCount int, err error) {
|
|
||||||
orderList, totalCount, err := a.OrderQuery(jdParams)
|
|
||||||
if err == nil {
|
|
||||||
err = utils.Map2StructByJson(orderList, &retVal, true)
|
|
||||||
}
|
|
||||||
return retVal, totalCount, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// orderFreightMoney 基础运费
|
// orderFreightMoney 基础运费
|
||||||
// tips 商家承担小费
|
// tips 商家承担小费
|
||||||
// merchantPaymentDistanceFreightMoney 取件服务费(开票)(正向单展示远距离运费;售后单则展示达达售后运费)
|
// merchantPaymentDistanceFreightMoney 取件服务费(开票)(正向单展示远距离运费;售后单则展示达达售后运费)
|
||||||
@@ -361,6 +395,28 @@ func (a *API) QuerySingleOrder(orderId string) (map[string]interface{}, error) {
|
|||||||
return result[0].(map[string]interface{}), nil
|
return result[0].(map[string]interface{}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) OrderQuery2(queryParam *OrderQueryParam) (retVal []*OrderInfo, totalCount int, err error) {
|
||||||
|
orderList, totalCount, err := a.OrderQuery(utils.Struct2MapByJson(queryParam))
|
||||||
|
if err == nil {
|
||||||
|
err = utils.Map2StructByJson(orderList, &retVal, true)
|
||||||
|
}
|
||||||
|
return retVal, totalCount, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) QuerySingleOrder2(orderID string) (orderInfo *OrderInfo, err error) {
|
||||||
|
orderList, _, err := a.OrderQuery2(&OrderQueryParam{
|
||||||
|
OrderID: utils.Str2Int64(orderID),
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
if len(orderList) > 0 {
|
||||||
|
orderInfo = orderList[0]
|
||||||
|
} else {
|
||||||
|
err = ErrCanNotFindOrder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return orderInfo, err
|
||||||
|
}
|
||||||
|
|
||||||
// 商家确认接单接口
|
// 商家确认接单接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=169&apiid=c1a15129d1374e9da7fa35487f878604
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=169&apiid=c1a15129d1374e9da7fa35487f878604
|
||||||
func (a *API) OrderAcceptOperate(orderId string, isAgreed bool, userName string) error {
|
func (a *API) OrderAcceptOperate(orderId string, isAgreed bool, userName string) error {
|
||||||
@@ -588,6 +644,7 @@ func (a *API) AfsSubmit(OrderID, pin, questionTypeCode, questionDesc, questionPi
|
|||||||
"orderId": OrderID,
|
"orderId": OrderID,
|
||||||
"pin": utils.GetAPIOperator(pin),
|
"pin": utils.GetAPIOperator(pin),
|
||||||
"questionTypeCode": questionTypeCode,
|
"questionTypeCode": questionTypeCode,
|
||||||
|
"skuList": skuList,
|
||||||
}
|
}
|
||||||
if questionDesc != "" {
|
if questionDesc != "" {
|
||||||
jdParams["questionDesc"] = questionDesc
|
jdParams["questionDesc"] = questionDesc
|
||||||
@@ -624,13 +681,53 @@ func ProcessQuestionPic(questionPic string) (outQuestionPic string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 订单商家加小费接口
|
// 订单商家加小费接口
|
||||||
|
// tips必须是100的倍数,另外必须要等到家下发运单后才能调用,否则会报“订单号srcOrderNo的订单不存在”错
|
||||||
|
// 这个tips是累计增的,比如第一次调用tips为100,再一次调用tips为200,则总共的tips就是300
|
||||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=ed9e3ca7325c4d4d8ceaf959ed0e7a62
|
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=ed9e3ca7325c4d4d8ceaf959ed0e7a62
|
||||||
func (a *API) OrderAddTips(OrderID string, tips int, pin string) (err error) {
|
func (a *API) OrderAddTips(orderID string, tips int, operator string) (err error) {
|
||||||
jdParams := map[string]interface{}{
|
jdParams := map[string]interface{}{
|
||||||
"orderId": OrderID,
|
"orderId": orderID,
|
||||||
"tips": tips,
|
"tips": tips,
|
||||||
"pin": utils.GetAPIOperator(pin),
|
"operator": utils.GetAPIOperator(operator),
|
||||||
}
|
}
|
||||||
_, err = a.AccessAPINoPage("order/addTips", jdParams, nil, nil, nullResultParser)
|
_, err = a.AccessAPINoPage("order/addTips", jdParams, nil, nil, nullResultParser)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据订单号查询订单跟踪接口
|
||||||
|
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=d9d4fd73fba14fd8851a4c054d2ee42e
|
||||||
|
func (a *API) GetByOrderNoForOaos(orderNo string) (orderTrackList []*OrderTrack, err error) {
|
||||||
|
jdParams := map[string]interface{}{
|
||||||
|
"orderNo": orderNo,
|
||||||
|
}
|
||||||
|
result, err := a.AccessAPINoPage("orderTrace/getByOrderNoForOaos", jdParams, nil, nil, genNoPageResultParser("code", "msg", "orderTrackList", "0"))
|
||||||
|
if err == nil {
|
||||||
|
err = utils.Map2StructByJson(result, &orderTrackList, false)
|
||||||
|
}
|
||||||
|
return orderTrackList, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新版根据订单号查询订单跟踪接口
|
||||||
|
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=6450cd91dd5b4dc0bb6a6cd17af6d0a4
|
||||||
|
func (a *API) GetByOrderNoForOaosNew(orderID string) (orderTrackList []*OrderTrack, err error) {
|
||||||
|
jdParams := map[string]interface{}{
|
||||||
|
"orderId": orderID,
|
||||||
|
}
|
||||||
|
result, err := a.AccessAPINoPage("orderTrace/getByOrderNoForOaosNew", jdParams, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
|
||||||
|
if err == nil {
|
||||||
|
err = utils.Map2StructByJson(result.(map[string]interface{})["orderTrackList"], &orderTrackList, false)
|
||||||
|
}
|
||||||
|
return orderTrackList, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订单自提码核验接口
|
||||||
|
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=428fa2cb66784b64a85db36ec2972ff9
|
||||||
|
func (a *API) CheckSelfPickCode(selfPickCode, orderID, operPin string) (err error) {
|
||||||
|
jdParams := map[string]interface{}{
|
||||||
|
"selfPickCode": selfPickCode,
|
||||||
|
"orderId": orderID,
|
||||||
|
"operPin": operPin,
|
||||||
|
}
|
||||||
|
_, err = a.AccessAPINoPage("ocs/checkSelfPickCode", jdParams, nil, nil, nullResultParser)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestQuerySingleOrder(t *testing.T) {
|
func TestQuerySingleOrder(t *testing.T) {
|
||||||
retVal, err := api.QuerySingleOrder("815536199000222")
|
retVal, err := api.QuerySingleOrder("921160248000222")
|
||||||
|
t.Log(utils.Format4Output(retVal, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@@ -218,3 +219,43 @@ func TestOrderShoudSettlementService2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
sugarLogger.Debug(utils.Format4Output(result, false))
|
sugarLogger.Debug(utils.Format4Output(result, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOrderAddTips(t *testing.T) {
|
||||||
|
err := api.OrderAddTips("918092290000042", 50, "xjh")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderQuery2(t *testing.T) {
|
||||||
|
orderList, _, err := api.OrderQuery2(&OrderQueryParam{
|
||||||
|
OrderID: 918092290000042,
|
||||||
|
})
|
||||||
|
t.Log(utils.Format4Output(orderList, false))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetByOrderNoForOaos(t *testing.T) {
|
||||||
|
orderList, err := api.GetByOrderNoForOaos("921235438000341")
|
||||||
|
t.Log(utils.Format4Output(orderList, false))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetByOrderNoForOaosNew(t *testing.T) {
|
||||||
|
orderList, err := api.GetByOrderNoForOaosNew("921235438000341")
|
||||||
|
t.Log(utils.Format4Output(orderList, false))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckSelfPickCode(t *testing.T) {
|
||||||
|
err := api.CheckSelfPickCode("020606", "921235438000341", "test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -106,3 +106,18 @@ func (a *API) QueryPromotionInfo(promotionInfoId int64) (promotionInfo *Promotio
|
|||||||
}
|
}
|
||||||
return promotionInfo, err
|
return promotionInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据到家商品ID查询单品级优惠活动列表接口
|
||||||
|
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=196&apiid=d73baba02c484109a3c3c1b1236ca13d
|
||||||
|
func (a *API) QueryPromotionSku(promotionType int, skuID int64, promotionState int /*, pageNo int64, pageSize int*/) (skuResultList []*PromotionLspQuerySkuResult, err error) {
|
||||||
|
jdParams := map[string]interface{}{
|
||||||
|
"promotionType": promotionType,
|
||||||
|
"skuId": skuID,
|
||||||
|
"promotionState": promotionState,
|
||||||
|
}
|
||||||
|
result, _, err := a.AccessAPIHavePage("singlePromote/queryPromotionSku", jdParams, nil, nil, genNormalHavePageResultParser("data"))
|
||||||
|
if err != nil {
|
||||||
|
err = utils.Map2StructByJson(result, &skuResultList, false)
|
||||||
|
}
|
||||||
|
return skuResultList, err
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,3 +21,24 @@ func TestQueryPromotionInfo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log(utils.Format4Output(result, false))
|
t.Log(utils.Format4Output(result, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQueryPromotionSku(t *testing.T) {
|
||||||
|
skuIDs := []int64{
|
||||||
|
2023335105,
|
||||||
|
// 2023335104,
|
||||||
|
// 2023335088,
|
||||||
|
// 2023335057,
|
||||||
|
// 2023335098,
|
||||||
|
// 2023335020,
|
||||||
|
}
|
||||||
|
for _, skuID := range skuIDs {
|
||||||
|
list, err := api.QueryPromotionSku(PromotionTypeDirectDown, skuID, PromotionStateConfirmed)
|
||||||
|
t.Log(utils.Format4Output(list, false))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// for _, v := range list {
|
||||||
|
// CancelPromotionSkuSingle()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,3 +76,70 @@ func TestCreatePromotionSkuLimitTime(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCancelPromotion(t *testing.T) {
|
||||||
|
promotionIDs := []int64{
|
||||||
|
24636389,
|
||||||
|
24753178,
|
||||||
|
24754087,
|
||||||
|
24970355,
|
||||||
|
24970383,
|
||||||
|
24970389,
|
||||||
|
25439508,
|
||||||
|
25444342,
|
||||||
|
25869363,
|
||||||
|
25871946,
|
||||||
|
26291079,
|
||||||
|
27036663,
|
||||||
|
27407558,
|
||||||
|
27407649,
|
||||||
|
27424152,
|
||||||
|
27424181,
|
||||||
|
27424247,
|
||||||
|
27424568,
|
||||||
|
27508490,
|
||||||
|
27555133,
|
||||||
|
27674289,
|
||||||
|
30969372,
|
||||||
|
41809699,
|
||||||
|
41810076,
|
||||||
|
41810296,
|
||||||
|
41811111,
|
||||||
|
44179379,
|
||||||
|
54080816,
|
||||||
|
54080829,
|
||||||
|
54080842,
|
||||||
|
55346987,
|
||||||
|
55347123,
|
||||||
|
55347340,
|
||||||
|
55348499,
|
||||||
|
55348706,
|
||||||
|
55348999,
|
||||||
|
55349177,
|
||||||
|
56723852,
|
||||||
|
56724283,
|
||||||
|
56725840,
|
||||||
|
56725955,
|
||||||
|
56726053,
|
||||||
|
60713479,
|
||||||
|
60714768,
|
||||||
|
60719242,
|
||||||
|
68818338,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range promotionIDs {
|
||||||
|
promotionInfo, err := api.QueryPromotionInfo(v)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// t.Log(promotionInfo.PromotionType)
|
||||||
|
if promotionInfo.PromotionType == PromotionTypeLimitedTime {
|
||||||
|
err = api.CancelPromotionLimitTime(v, "", utils.GetUUID())
|
||||||
|
} else {
|
||||||
|
err = api.CancelPromotionSingle(v, "", utils.GetUUID())
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
package jdapi
|
package jdapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -65,12 +63,14 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
MaxBatchSize4BatchUpdateOutSkuId = 50
|
MaxBatchSize4BatchUpdateOutSkuId = 50
|
||||||
|
MaxPageSize4QuerySku = 50
|
||||||
|
MaxSkuIDsCount4QueryListBySkuIds = 25
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SkuFixedStatusOnline = 1
|
SkuFixedStatusOnline = 1 // 上架
|
||||||
SkuFixedStatusOffline = 2
|
SkuFixedStatusOffline = 2 // 下架
|
||||||
SkuFixedStatusDeleted = 4
|
SkuFixedStatusDeleted = 4 // 删除
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -79,12 +79,21 @@ const (
|
|||||||
CreateSpuResultFailed = 3
|
CreateSpuResultFailed = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IsFilterDelTrue = "0" // 0代表不查已删除商品
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxSkuNameCharCount = 45 // skuname最长字符数
|
MaxSkuNameCharCount = 45 // skuname最长字符数
|
||||||
SaleAttrIDBase = 1001
|
SaleAttrIDBase = 1001
|
||||||
SaleAttrValueIDBase = 10
|
SaleAttrValueIDBase = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ImgTypeMain = 1 // 商品图片
|
||||||
|
ImgTypeDetail = 2 // 详情图片
|
||||||
|
)
|
||||||
|
|
||||||
type SkuIDPair struct {
|
type SkuIDPair struct {
|
||||||
SkuId int64 `json:"skuId"`
|
SkuId int64 `json:"skuId"`
|
||||||
OutSkuId string `json:"outSkuId"`
|
OutSkuId string `json:"outSkuId"`
|
||||||
@@ -119,11 +128,11 @@ type CategoryInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CreateByUpcParam struct {
|
type CreateByUpcParam struct {
|
||||||
Upc string
|
UniqueUpc string `json:"uniqueCode"` // 商品UPC码
|
||||||
OutSkuId string
|
OutSku string `json:"outSku"` // 商家商品编码,商家系统中唯一编码,限1-35字符,与到家商品编码一对一对应
|
||||||
Price int // 单位为分
|
JdPrice string `json:"jdPrice"` // 商家商品价格(单位:元),用于初始商品门店价格,所有的商品门店价格都会初始化成该值。后续修改商品门店价格需要通过价格类接口修改。
|
||||||
ShopCategoryId int64
|
ShopCategoryID int64 `json:"shopCategoryId"` // 商家店内分类编码,店内分类编码通过查询商家店内分类信息接口获取
|
||||||
IsSale bool
|
IsSale bool `json:"isSale"` // 门店商品可售状态,true为可售,false为不可售,默认为可售。
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateByUpcPair struct {
|
type CreateByUpcPair struct {
|
||||||
@@ -131,13 +140,58 @@ type CreateByUpcPair struct {
|
|||||||
SkuId int64
|
SkuId int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type QuerySkuParam struct {
|
||||||
|
SkuName string `json:"skuName,omitempty"`
|
||||||
|
UpcCode string `json:"upcCode,omitempty"`
|
||||||
|
SkuID int64 `json:"skuId,omitempty"`
|
||||||
|
IsFilterDel string `json:"isFilterDel,omitempty"` // 是否查询出已删除的上传商品(0代表不查已删除商品,不填则查出全部商品)
|
||||||
|
PageNo int `json:"pageNo,omitempty"`
|
||||||
|
PageSize int `json:"pageSize,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SkuMain struct {
|
||||||
|
SuperID int64 `json:"superId"`
|
||||||
|
SkuID int64 `json:"skuId"`
|
||||||
|
OutSkuID string `json:"outSkuId"`
|
||||||
|
CategoryID int64 `json:"categoryId"`
|
||||||
|
BrandID int64 `json:"brandId"`
|
||||||
|
ShopCategories []int64 `json:"shopCategories"`
|
||||||
|
SkuName string `json:"skuName"`
|
||||||
|
Slogan string `json:"slogan"`
|
||||||
|
FixedStatus int `json:"fixedStatus"` // 商家商品上下架状态(1:上架;2:下架;4:删除;)
|
||||||
|
FixedUpTime string `json:"fixedUpTime"`
|
||||||
|
OrgCode int `json:"orgCode"`
|
||||||
|
SellCities []int64 `json:"sellCities"`
|
||||||
|
SkuPrice int `json:"skuPrice"`
|
||||||
|
Weight float64 `json:"weight"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryListBySkuIdsParam struct {
|
||||||
|
SkuIDs []int64 `json:"skuIds"`
|
||||||
|
ImgType int `json:"imgType,omitempty"`
|
||||||
|
HandleStatus []int `json:"handleStatus,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImgHandleQueryResult struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
SkuID int64 `json:"skuId"`
|
||||||
|
IsMain int `json:"isMain"`
|
||||||
|
ImgType int `json:"imgType"`
|
||||||
|
SourceImgURL string `json:"sourceImgUrl"`
|
||||||
|
SkuImgSort int `json:"skuImgSort"`
|
||||||
|
HandleStatus int `json:"handleStatus"`
|
||||||
|
HandleStatusStr string `json:"handleStatusStr"`
|
||||||
|
HandleRemark string `json:"handleRemark"`
|
||||||
|
HandleErrLog string `json:"handleErrLog"`
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
skuExistReg = regexp.MustCompile(`商家skuId已存在:(\d+)`)
|
skuExistReg = regexp.MustCompile(`商家skuId已存在:(\d+)`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 分页查询商品品牌信息接口
|
// 分页查询商品品牌信息接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=1ca07a3e767649a7a44fc6ea7e9ed8dd
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=1ca07a3e767649a7a44fc6ea7e9ed8dd
|
||||||
func (a *API) QueryPageBrandInfo(pageNo, pageSize, brandId int, brandName string) (brandList []*BrandInfo, totalCount int, err error) {
|
func (a *API) QueryPageBrandInfo(pageNo, pageSize int, brandId int64, brandName string) (brandList []*BrandInfo, totalCount int, err error) {
|
||||||
if pageNo <= 0 {
|
if pageNo <= 0 {
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
}
|
}
|
||||||
@@ -320,44 +374,28 @@ func (a *API) BatchUpdateOutSkuId(skuInfoList []*SkuIDPair) (retVal interface{},
|
|||||||
// 查询商家已上传商品信息列表接口
|
// 查询商家已上传商品信息列表接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=e433b95f74524dab91718432c0358977
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=e433b95f74524dab91718432c0358977
|
||||||
// pageNo 从1开始
|
// pageNo 从1开始
|
||||||
func (a *API) QuerySkuInfos(skuName string, skuId int64, pageNo, pageSize int, isFilterDel bool) (retVal []map[string]interface{}, totalCount int, err error) {
|
func (a *API) QuerySkuInfos(queryParam *QuerySkuParam) (skuList []*SkuMain, totalCount int, err error) {
|
||||||
if pageNo <= 0 {
|
if queryParam.PageNo <= 0 {
|
||||||
pageNo = 1
|
queryParam.PageNo = 1
|
||||||
}
|
}
|
||||||
if pageSize == 0 {
|
if queryParam.PageSize == 0 {
|
||||||
pageSize = 50
|
queryParam.PageSize = MaxPageSize4QuerySku
|
||||||
}
|
}
|
||||||
params := map[string]interface{}{
|
result, totalCount, err := a.AccessAPIHavePage("pms/querySkuInfos", utils.Struct2MapByJson(queryParam), nil, nil, nil)
|
||||||
KeyPageNo: pageNo, // pageNo好像必须要有值,否则一直不返回
|
|
||||||
KeyPageSize: pageSize,
|
|
||||||
}
|
|
||||||
if skuName != "" {
|
|
||||||
params[KeySkuName] = skuName
|
|
||||||
}
|
|
||||||
if skuId != 0 {
|
|
||||||
params[KeySkuId] = skuId
|
|
||||||
}
|
|
||||||
if isFilterDel {
|
|
||||||
params[KeyIsFilterDel] = "1"
|
|
||||||
} else {
|
|
||||||
params[KeyIsFilterDel] = "0"
|
|
||||||
}
|
|
||||||
result, totalCount, err := a.AccessAPIHavePage("pms/querySkuInfos", params, nil, nil, nil)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return utils.Slice2MapSlice(result), totalCount, nil
|
err = utils.Map2StructByJson(result, &skuList, false)
|
||||||
}
|
}
|
||||||
return nil, 0, err
|
return skuList, totalCount, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询商品图片处理结果接口
|
// 查询商品图片处理结果接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=17506653e03542f9a49023711780c30d
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=17506653e03542f9a49023711780c30d
|
||||||
func (a *API) QueryListBySkuIds(skuIds []int64, addParams map[string]interface{}) (retVal []map[string]interface{}, err error) {
|
func (a *API) QueryListBySkuIds(queryParam *QueryListBySkuIdsParam) (imgList []*ImgHandleQueryResult, err error) {
|
||||||
result, err := a.AccessAPINoPage("order/queryListBySkuIds", utils.MergeMaps(addParams, utils.Params2Map("skuIds", skuIds)), nil, nil, nil)
|
result, err := a.AccessAPINoPage("order/queryListBySkuIds", utils.Struct2MapByJson(queryParam), nil, nil, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
err = utils.Map2StructByJson(result, &imgList, false)
|
||||||
}
|
}
|
||||||
return nil, err
|
return imgList, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分页查询京东到家商品前缀库接口
|
// 分页查询京东到家商品前缀库接口
|
||||||
@@ -543,22 +581,12 @@ func (a *API) GetSpuSaleAttr(outSpuId string) (attrList []map[string]interface{}
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) BatchAddSku(paramList []*CreateByUpcParam) (pairs []*CreateByUpcPair, err error) {
|
func (a *API) BatchAddSku(batchSkuRequestList []*CreateByUpcParam) (pairs []*CreateByUpcPair, err error) {
|
||||||
batchSkuRequestList := make([]map[string]interface{}, len(paramList))
|
|
||||||
for k, v := range paramList {
|
|
||||||
batchSkuRequestList[k] = map[string]interface{}{
|
|
||||||
"uniqueCode": v.Upc,
|
|
||||||
"outSku": v.OutSkuId,
|
|
||||||
"jdPrice": fmt.Sprintf("%.2f", float32(v.Price)/100),
|
|
||||||
"shopCategoryId": v.ShopCategoryId,
|
|
||||||
"isSale": v.IsSale,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result, err := a.AccessAPINoPage("PmsSkuMainService/batchAddSku", map[string]interface{}{
|
result, err := a.AccessAPINoPage("PmsSkuMainService/batchAddSku", map[string]interface{}{
|
||||||
"batchSkuRequestList": batchSkuRequestList,
|
"batchSkuRequestList": batchSkuRequestList,
|
||||||
}, nil, nil, genNoPageResultParser("code", "result", "detail", "0"))
|
}, nil, nil, genNoPageResultParser("code", "result", "detail", "0"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
globals.SugarLogger.Debug(utils.Format4Output(result, false))
|
// globals.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||||
// todo 这个API在找不到UPC创建失败时,code也是0,底层不能判断失败
|
// todo 这个API在找不到UPC创建失败时,code也是0,底层不能判断失败
|
||||||
if result2, ok := result.([]interface{}); ok && len(result2) > 0 {
|
if result2, ok := result.([]interface{}); ok && len(result2) > 0 {
|
||||||
detail := utils.Slice2MapSlice(result2)
|
detail := utils.Slice2MapSlice(result2)
|
||||||
|
|||||||
@@ -58,7 +58,11 @@ func TestBatchUpdateOutSkuId(t *testing.T) {
|
|||||||
|
|
||||||
func TestQuerySkuInfos(t *testing.T) {
|
func TestQuerySkuInfos(t *testing.T) {
|
||||||
pageSize := 20
|
pageSize := 20
|
||||||
result, totalCount, err := api.QuerySkuInfos("一个高级商品", 0, 0, pageSize, true)
|
result, totalCount, err := api.QuerySkuInfos(&QuerySkuParam{
|
||||||
|
IsFilterDel: IsFilterDelTrue,
|
||||||
|
})
|
||||||
|
t.Log(utils.Format4Output(result, false))
|
||||||
|
t.Log(totalCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -73,7 +77,10 @@ func TestQueryListBySkuIds(t *testing.T) {
|
|||||||
2018806493,
|
2018806493,
|
||||||
2018805873,
|
2018805873,
|
||||||
}
|
}
|
||||||
result, err := api.QueryListBySkuIds(ids, nil)
|
result, err := api.QueryListBySkuIds(&QueryListBySkuIdsParam{
|
||||||
|
SkuIDs: ids,
|
||||||
|
})
|
||||||
|
t.Log(utils.Format4Output(result, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -152,10 +159,10 @@ func TestGetSpuSaleAttr(t *testing.T) {
|
|||||||
func TestBatchAddSku(t *testing.T) {
|
func TestBatchAddSku(t *testing.T) {
|
||||||
paramList := []*CreateByUpcParam{
|
paramList := []*CreateByUpcParam{
|
||||||
&CreateByUpcParam{
|
&CreateByUpcParam{
|
||||||
Upc: "6948939649102",
|
UniqueUpc: "6948939649102",
|
||||||
OutSkuId: "50001",
|
OutSku: "50001",
|
||||||
Price: 213,
|
JdPrice: "2.13",
|
||||||
ShopCategoryId: 4247719,
|
ShopCategoryID: 4247719,
|
||||||
IsSale: true,
|
IsSale: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,19 @@ const (
|
|||||||
KeyStandByPhone = "standByPhone"
|
KeyStandByPhone = "standByPhone"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CarrierNoCrowdSourcing = 9966 // 众包
|
||||||
|
CarrierNoSelfDelivery = 2938 // 自送
|
||||||
|
CarrierNoSelfTake = 9999 // 到店自提
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CoordinateTypeGoogle = 1 // 谷歌
|
||||||
|
CoordinateTypeBaidu = 2 // 百度
|
||||||
|
CoordinateTypeAutonavi = 3 // 高德
|
||||||
|
CoordinateTypeTencent = 4 // 腾讯
|
||||||
|
)
|
||||||
|
|
||||||
type CreateShopResult struct {
|
type CreateShopResult struct {
|
||||||
DeliveryRangeType int `json:"deliveryRangeType"`
|
DeliveryRangeType int `json:"deliveryRangeType"`
|
||||||
CoordinatePoints string `json:"coordinatePoints"`
|
CoordinatePoints string `json:"coordinatePoints"`
|
||||||
@@ -44,6 +57,165 @@ type CityInfo struct {
|
|||||||
Yn int `json:"yn"`
|
Yn int `json:"yn"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OpStoreParams struct {
|
||||||
|
// 以下可用于修改(及查询)
|
||||||
|
StationNo string `json:"stationNo"` // 强制参数,主键
|
||||||
|
StationName string `json:"stationName,omitempty"`
|
||||||
|
OutSystemID string `json:"outSystemId,omitempty"`
|
||||||
|
Mobile string `json:"mobile,omitempty"`
|
||||||
|
Phone string `json:"phone,omitempty"`
|
||||||
|
Lat float64 `json:"lat,omitempty"`
|
||||||
|
Lng float64 `json:"lng,omitempty"`
|
||||||
|
City int `json:"city,omitempty"`
|
||||||
|
County int `json:"county,omitempty"`
|
||||||
|
StationAddress string `json:"stationAddress,omitempty"`
|
||||||
|
Operator string `json:"operator"` // 返回值无
|
||||||
|
ServiceTimeEnd1 int `json:"serviceTimeEnd1,omitempty"`
|
||||||
|
ServiceTimeStart1 int `json:"serviceTimeStart1,omitempty"`
|
||||||
|
ServiceTimeEnd2 int `json:"serviceTimeEnd2,omitempty"`
|
||||||
|
ServiceTimeStart2 int `json:"serviceTimeStart2,omitempty"`
|
||||||
|
DeliveryRangeType int8 `json:"deliveryRangeType,omitempty"` // 返回值无,划分配送服务范围的类型(3、圆心半径、2、不规则多边形(手动画范围))。若更新此字段需传完整值。
|
||||||
|
CoordinateType int `json:"coordinateType,omitempty"` // 返回值无,使用的地图类型(1,谷歌), (2,百度), (3,高德), (4,腾讯)
|
||||||
|
DeliveryRangeRadius int `json:"deliveryRangeRadius,omitempty"` // 返回值无,时效服务范围半径(单位:米)(如果服务范围为类型3的话,该字段有值)
|
||||||
|
CoordinatePoints string `json:"coordinatePoints,omitempty"` // 返回值无,坐标点集合(如果服务范围为类型2的话,该字段有值),每个点以:经度,纬度 的格式表示,用“;”隔开多个点;对于腾讯地图、谷歌地图和高德地图,整个coordinatePoints的长度必须小于2k;对于百度地图,整个coordinatePoints的长度必须小于1k
|
||||||
|
CloseStatus int `json:"closeStatus"` // 0是有意义的值,所以不能是omitempty
|
||||||
|
StoreNotice string `json:"storeNotice,omitempty"`
|
||||||
|
StandByPhone string `json:"standByPhone,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StoreDetail struct {
|
||||||
|
// 以下可用于修改(及查询)
|
||||||
|
StationNo string `json:"stationNo"` // 强制参数,主键
|
||||||
|
StationName string `json:"stationName,omitempty"`
|
||||||
|
OutSystemID string `json:"outSystemId,omitempty"`
|
||||||
|
Mobile string `json:"mobile,omitempty"`
|
||||||
|
Phone string `json:"phone,omitempty"`
|
||||||
|
Lat float64 `json:"lat,omitempty"`
|
||||||
|
Lng float64 `json:"lng,omitempty"`
|
||||||
|
City int `json:"city,omitempty"`
|
||||||
|
County int `json:"county,omitempty"`
|
||||||
|
StationAddress string `json:"stationAddress,omitempty"`
|
||||||
|
// Operator string `json:"operator"` // 返回值无
|
||||||
|
ServiceTimeEnd1 int `json:"serviceTimeEnd1,omitempty"`
|
||||||
|
ServiceTimeStart1 int `json:"serviceTimeStart1,omitempty"`
|
||||||
|
ServiceTimeEnd2 int `json:"serviceTimeEnd2,omitempty"`
|
||||||
|
ServiceTimeStart2 int `json:"serviceTimeStart2,omitempty"`
|
||||||
|
// DeliveryRangeType int8 `json:"deliveryRangeType,omitempty"` // 返回值无,划分配送服务范围的类型(3、圆心半径、2、不规则多边形(手动画范围))。若更新此字段需传完整值。
|
||||||
|
// CoordinateType int `json:"coordinateType,omitempty"` // 返回值无,使用的地图类型(1,谷歌), (2,百度), (3,高德), (4,腾讯)
|
||||||
|
// DeliveryRangeRadius int `json:"deliveryRangeRadius,omitempty"` // 返回值无,时效服务范围半径(单位:米)(如果服务范围为类型3的话,该字段有值)
|
||||||
|
// CoordinatePoints string `json:"coordinatePoints,omitempty"` // 返回值无,坐标点集合(如果服务范围为类型2的话,该字段有值),每个点以:经度,纬度 的格式表示,用“;”隔开多个点;对于腾讯地图、谷歌地图和高德地图,整个coordinatePoints的长度必须小于2k;对于百度地图,整个coordinatePoints的长度必须小于1k
|
||||||
|
CloseStatus int `json:"closeStatus"` // 0是有意义的值,所以不能是omitempty
|
||||||
|
StoreNotice string `json:"storeNotice,omitempty"`
|
||||||
|
StandByPhone string `json:"standByPhone,omitempty"`
|
||||||
|
|
||||||
|
// 以下仅用于查询
|
||||||
|
AllowRangeOptimized int `json:"allowRangeOptimized"`
|
||||||
|
CacheKey4StoreList string `json:"cacheKey4StoreList"`
|
||||||
|
CarrierNo int `json:"carrierNo"`
|
||||||
|
CityName string `json:"cityName"`
|
||||||
|
Coordinate string `json:"coordinate"`
|
||||||
|
CoordinateAddress string `json:"coordinateAddress"`
|
||||||
|
CountyName string `json:"countyName"`
|
||||||
|
CreatePin string `json:"createPin"`
|
||||||
|
CreateTime *utils.JavaDate `json:"createTime"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
IndustryTag int `json:"industryTag"`
|
||||||
|
InnerNoStatus int `json:"innerNoStatus"`
|
||||||
|
IsAutoOrder int `json:"isAutoOrder"` // 是否自动接单,0:是1:否
|
||||||
|
IsMembership int `json:"isMembership"`
|
||||||
|
IsNoPaper int `json:"isNoPaper"`
|
||||||
|
OnlineTime *utils.JavaDate `json:"onlineTime"`
|
||||||
|
OrderAging int `json:"orderAging"`
|
||||||
|
OrderNoticeType int `json:"orderNoticeType"`
|
||||||
|
PreWarehouse int `json:"preWarehouse"`
|
||||||
|
Province int `json:"province"`
|
||||||
|
ProvinceName string `json:"provinceName"`
|
||||||
|
QualifyStatus int `json:"qualifyStatus"`
|
||||||
|
RegularFlag int `json:"regularFlag"`
|
||||||
|
StationDeliveryStatus int `json:"stationDeliveryStatus"`
|
||||||
|
SupportInvoice int `json:"supportInvoice"`
|
||||||
|
SupportOfflinePurchase int `json:"supportOfflinePurchase"`
|
||||||
|
TestMark int `json:"testMark"`
|
||||||
|
TimeAmType int `json:"timeAmType"`
|
||||||
|
TimePmType int `json:"timePmType"`
|
||||||
|
Ts *utils.JavaDate `json:"ts"`
|
||||||
|
UpdatePin string `json:"updatePin"`
|
||||||
|
UpdateTime *utils.JavaDate `json:"updateTime"`
|
||||||
|
VenderID string `json:"venderId"`
|
||||||
|
VenderName string `json:"venderName"`
|
||||||
|
WareType int `json:"wareType"`
|
||||||
|
WhiteDelivery bool `json:"whiteDelivery"`
|
||||||
|
Yn int8 `json:"yn"` // 门店状态,0启用,1禁用
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderProdCommentVo struct {
|
||||||
|
CreatePin string `json:"createPin"`
|
||||||
|
CreateTime *utils.JavaDate `json:"createTime"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
IsPraise int `json:"isPraise"`
|
||||||
|
Score int `json:"score"`
|
||||||
|
ScoreLevel int `json:"scoreLevel"`
|
||||||
|
SkuID int64 `json:"skuId"`
|
||||||
|
SkuName string `json:"skuName"`
|
||||||
|
UpdatePin string `json:"updatePin"`
|
||||||
|
UpdateTime *utils.JavaDate `json:"updateTime"`
|
||||||
|
Yn int8 `json:"yn"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderCommentInfo struct {
|
||||||
|
AppVersion string `json:"appVersion"`
|
||||||
|
CreatePin string `json:"createPin"`
|
||||||
|
CreateTime *utils.JavaDate `json:"createTime"`
|
||||||
|
DeliveryCarrierNo string `json:"deliveryCarrierNo"`
|
||||||
|
DeliveryConfirmTime *utils.JavaDate `json:"deliveryConfirmTime"`
|
||||||
|
DeliveryConfirmTime2 *utils.JavaDate `json:"deliveryConfirmTime2"`
|
||||||
|
DeliveryDifTime int `json:"deliveryDifTime"`
|
||||||
|
DeliveryDifTime2 int `json:"deliveryDifTime2"`
|
||||||
|
DeliveryManNo string `json:"deliveryManNo"`
|
||||||
|
DocID interface{} `json:"docId"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
IsUpdate int `json:"isUpdate"`
|
||||||
|
OrderID int64 `json:"orderId"`
|
||||||
|
OrderProdCommentVoList []*OrderProdCommentVo `json:"orderProdCommentVoList"`
|
||||||
|
OrderType int `json:"orderType"`
|
||||||
|
OrgCode int `json:"orgCode"`
|
||||||
|
OrgCommentContent string `json:"orgCommentContent"`
|
||||||
|
OrgCommentStatus int `json:"orgCommentStatus"`
|
||||||
|
OrgCommentTime *utils.JavaDate `json:"orgCommentTime"`
|
||||||
|
OrgName string `json:"orgName"`
|
||||||
|
Score3 int `json:"score3"`
|
||||||
|
Score3Content string `json:"score3Content"`
|
||||||
|
Score4 int `json:"score4"`
|
||||||
|
Score4Content string `json:"score4Content"`
|
||||||
|
ScoreLevel int `json:"scoreLevel"`
|
||||||
|
StoreID int64 `json:"storeId"`
|
||||||
|
StoreName string `json:"storeName"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
TagsKey []string `json:"tagsKey"`
|
||||||
|
UpdatePin string `json:"updatePin"`
|
||||||
|
UpdateTime *utils.JavaDate `json:"updateTime"`
|
||||||
|
VenderTageKey []string `json:"venderTageKey"`
|
||||||
|
VenderTags []string `json:"venderTags"`
|
||||||
|
Yn int8 `json:"yn"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StoreDeliveryRange struct {
|
||||||
|
Adresses string `json:"adresses"`
|
||||||
|
CreatePin string `json:"createPin"`
|
||||||
|
CreateTime *utils.JavaDate `json:"createTime"`
|
||||||
|
DeliveryRange string `json:"deliveryRange"`
|
||||||
|
DeliveryRangeRadius int `json:"deliveryRangeRadius"`
|
||||||
|
DeliveryRangeType int `json:"deliveryRangeType"`
|
||||||
|
DeliveryServiceType int `json:"deliveryServiceType"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
StationNo string `json:"stationNo"`
|
||||||
|
Ts *utils.JavaDate `json:"ts"`
|
||||||
|
UpdatePin string `json:"updatePin"`
|
||||||
|
UpdateTime *utils.JavaDate `json:"updateTime"`
|
||||||
|
VenderID string `json:"venderId"`
|
||||||
|
Yn int8 `json:"yn"`
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) GetAllCities() (cities []*CityInfo, err error) {
|
func (a *API) GetAllCities() (cities []*CityInfo, err error) {
|
||||||
result, err := a.AccessAPINoPage("address/allcities", nil, nil, nil, genNoPageResultParser("code", "msg", "result", "0"))
|
result, err := a.AccessAPINoPage("address/allcities", nil, nil, nil, genNoPageResultParser("code", "msg", "result", "0"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -69,23 +241,9 @@ func (a *API) GetStationsByVenderId() ([]string, error) {
|
|||||||
|
|
||||||
// 新增不带资质的门店信息接口
|
// 新增不带资质的门店信息接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=93acef27c3aa4d8286d5c8c26b493629
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=93acef27c3aa4d8286d5c8c26b493629
|
||||||
func (a *API) CreateStore(stationName, phone string, city, county int, stationAddress, userName string, serviceTimeStart1, serviceTimeEnd1 int, lng, lat float64, deliveryRangeType, coordinateType int, standByPhone string, addParams map[string]interface{}) (*CreateShopResult, error) {
|
func (a *API) CreateStore(createParams *OpStoreParams) (*CreateShopResult, error) {
|
||||||
params := map[string]interface{}{
|
createParams.Operator = utils.GetAPIOperator(createParams.Operator)
|
||||||
KeyStationName: stationName,
|
result, err := a.AccessAPINoPage("store/createStore", utils.Struct2MapByJson(createParams), nil, nil, func(data map[string]interface{}) (interface{}, error) {
|
||||||
KeyPhone: phone,
|
|
||||||
KeyCity: city,
|
|
||||||
KeyCounty: county,
|
|
||||||
KeyStationAddress: stationAddress,
|
|
||||||
KeyOperator: utils.GetAPIOperator(userName),
|
|
||||||
KeyServiceTimeStart1: serviceTimeStart1,
|
|
||||||
KeyServiceTimeEnd2: serviceTimeEnd1,
|
|
||||||
KeyLng: lng,
|
|
||||||
KeyLat: lat,
|
|
||||||
KeyDeliveryRangeType: deliveryRangeType,
|
|
||||||
KeyCoordinateType: coordinateType,
|
|
||||||
KeyStandByPhone: standByPhone,
|
|
||||||
}
|
|
||||||
result, err := a.AccessAPINoPage("store/createStore", utils.MergeMaps(params, addParams), nil, nil, func(data map[string]interface{}) (interface{}, error) {
|
|
||||||
innerCode := data["code"].(string)
|
innerCode := data["code"].(string)
|
||||||
if data["code"] == "0" {
|
if data["code"] == "0" {
|
||||||
mapData := data["data"].(map[string]interface{})
|
mapData := data["data"].(map[string]interface{})
|
||||||
@@ -102,37 +260,66 @@ func (a *API) CreateStore(stationName, phone string, city, county int, stationAd
|
|||||||
|
|
||||||
// 根据到家门店编码查询门店基本信息接口
|
// 根据到家门店编码查询门店基本信息接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=4c48e347027146d5a103e851055cb1a7
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=4c48e347027146d5a103e851055cb1a7
|
||||||
func (a *API) GetStoreInfoByStationNo(storeNo string) (map[string]interface{}, error) {
|
// func (a *API) GetStoreInfoByStationNo(storeNo string) (map[string]interface{}, error) {
|
||||||
|
// result, err := a.AccessAPINoPage("storeapi/getStoreInfoByStationNo", utils.Params2Map("StoreNo", storeNo), nil, nil, nil)
|
||||||
|
// if err == nil {
|
||||||
|
// return result.(map[string]interface{}), nil
|
||||||
|
// }
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (a *API) GetStoreInfoByStationNo2(storeNo string) (storeDetail *StoreDetail, err error) {
|
||||||
result, err := a.AccessAPINoPage("storeapi/getStoreInfoByStationNo", utils.Params2Map("StoreNo", storeNo), nil, nil, nil)
|
result, err := a.AccessAPINoPage("storeapi/getStoreInfoByStationNo", utils.Params2Map("StoreNo", storeNo), nil, nil, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return result.(map[string]interface{}), nil
|
err = utils.Map2StructByJson(result, &storeDetail, false)
|
||||||
}
|
}
|
||||||
return nil, err
|
return storeDetail, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改门店基础信息接口
|
// 修改门店基础信息接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=2600369a456446f0921e918f3d15e96a
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=2600369a456446f0921e918f3d15e96a
|
||||||
func (a *API) UpdateStoreInfo4Open(storeNo, userName string, addParams map[string]interface{}) error {
|
// func (a *API) UpdateStoreInfo4Open(storeNo, userName string, addParams map[string]interface{}) error {
|
||||||
jdParams := map[string]interface{}{
|
// jdParams := map[string]interface{}{
|
||||||
"stationNo": storeNo,
|
// "stationNo": storeNo,
|
||||||
"operator": utils.GetAPIOperator(userName),
|
// "operator": utils.GetAPIOperator(userName),
|
||||||
|
// }
|
||||||
|
// jdParams = utils.MergeMaps(jdParams, addParams)
|
||||||
|
// _, err := a.AccessAPINoPage("store/updateStoreInfo4Open", jdParams, nil, nil, nullResultParser)
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (a *API) UpdateStoreInfo4Open2(updateParams *OpStoreParams, modifyCloseStatus bool) (err error) {
|
||||||
|
updateParams.Operator = utils.GetAPIOperator(updateParams.Operator)
|
||||||
|
mapData := utils.Struct2MapByJson(updateParams)
|
||||||
|
if !modifyCloseStatus {
|
||||||
|
delete(mapData, "closeStatus")
|
||||||
}
|
}
|
||||||
jdParams = utils.MergeMaps(jdParams, addParams)
|
_, err = a.AccessAPINoPage("store/updateStoreInfo4Open", mapData, nil, nil, nullResultParser)
|
||||||
_, err := a.AccessAPINoPage("store/updateStoreInfo4Open", jdParams, nil, nil, nullResultParser)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据订单号查询商家门店评价信息接口
|
// 根据订单号查询商家门店评价信息接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=bd23397725bb4e74b69e2f2fa1c88d43
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=bd23397725bb4e74b69e2f2fa1c88d43
|
||||||
func (a *API) GetCommentByOrderId(orderId int64) (map[string]interface{}, error) {
|
// func (a *API) GetCommentByOrderId(orderId int64) (map[string]interface{}, error) {
|
||||||
|
// jdParams := map[string]interface{}{
|
||||||
|
// "orderId": orderId,
|
||||||
|
// }
|
||||||
|
// result, err := a.AccessAPINoPage("commentOutApi/getCommentByOrderId", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "200"))
|
||||||
|
// if err == nil {
|
||||||
|
// return result.(map[string]interface{}), nil
|
||||||
|
// }
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (a *API) GetCommentByOrderId2(orderId int64) (orderComment *OrderCommentInfo, err error) {
|
||||||
jdParams := map[string]interface{}{
|
jdParams := map[string]interface{}{
|
||||||
"orderId": orderId,
|
"orderId": orderId,
|
||||||
}
|
}
|
||||||
result, err := a.AccessAPINoPage("commentOutApi/getCommentByOrderId", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "200"))
|
result, err := a.AccessAPINoPage("commentOutApi/getCommentByOrderId", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "200"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return result.(map[string]interface{}), nil
|
err = utils.Map2StructByJson(result, &orderComment, false)
|
||||||
}
|
}
|
||||||
return nil, err
|
return orderComment, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 商家门店评价信息回复接口
|
// 商家门店评价信息回复接口
|
||||||
@@ -169,15 +356,26 @@ func (a *API) UpdateStoreConfig4Open(stationNo string, isAutoOrder bool) (bool,
|
|||||||
|
|
||||||
// 获取门店配送范围接口
|
// 获取门店配送范围接口
|
||||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=8f6d0ac75d734c68bf5bd2a09f376a78
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=8f6d0ac75d734c68bf5bd2a09f376a78
|
||||||
func (a *API) GetDeliveryRangeByStationNo(stationNo string) (map[string]interface{}, error) {
|
// func (a *API) GetDeliveryRangeByStationNo(stationNo string) (map[string]interface{}, error) {
|
||||||
|
// jdParams := map[string]interface{}{
|
||||||
|
// "stationNo": stationNo,
|
||||||
|
// }
|
||||||
|
// result, err := a.AccessAPINoPage("store/getDeliveryRangeByStationNo", jdParams, nil, nil, nil)
|
||||||
|
// if err == nil {
|
||||||
|
// return result.(map[string]interface{}), nil
|
||||||
|
// }
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (a *API) GetDeliveryRangeByStationNo2(stationNo string) (deliveryRange *StoreDeliveryRange, err error) {
|
||||||
jdParams := map[string]interface{}{
|
jdParams := map[string]interface{}{
|
||||||
"stationNo": stationNo,
|
"stationNo": stationNo,
|
||||||
}
|
}
|
||||||
result, err := a.AccessAPINoPage("store/getDeliveryRangeByStationNo", jdParams, nil, nil, nil)
|
result, err := a.AccessAPINoPage("store/getDeliveryRangeByStationNo", jdParams, nil, nil, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return result.(map[string]interface{}), nil
|
err = utils.Map2StructByJson(result, &deliveryRange, false)
|
||||||
}
|
}
|
||||||
return nil, err
|
return deliveryRange, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 私有函数
|
// 私有函数
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package jdapi
|
package jdapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -36,9 +40,9 @@ type CorporationInfo struct {
|
|||||||
EconKind string `json:"econ_kind"`
|
EconKind string `json:"econ_kind"`
|
||||||
EndDate string `json:"end_date"`
|
EndDate string `json:"end_date"`
|
||||||
TermEnd string `json:"term_end"`
|
TermEnd string `json:"term_end"`
|
||||||
NeedID bool `json:"needID"`
|
// NeedID bool `json:"needID"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Partners []struct {
|
Partners []struct {
|
||||||
IdentifyType string `json:"identify_type"`
|
IdentifyType string `json:"identify_type"`
|
||||||
ShouldCapiItems []interface{} `json:"should_capi_items"`
|
ShouldCapiItems []interface{} `json:"should_capi_items"`
|
||||||
StockType string `json:"stock_type"`
|
StockType string `json:"stock_type"`
|
||||||
@@ -136,14 +140,108 @@ type PageShopInfo struct {
|
|||||||
StoreShareURL string `json:"storeShareUrl"`
|
StoreShareURL string `json:"storeShareUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
type PageSku struct {
|
||||||
monthSaleNumReg = regexp.MustCompile(`(\d+)([千|万])`)
|
ButtonEnable bool `json:"buttonEnable"`
|
||||||
|
CatID string `json:"catId"`
|
||||||
|
FixedStatus bool `json:"fixedStatus"`
|
||||||
|
FuncIndicatins string `json:"funcIndicatins"`
|
||||||
|
H5SwichItem struct {
|
||||||
|
IsLeadApp bool `json:"isLeadApp"`
|
||||||
|
} `json:"h5SwichItem"`
|
||||||
|
HasSaleAttr bool `json:"hasSaleAttr"`
|
||||||
|
IconType int `json:"iconType"`
|
||||||
|
Image []*SkuPageImg `json:"image"`
|
||||||
|
InCartCount int `json:"inCartCount"`
|
||||||
|
IsInScope bool `json:"isInScope"`
|
||||||
|
IsRemind bool `json:"isRemind"`
|
||||||
|
MarkingPrice string `json:"markingPrice"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OrgCode string `json:"orgCode"`
|
||||||
|
Prescription bool `json:"prescription"`
|
||||||
|
PriceUnit string `json:"priceUnit"`
|
||||||
|
ProductComment struct {
|
||||||
|
CommentNum string `json:"commentNum"`
|
||||||
|
GoodRate float64 `json:"goodRate"`
|
||||||
|
GoodRating string `json:"goodRating"`
|
||||||
|
HasMore bool `json:"hasMore"`
|
||||||
|
TotalScore string `json:"totalScore"`
|
||||||
|
} `json:"productComment"`
|
||||||
|
ProductInfoType int `json:"productInfoType"`
|
||||||
|
ProductType int `json:"productType"`
|
||||||
|
ProductTypeEnum string `json:"productTypeEnum"`
|
||||||
|
ShareProductURL string `json:"shareProductUrl"`
|
||||||
|
ShowState int `json:"showState"`
|
||||||
|
ShowStateEnum string `json:"showStateEnum"`
|
||||||
|
ShowStateName string `json:"showStateName"`
|
||||||
|
ShowTimLine bool `json:"showTimLine"`
|
||||||
|
SkuID int64 `json:"skuId"`
|
||||||
|
SkuPriceVO struct {
|
||||||
|
BasicPrice string `json:"basicPrice"`
|
||||||
|
MkPrice string `json:"mkPrice"`
|
||||||
|
Promotion int `json:"promotion"`
|
||||||
|
RealTimePrice string `json:"realTimePrice"`
|
||||||
|
SkuID string `json:"skuId"`
|
||||||
|
} `json:"skuPriceVO"`
|
||||||
|
Standard string `json:"standard"`
|
||||||
|
StoreInfo struct {
|
||||||
|
Show bool `json:"show"`
|
||||||
|
StoreID string `json:"storeId"`
|
||||||
|
} `json:"storeInfo"`
|
||||||
|
Subtitle string `json:"subtitle"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
UserActionSku string `json:"userActionSku"`
|
||||||
|
VenderID string `json:"venderId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
QualifyTypeCompany = "25" // 营业执照
|
||||||
|
QualifyTypePerson = "22" // 身份证,个体工商户要求填
|
||||||
|
QualifyTypeAddInfo = "31" // 附加信息,如果身份证是长期有效,要求身份证背面信息
|
||||||
|
|
||||||
|
SaveQualifyActionTypeCommit = 0 // 提交
|
||||||
|
SaveQualifyActionTypeSave = 1 // 暂时保存
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) AccessStorePage(fullURL string, params map[string]interface{}, isPost bool) (retVal map[string]interface{}, err error) {
|
type QualifyItem struct {
|
||||||
|
QualifyURL string `json:"qualifyUrl"`
|
||||||
|
QualifyType string `json:"qualifyType"`
|
||||||
|
QualifyExpireForever int `json:"qualifyExpireForever"` // 0:永久有性,1:非永久有效(需要填QualifyExpireEnd)
|
||||||
|
QualifyExpireStart string `json:"qualifyExpireStart"`
|
||||||
|
QualifyExpireEnd string `json:"qualifyExpireEnd,omitempty"`
|
||||||
|
QualifyName string `json:"qualifyName,omitempty"`
|
||||||
|
QualifyOwner string `json:"qualifyOwner,omitempty"`
|
||||||
|
LicenceType string `json:"licenceType,omitempty"` // -1
|
||||||
|
QualifyNumber string `json:"qualifyNumber,omitempty"`
|
||||||
|
QualifyAddress string `json:"qualifyAddress,omitempty"`
|
||||||
|
LicenceName string `json:"licenceName,omitempty"`
|
||||||
|
EconKind string `json:"econKind,omitempty"`
|
||||||
|
Scope string `json:"scope,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
monthSaleNumReg = regexp.MustCompile(`(\d+)([千|万])`)
|
||||||
|
pageExceedLimitCodes = map[string]int{
|
||||||
|
"403": 1,
|
||||||
|
}
|
||||||
|
pageCanRetryCodes = map[string]int{}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KeyImgData = "imgData"
|
||||||
|
KeyImgName = "imgName"
|
||||||
|
|
||||||
|
ResultKeyData = "data"
|
||||||
|
ResultKeyResult = "result"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *API) AccessStorePage2(fullURL string, params map[string]interface{}, isPost bool, resultKey string) (retVal interface{}, err error) {
|
||||||
if a.GetCookieCount() == 0 {
|
if a.GetCookieCount() == 0 {
|
||||||
return nil, fmt.Errorf("需要设置Store Cookie才能使用此方法")
|
return nil, fmt.Errorf("需要设置Store Cookie才能使用此方法")
|
||||||
}
|
}
|
||||||
|
imgData := params[KeyImgData]
|
||||||
|
if imgData != nil {
|
||||||
|
delete(params, KeyImgData)
|
||||||
|
}
|
||||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||||
func() *http.Request {
|
func() *http.Request {
|
||||||
var request *http.Request
|
var request *http.Request
|
||||||
@@ -151,8 +249,26 @@ func (a *API) AccessStorePage(fullURL string, params map[string]interface{}, isP
|
|||||||
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(fullURL, "", params), nil)
|
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(fullURL, "", params), nil)
|
||||||
} else {
|
} else {
|
||||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
|
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
|
||||||
|
if params[KeyImgName] == nil {
|
||||||
|
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
} else {
|
||||||
|
var b bytes.Buffer
|
||||||
|
w := multipart.NewWriter(&b)
|
||||||
|
if fw, err := w.CreateFormFile("uploadFile", params[KeyImgName].(string)); err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
} else {
|
||||||
|
fw.Write(imgData.([]byte))
|
||||||
|
}
|
||||||
|
for k, v := range params {
|
||||||
|
// baseapi.SugarLogger.Debug(k, " ", v)
|
||||||
|
w.WriteField(k, url.QueryEscape(fmt.Sprint(v)))
|
||||||
|
}
|
||||||
|
w.Close()
|
||||||
|
// b.WriteString(utils.Map2URLValues(params).Encode())
|
||||||
|
request, _ = http.NewRequest(http.MethodPost, fullURL, &b)
|
||||||
|
request.Header.Set("Content-Type", w.FormDataContentType())
|
||||||
|
}
|
||||||
request.Header.Set("charset", "UTF-8")
|
request.Header.Set("charset", "UTF-8")
|
||||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -166,15 +282,20 @@ func (a *API) AccessStorePage(fullURL string, params map[string]interface{}, isP
|
|||||||
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
|
||||||
}
|
}
|
||||||
retVal = jsonResult1
|
retVal = jsonResult1
|
||||||
code := jsonResult1["code"].(string)
|
code, ok := jsonResult1["code"].(string)
|
||||||
|
if !ok {
|
||||||
|
return platformapi.ErrLevelGeneralFail, utils.NewErrorCode(utils.Format4Output(jsonResult1, true), "999")
|
||||||
|
}
|
||||||
if code == ResponseCodeSuccess {
|
if code == ResponseCodeSuccess {
|
||||||
retVal, _ = jsonResult1["result"].(map[string]interface{})
|
if resultKey != "" {
|
||||||
|
retVal = jsonResult1[resultKey]
|
||||||
|
}
|
||||||
return platformapi.ErrLevelSuccess, nil
|
return platformapi.ErrLevelSuccess, nil
|
||||||
}
|
}
|
||||||
newErr := utils.NewErrorCode(jsonResult1["msg"].(string), code)
|
newErr := utils.NewErrorCode(jsonResult1["msg"].(string), code)
|
||||||
if _, ok := exceedLimitCodes[code]; ok {
|
if _, ok := pageExceedLimitCodes[code]; ok {
|
||||||
return platformapi.ErrLevelExceedLimit, newErr
|
return platformapi.ErrLevelExceedLimit, newErr
|
||||||
} else if _, ok := canRetryCodes[code]; ok {
|
} else if _, ok := pageCanRetryCodes[code]; ok {
|
||||||
return platformapi.ErrLevelRecoverableErr, newErr
|
return platformapi.ErrLevelRecoverableErr, newErr
|
||||||
} else {
|
} else {
|
||||||
baseapi.SugarLogger.Debugf("jd AccessStorePage failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
baseapi.SugarLogger.Debugf("jd AccessStorePage failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||||
@@ -184,6 +305,14 @@ func (a *API) AccessStorePage(fullURL string, params map[string]interface{}, isP
|
|||||||
return retVal, err
|
return retVal, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) AccessStorePage(fullURL string, params map[string]interface{}, isPost bool) (retVal map[string]interface{}, err error) {
|
||||||
|
result, err := a.AccessStorePage2(fullURL, params, isPost, ResultKeyResult)
|
||||||
|
if err == nil {
|
||||||
|
retVal, _ = result.(map[string]interface{})
|
||||||
|
}
|
||||||
|
return retVal, err
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) GetRealMobile4Order(orderId, stationNo string) (mobile string, err error) {
|
func (a *API) GetRealMobile4Order(orderId, stationNo string) (mobile string, err error) {
|
||||||
retVal, err := a.GetStoreOrderInfo(orderId, stationNo)
|
retVal, err := a.GetStoreOrderInfo(orderId, stationNo)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -202,7 +331,7 @@ func (a *API) GetStoreOrderInfo(orderId, stationNo string) (storeOrderInfo map[s
|
|||||||
if stationNo != "" {
|
if stationNo != "" {
|
||||||
params["stationNo"] = stationNo
|
params["stationNo"] = stationNo
|
||||||
}
|
}
|
||||||
retVal, err := a.AccessStorePage("http://store.jddj.com/order/newManager/search", params, false)
|
retVal, err := a.AccessStorePage("http://order.jddj.com/order/newManager/search", params, false)
|
||||||
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
|
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
|
||||||
@@ -229,7 +358,7 @@ func (a *API) GetStoreOrderInfoList(fromTime, toTime string) (storeOrderList []m
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
params["pageNo"] = pageNo
|
params["pageNo"] = pageNo
|
||||||
retVal, err := a.AccessStorePage("http://store.jddj.com/order/newManager/tabQuery/all", params, false)
|
retVal, err := a.AccessStorePage("http://order.jddj.com/order/newManager/tabQuery/all", params, false)
|
||||||
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
|
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
|
||||||
@@ -246,7 +375,7 @@ func (a *API) GetStoreOrderInfoList(fromTime, toTime string) (storeOrderList []m
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) GetSkuPageInfo(skuId int64) (skuPageInfo map[string]interface{}, err error) {
|
func (a *API) GetSkuPageInfo(skuId int64) (skuPageInfo *PageSku, err error) {
|
||||||
skuIDMap := map[string]interface{}{
|
skuIDMap := map[string]interface{}{
|
||||||
"skuId": utils.Int64ToStr(skuId),
|
"skuId": utils.Int64ToStr(skuId),
|
||||||
"storeId": "0",
|
"storeId": "0",
|
||||||
@@ -258,14 +387,17 @@ func (a *API) GetSkuPageInfo(skuId int64) (skuPageInfo map[string]interface{}, e
|
|||||||
"body": utils.Format4Output(skuIDMap, true),
|
"body": utils.Format4Output(skuIDMap, true),
|
||||||
}
|
}
|
||||||
|
|
||||||
skuPageInfo, err = a.AccessStorePage("https://daojia.jd.com/client", params, false)
|
result, err := a.AccessStorePage("https://daojia.jd.com/client", params, false)
|
||||||
|
if err == nil {
|
||||||
|
err = utils.Map2StructByJson(result, &skuPageInfo, false)
|
||||||
|
}
|
||||||
return skuPageInfo, err
|
return skuPageInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) GetSkuPageImageInfo(skuId int64) (imgList []*SkuPageImg, err error) {
|
func (a *API) GetSkuPageImageInfo(skuId int64) (imgList []*SkuPageImg, err error) {
|
||||||
skuPageInfo, err := a.GetSkuPageInfo(skuId)
|
skuPageInfo, err := a.GetSkuPageInfo(skuId)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = utils.Map2StructByJson(skuPageInfo["image"], &imgList, false)
|
imgList = skuPageInfo.Image
|
||||||
}
|
}
|
||||||
return imgList, err
|
return imgList, err
|
||||||
}
|
}
|
||||||
@@ -346,3 +478,47 @@ func MonthSaleNum2Int(monthSaleNumStr string) (monthSaleNum int) {
|
|||||||
}
|
}
|
||||||
return monthSaleNum
|
return monthSaleNum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) StoreUploadImg(imgFileName string, imgBin []byte) (imgURL string, err error) {
|
||||||
|
result, err := a.AccessStorePage2("https://sta-store.jddj.com/store/uploadImg.json", map[string]interface{}{
|
||||||
|
KeyImgData: imgBin,
|
||||||
|
KeyImgName: imgFileName,
|
||||||
|
}, true, ResultKeyData)
|
||||||
|
if err == nil {
|
||||||
|
imgURL = result.(string)
|
||||||
|
}
|
||||||
|
return imgURL, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) StoreUploadImgByURL(inImgURL string) (imgURL string, err error) {
|
||||||
|
response, err := http.Get(inImgURL)
|
||||||
|
if err == nil {
|
||||||
|
defer func() {
|
||||||
|
response.Body.Close()
|
||||||
|
}()
|
||||||
|
if response.StatusCode == http.StatusOK {
|
||||||
|
bodyData, err2 := ioutil.ReadAll(response.Body)
|
||||||
|
if err = err2; err == nil {
|
||||||
|
imgName := utils.GetUUID()
|
||||||
|
if lastSlashIndex := strings.LastIndex(inImgURL, "/"); lastSlashIndex >= 0 {
|
||||||
|
imgName = inImgURL[lastSlashIndex+1:]
|
||||||
|
}
|
||||||
|
return a.StoreUploadImg(imgName, bodyData)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = platformapi.ErrHTTPCodeIsNot200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) SaveQualify(stationNo string, actionType int, qualifyList []*QualifyItem) (err error) {
|
||||||
|
_, err = a.AccessStorePage2("https://sta-store.jddj.com/store/saveQualify.o2o", map[string]interface{}{
|
||||||
|
"stationNo": stationNo,
|
||||||
|
"actionType": actionType,
|
||||||
|
"qualifyList": utils.Format4Output(qualifyList, true),
|
||||||
|
"type": 1,
|
||||||
|
"degrade": "no",
|
||||||
|
}, true, "")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestGetRealMobileNumber4Order(t *testing.T) {
|
func TestGetRealMobileNumber4Order(t *testing.T) {
|
||||||
orderId := "910170516000941"
|
orderId := "921823424000122"
|
||||||
desiredMobile := "13398196274"
|
desiredMobile := "13722455105"
|
||||||
mobile, err := api.GetRealMobile4Order(orderId, "")
|
mobile, err := api.GetRealMobile4Order(orderId, "11893205")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -21,8 +21,8 @@ func TestGetRealMobileNumber4Order(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetStoreOrderInfo(t *testing.T) {
|
func TestGetStoreOrderInfo(t *testing.T) {
|
||||||
orderId := "910170516000941"
|
orderId := "921823424000122"
|
||||||
orderInfo, err := api.GetStoreOrderInfo(orderId, "")
|
orderInfo, err := api.GetStoreOrderInfo(orderId, "11893205")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ func TestGetSkuPageImageInfo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCorporationInfo(t *testing.T) {
|
func TestGetCorporationInfo(t *testing.T) {
|
||||||
imgList, err := api.GetCorporationInfo("", "915101003431062533")
|
imgList, err := api.GetCorporationInfo("", "92330104MA28XPXH5G")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -101,3 +101,91 @@ func TestMonthSaleNum2Int(t *testing.T) {
|
|||||||
t.Fatalf("num3:%d", num3)
|
t.Fatalf("num3:%d", num3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStoreUploadImgByURL(t *testing.T) {
|
||||||
|
outImgURL, err := api.StoreUploadImgByURL("http://image.jxc4.com/940c151db7e396f2ceaec0304597836f.jpg")
|
||||||
|
t.Log(outImgURL)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSaveQualify(t *testing.T) {
|
||||||
|
jsonStr := `
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"qualifyUrl":"http://img30.360buyimg.com/vendersettle/jfs/t1/69834/24/6602/68812/5d4d35fdEaaf373c6/5c1c50e7bb6330e4.jpg",
|
||||||
|
"qualifyType":"25",
|
||||||
|
"qualifyExpireForever":0,
|
||||||
|
"qualifyExpireStart":"2017-09-07 00:00:00",
|
||||||
|
"qualifyName":"刘男",
|
||||||
|
"licenceType":"-1",
|
||||||
|
"qualifyNumber":"92330104MA28XPXH5G",
|
||||||
|
"qualifyAddress":"浙江省杭州市江干区八堡家园5排10号一楼102",
|
||||||
|
"licenceName":"杭州市江干区刘男便利店",
|
||||||
|
"econKind":"个体工商户",
|
||||||
|
"scope":"食品经营(凭有效许可证经营);零售:卷烟、雪茄烟(凭有效许可证经营);批发、零售:日用百货,五金。(依法须经批准的项目,经相关部门批准后方可开展经营活动)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qualifyUrl":"http://img30.360buyimg.com/vendersettle/jfs/t1/58554/26/7134/19343/5d4d3639E57b14138/bcce25e1eac11be8.jpg",
|
||||||
|
"qualifyType":"22",
|
||||||
|
"qualifyExpireForever":1,
|
||||||
|
"qualifyExpireStart":"2013-07-22 16:59:38",
|
||||||
|
"qualifyExpireEnd":"2033-07-22 16:59:50",
|
||||||
|
"qualifyOwner":"刘男",
|
||||||
|
"qualifyNumber":"420621198110303336"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qualifyUrl":"",
|
||||||
|
"qualifyType":"33",
|
||||||
|
"qualifyExpireForever":1,
|
||||||
|
"qualifyExpireStart":"",
|
||||||
|
"qualifyExpireEnd":""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qualifyUrl":"",
|
||||||
|
"qualifyType":"8",
|
||||||
|
"qualifyExpireForever":1,
|
||||||
|
"qualifyExpireStart":"",
|
||||||
|
"qualifyExpireEnd":""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qualifyUrl":"",
|
||||||
|
"qualifyType":"9",
|
||||||
|
"qualifyExpireForever":1,
|
||||||
|
"qualifyExpireStart":"",
|
||||||
|
"qualifyExpireEnd":""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qualifyUrl":"",
|
||||||
|
"qualifyType":"10",
|
||||||
|
"qualifyExpireForever":1,
|
||||||
|
"qualifyExpireStart":"",
|
||||||
|
"qualifyExpireEnd":""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qualifyUrl":"",
|
||||||
|
"qualifyType":"29",
|
||||||
|
"qualifyExpireForever":1,
|
||||||
|
"qualifyExpireStart":"",
|
||||||
|
"qualifyExpireEnd":""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"qualifyUrl":"",
|
||||||
|
"qualifyType":"31",
|
||||||
|
"qualifyExpireForever":1,
|
||||||
|
"qualifyExpireStart":"",
|
||||||
|
"qualifyExpireEnd":""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
`
|
||||||
|
var qualityList []*QualifyItem
|
||||||
|
err := utils.UnmarshalUseNumber([]byte(jsonStr), &qualityList)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = api.SaveQualify("11902261", SaveQualifyActionTypeSave, qualityList)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
const (
|
const (
|
||||||
MaxStoreSkuBatchSize = 50
|
MaxStoreSkuBatchSize = 50
|
||||||
MaxStockQty = 100000000
|
MaxStockQty = 100000000
|
||||||
|
|
||||||
|
MaxAddByStoreAndSkusCount = 30 // 批量置顶商品排序接口的最大个数
|
||||||
)
|
)
|
||||||
|
|
||||||
type SkuPriceInfo struct {
|
type SkuPriceInfo struct {
|
||||||
@@ -109,7 +111,7 @@ func (a *API) UpdateVendorStationPrice(trackInfo string, outStationNo, stationNo
|
|||||||
result, err := a.AccessAPINoPage2("venderprice/updateStationPrice", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "0"), trackInfo)
|
result, err := a.AccessAPINoPage2("venderprice/updateStationPrice", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "0"), trackInfo)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
var err2 error
|
var err2 error
|
||||||
if responseList, err2 = a.handleBatchOpResult(len(skuPriceInfoList), result, "json2"); err2 != nil && err == nil {
|
if responseList, err2 = a.handleBatchOpResult(len(skuPriceInfoList), err, result, "json2"); err2 != nil && err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,18 +148,20 @@ func (a *API) GetStationInfoList(stationNo string, skuIds []int64) (priceInfo []
|
|||||||
return priceInfo, err
|
return priceInfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) handleBatchOpResult(batchCount int, result interface{}, tagName string) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
func (a *API) handleBatchOpResult(batchCount int, inErr error, result interface{}, tagName string) (responseList []*StoreSkuBatchUpdateResponse, err error) {
|
||||||
if err = utils.Map2Struct(result, &responseList, true, tagName); err == nil {
|
if result != nil {
|
||||||
var failedList []*StoreSkuBatchUpdateResponse
|
if err = utils.Map2Struct(result, &responseList, true, tagName); err == nil {
|
||||||
for _, v := range responseList {
|
var failedList []*StoreSkuBatchUpdateResponse
|
||||||
if v.Code != 0 {
|
for _, v := range responseList {
|
||||||
failedList = append(failedList, v)
|
if v.Code != 0 {
|
||||||
|
failedList = append(failedList, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(failedList) >= batchCount {
|
||||||
|
err = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseCodeAccessFailed, 1) // 此错误基本用不到
|
||||||
|
} else if len(failedList) > 0 { // 部分失败
|
||||||
|
err = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseInnerCodePartialFailed, 1)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if len(failedList) >= batchCount {
|
|
||||||
err = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseCodeAccessFailed, 1) // 此错误基本用不到
|
|
||||||
} else if len(failedList) > 0 { // 部分失败
|
|
||||||
err = utils.NewErrorCode(string(utils.MustMarshal(failedList)), ResponseInnerCodePartialFailed, 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return responseList, err
|
return responseList, err
|
||||||
@@ -181,7 +185,7 @@ func (a *API) BatchUpdateCurrentQtys(trackInfo, outStationNo, stationNo string,
|
|||||||
result, err := a.AccessAPINoPage2("stock/batchUpdateCurrentQtys", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
result, err := a.AccessAPINoPage2("stock/batchUpdateCurrentQtys", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
var err2 error
|
var err2 error
|
||||||
if responseList, err2 = a.handleBatchOpResult(len(skuStockList), result, ""); err2 != nil && err == nil {
|
if responseList, err2 = a.handleBatchOpResult(len(skuStockList), err, result, ""); err2 != nil && err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,7 +235,7 @@ func (a *API) UpdateVendibility(trackInfo string, listBaseStockCenterRequest []*
|
|||||||
result, err := a.AccessAPINoPage2("stock/updateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
result, err := a.AccessAPINoPage2("stock/updateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
var err2 error
|
var err2 error
|
||||||
if responseList, err2 = a.handleBatchOpResult(len(listBaseStockCenterRequest), result, ""); err2 != nil && err == nil {
|
if responseList, err2 = a.handleBatchOpResult(len(listBaseStockCenterRequest), err, result, ""); err2 != nil && err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,10 +257,11 @@ func (a *API) BatchUpdateVendibility(trackInfo, outStationNo, stationNo string,
|
|||||||
} else {
|
} else {
|
||||||
jdParams["stationNo"] = stationNo
|
jdParams["stationNo"] = stationNo
|
||||||
}
|
}
|
||||||
|
// 此函数在全部失败时,err仍然返回成功
|
||||||
result, err := a.AccessAPINoPage2("stock/batchUpdateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
result, err := a.AccessAPINoPage2("stock/batchUpdateVendibility", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"), trackInfo)
|
||||||
if result != nil {
|
if result != nil {
|
||||||
var err2 error
|
var err2 error
|
||||||
if responseList, err2 = a.handleBatchOpResult(len(stockVendibilityList), result, ""); err2 != nil && err == nil {
|
if responseList, err2 = a.handleBatchOpResult(len(stockVendibilityList), err, result, ""); err2 != nil && err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,3 +296,14 @@ func (a *API) QueryStockCenter(outStationNo string, skuIds []*SkuIdEntity, userP
|
|||||||
}
|
}
|
||||||
return vendibilityResponse, err
|
return vendibilityResponse, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批量置顶商品排序接口
|
||||||
|
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=a7677f1a75984ed3a6ea3d4827f5a6b4
|
||||||
|
func (a *API) AddByStoreAndSkus(stationNo int64, skuIDs []int64) (err error) {
|
||||||
|
jdParams := map[string]interface{}{
|
||||||
|
"storeId": stationNo,
|
||||||
|
"skuIds": skuIDs,
|
||||||
|
}
|
||||||
|
_, err = a.AccessAPINoPage("OrgSortService/addByStoreAndSkus", jdParams, nil, nil, genNoPageResultParser("status", "message", "", "200"))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import (
|
|||||||
const (
|
const (
|
||||||
mustExistStoreID = "11053496"
|
mustExistStoreID = "11053496"
|
||||||
mustExistStoreJXID = "2"
|
mustExistStoreJXID = "2"
|
||||||
|
|
||||||
|
// mustExistStoreID = "11734851"
|
||||||
|
// mustExistStoreJXID = "100118"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetAllCities(t *testing.T) {
|
func TestGetAllCities(t *testing.T) {
|
||||||
@@ -39,56 +42,51 @@ func TestGetStationsByVenderId(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetStoreInfoByStationNo(t *testing.T) {
|
func TestGetStoreInfoByStationNo(t *testing.T) {
|
||||||
result, err := api.GetStoreInfoByStationNo(mustExistStoreID)
|
result, err := api.GetStoreInfoByStationNo2(mustExistStoreID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
outSystemId := result["outSystemId"].(string)
|
t.Log(utils.Format4Output(result, false))
|
||||||
if outSystemId != "100285" {
|
if result.OutSystemID != mustExistStoreJXID {
|
||||||
baseapi.SugarLogger.Fatalf("outSystemId is not correct, its:%s", outSystemId)
|
baseapi.SugarLogger.Fatalf("outSystemId is not correct, its:%s", result.OutSystemID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateStoreInfo4Open(t *testing.T) {
|
func TestUpdateStoreInfo4Open(t *testing.T) {
|
||||||
result, err := api.GetStoreInfoByStationNo(mustExistStoreID)
|
result, err := api.GetStoreInfoByStationNo2(mustExistStoreID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
oldAddress := result["stationAddress"].(string)
|
oldAddress := result.StationAddress
|
||||||
testAddress := oldAddress + "T"
|
params := &OpStoreParams{
|
||||||
addParams := map[string]interface{}{
|
StationNo: mustExistStoreID,
|
||||||
"stationAddress": testAddress,
|
Operator: "test",
|
||||||
|
StationAddress: oldAddress + "T",
|
||||||
}
|
}
|
||||||
err = api.UpdateStoreInfo4Open(mustExistStoreID, "test", addParams)
|
err = api.UpdateStoreInfo4Open2(params, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err = api.GetStoreInfoByStationNo(mustExistStoreID)
|
result, err = api.GetStoreInfoByStationNo2(mustExistStoreID)
|
||||||
newAddress := result["stationAddress"].(string)
|
newAddress := result.StationAddress
|
||||||
if newAddress != testAddress {
|
if newAddress != params.StationAddress {
|
||||||
t.Fatalf("address not match, newAddress:%s, oldAddress:%s", newAddress, oldAddress)
|
t.Fatalf("address not match, newAddress:%s, oldAddress:%s", newAddress, oldAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
addParams = map[string]interface{}{
|
params.StationAddress = oldAddress
|
||||||
"stationAddress": oldAddress,
|
api.UpdateStoreInfo4Open2(params, false)
|
||||||
}
|
|
||||||
api.UpdateStoreInfo4Open(mustExistStoreID, "test", addParams)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetCommentByOrderId(t *testing.T) {
|
func TestGetCommentByOrderId(t *testing.T) {
|
||||||
testOrderID := int64(822347450000922)
|
testOrderID := int64(922520919000622)
|
||||||
result, err := api.GetCommentByOrderId(testOrderID)
|
result, err := api.GetCommentByOrderId2(testOrderID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
gotOrderID := utils.MustInterface2Int64(result["orderId"])
|
|
||||||
if gotOrderID != testOrderID {
|
|
||||||
t.Fatalf("GetCommentByOrderId wrong, gotOrderID:%d", gotOrderID)
|
|
||||||
}
|
|
||||||
t.Log(utils.Format4Output(result, false))
|
t.Log(utils.Format4Output(result, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,38 +102,38 @@ func TestUpdateStoreConfig4Open(t *testing.T) {
|
|||||||
t.Fatal(result)
|
t.Fatal(result)
|
||||||
}
|
}
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
result2, err := api.GetStoreInfoByStationNo(testStationNo)
|
result2, err := api.GetStoreInfoByStationNo2(testStationNo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
isAutoOrder := int(utils.MustInterface2Int64(result2["isAutoOrder"]))
|
isAutoOrder := result2.IsAutoOrder
|
||||||
if isAutoOrder != 0 && desiredValue || isAutoOrder == 0 && !desiredValue {
|
if isAutoOrder != 0 && desiredValue || isAutoOrder == 0 && !desiredValue {
|
||||||
t.Fatalf("UpdateStoreConfig4Open failed, isAutoOrder:%d", isAutoOrder)
|
t.Fatalf("UpdateStoreConfig4Open failed, isAutoOrder:%d", isAutoOrder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetDeliveryRangeByStationNo(t *testing.T) {
|
func TestGetDeliveryRangeByStationNo(t *testing.T) {
|
||||||
const testStoreID = "11738152"
|
const testStoreID = "11734851"
|
||||||
result, err := api.GetDeliveryRangeByStationNo(testStoreID)
|
result, err := api.GetDeliveryRangeByStationNo2(testStoreID)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
result2, err := api.GetStoreInfoByStationNo(testStoreID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||||
baseapi.SugarLogger.Debug(utils.Format4Output(result2, false))
|
}
|
||||||
deliveryRange := result["deliveryRange"].(string)
|
|
||||||
params := map[string]interface{}{
|
func TestDisableAutoOrder4AllStores(t *testing.T) {
|
||||||
"lng": result2["lng"],
|
storeIDs, err := api.GetStationsByVenderId()
|
||||||
"lat": result2["lat"],
|
|
||||||
"coordinateType": 3,
|
|
||||||
"deliveryRangeType": 2,
|
|
||||||
"coordinatePoints": deliveryRange,
|
|
||||||
}
|
|
||||||
err = api.UpdateStoreInfo4Open(testStoreID, "test", params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
for _, storeID := range storeIDs {
|
||||||
|
if storeInfo, err := api.GetStoreInfoByStationNo2(storeID); err == nil {
|
||||||
|
if storeInfo.Yn == 0 && storeInfo.IsAutoOrder == 0 {
|
||||||
|
t.Log(storeID)
|
||||||
|
api.UpdateStoreConfig4Open(storeID, false)
|
||||||
|
}
|
||||||
|
t.Log(utils.Format4Output(storeInfo, false))
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func init() {
|
|||||||
// prod
|
// prod
|
||||||
// api = New("3c0a05d464c247c19d7ec13accc78605", "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE")
|
// api = New("3c0a05d464c247c19d7ec13accc78605", "b1M}9?:sTbsB[OF2gNORnN(|(iy9rB8(`7]|[wGLnbmt`evfM>E:A90DjHAW:UPE")
|
||||||
|
|
||||||
api.SetCookie("token", "0seqGSJnhbr4XJ0EaIQL6CoOpnaV1ErgS42uOlzNXYIX7PeuLuyCFQQZKKWGExJ7IMTQQQDe5H6YMmVFnxjCkw")
|
api.SetCookie("token", "M0p9VatZSeSHfrosD5IViAVl73IcA8mlcuHIV5sG6Zpv83a7JE0wY3t26aEhrrs_MR5gtLSFF1UIkt8HAjaXow")
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleError(t *testing.T, err error) {
|
func handleError(t *testing.T, err error) {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi"
|
"git.rosy.net.cn/baseapi"
|
||||||
@@ -45,10 +44,12 @@ const (
|
|||||||
ErrCodeSysErr = 700 // 系统错误,按美团外卖技术支持的说法,可当成需重试的错误
|
ErrCodeSysErr = 700 // 系统错误,按美团外卖技术支持的说法,可当成需重试的错误
|
||||||
ErrCodeAccessLimited = 711 // 接口调用过于频繁,触发流控,请降低调用频率
|
ErrCodeAccessLimited = 711 // 接口调用过于频繁,触发流控,请降低调用频率
|
||||||
|
|
||||||
ErrCodeNoAppFood = 805 // 不存在此菜品
|
ErrCodeNoAppFood = 805 // 不存在此菜品
|
||||||
ErrCodeNoSuchOrder = 808 // 不存在此订单
|
ErrCodeNoSuchOrder = 806 // 不存在此订单
|
||||||
ErrCodeSkuCategoryNotExist = 1021 // 菜品分类不存在
|
ErrCodeOpFailed = 808 // 操作失败(如订单在操作时,状态已变更等情况)
|
||||||
ErrCodeSkuCategoryExist = 1037 // 菜品分类已存在
|
ErrCodeSkuCategoryNotExist = 1021 // 菜品分类不存在
|
||||||
|
ErrCodeSkuCategoryExist = 1037 // 菜品分类已存在
|
||||||
|
ErrCodeCanNotModifyStoreDeliveryInfo = 3018 // 商家已接入美团配送,不可修改门店配送相关信息
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
@@ -59,16 +60,15 @@ type API struct {
|
|||||||
callbackURL string
|
callbackURL string
|
||||||
client *http.Client
|
client *http.Client
|
||||||
config *platformapi.APIConfig
|
config *platformapi.APIConfig
|
||||||
|
|
||||||
locker sync.RWMutex
|
|
||||||
userCookies map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
canRetryCodes = map[int]int{
|
canRetryCodes = map[int]int{
|
||||||
ErrCodeSysErr: 1,
|
|
||||||
ErrCodeAccessLimited: 1,
|
ErrCodeAccessLimited: 1,
|
||||||
}
|
}
|
||||||
|
canRecoverCodes = map[int]int{
|
||||||
|
ErrCodeSysErr: 1,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(appID, secret, callbackURL string, config ...*platformapi.APIConfig) *API {
|
func New(appID, secret, callbackURL string, config ...*platformapi.APIConfig) *API {
|
||||||
@@ -82,8 +82,6 @@ func New(appID, secret, callbackURL string, config ...*platformapi.APIConfig) *A
|
|||||||
callbackURL: callbackURL,
|
callbackURL: callbackURL,
|
||||||
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
client: &http.Client{Timeout: curConfig.ClientTimeout},
|
||||||
config: &curConfig,
|
config: &curConfig,
|
||||||
|
|
||||||
userCookies: make(map[string]string),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +143,7 @@ func (a *API) AccessAPI2(cmd string, isGet bool, bizParams map[string]interface{
|
|||||||
fw.Write(imgData.([]byte))
|
fw.Write(imgData.([]byte))
|
||||||
}
|
}
|
||||||
for k, v := range params {
|
for k, v := range params {
|
||||||
fmt.Println(k, " ", v)
|
// baseapi.SugarLogger.Debug(k, " ", v)
|
||||||
w.WriteField(k, url.QueryEscape(fmt.Sprint(v)))
|
w.WriteField(k, url.QueryEscape(fmt.Sprint(v)))
|
||||||
}
|
}
|
||||||
w.Close()
|
w.Close()
|
||||||
@@ -173,6 +171,8 @@ func (a *API) AccessAPI2(cmd string, isGet bool, bizParams map[string]interface{
|
|||||||
newErr := utils.NewErrorIntCode(errorInfo["msg"].(string), int(utils.MustInterface2Int64(errorInfo["code"])))
|
newErr := utils.NewErrorIntCode(errorInfo["msg"].(string), int(utils.MustInterface2Int64(errorInfo["code"])))
|
||||||
if canRetryCodes[newErr.IntCode()] == 1 {
|
if canRetryCodes[newErr.IntCode()] == 1 {
|
||||||
return platformapi.ErrLevelExceedLimit, newErr
|
return platformapi.ErrLevelExceedLimit, newErr
|
||||||
|
} else if canRecoverCodes[newErr.IntCode()] == 1 {
|
||||||
|
return platformapi.ErrLevelRecoverableErr, newErr
|
||||||
}
|
}
|
||||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ const (
|
|||||||
NotifyTypeCancelRefundComplaint = "cancelRefundComplaint" // 用户取消退款申诉
|
NotifyTypeCancelRefundComplaint = "cancelRefundComplaint" // 用户取消退款申诉
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrderPickTypeNormal = 0 // 普通(配送)
|
||||||
|
OrderPickTypeSelf = 1 // 用户到店自取
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UserApplyCancelWaitMinute = 30 // 用户申请退款后,商家未在30分钟内(大连锁商家为3小时内)处理退款请求,系统将自动同意退款
|
UserApplyCancelWaitMinute = 30 // 用户申请退款后,商家未在30分钟内(大连锁商家为3小时内)处理退款请求,系统将自动同意退款
|
||||||
)
|
)
|
||||||
@@ -308,6 +313,23 @@ type GetOrderIdByDaySeqResult struct {
|
|||||||
OrderIDs []int64 `json:"order_ids"`
|
OrderIDs []int64 `json:"order_ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserRealPhoneNumberInfo struct {
|
||||||
|
OrderID int64 `json:"order_id"`
|
||||||
|
AppPoiCode string `json:"app_poi_code"`
|
||||||
|
WmOrderIDView string `json:"wm_order_id_view"`
|
||||||
|
DaySeq int `json:"day_seq"`
|
||||||
|
RealPhoneNumber string `json:"real_phone_number"` // 订单收货人的真实手机号码
|
||||||
|
RealOrderPhoneNumber string `json:"real_order_phone_number"` // 鲜花绿植类订单预订人的真实手机号码,如无则返回空。
|
||||||
|
}
|
||||||
|
|
||||||
|
type RiderRealPhoneNumberInfo struct {
|
||||||
|
OrderID int64 `json:"order_id"`
|
||||||
|
AppPoiCode string `json:"app_poi_code"`
|
||||||
|
WmOrderIDView string `json:"wm_order_id_view"`
|
||||||
|
RiderName string `json:"rider_name"`
|
||||||
|
RiderRealPhoneNumber string `json:"rider_real_phone_number"` // 骑手真实手机号
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) OrderReceived(orderID int64) (err error) {
|
func (a *API) OrderReceived(orderID int64) (err error) {
|
||||||
_, err = a.AccessAPI("order/poi_received", true, map[string]interface{}{
|
_, err = a.AccessAPI("order/poi_received", true, map[string]interface{}{
|
||||||
KeyOrderID: orderID,
|
KeyOrderID: orderID,
|
||||||
@@ -462,8 +484,10 @@ func (a *API) OrderLogisticsStatus(orderID int64) (status map[string]interface{}
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 拉取用户真实手机号(必接)
|
||||||
|
// https://developer.waimai.meituan.com/home/docDetail/222
|
||||||
// limit最大为MaxBatchPullPhoneNumberLimit = 1000
|
// limit最大为MaxBatchPullPhoneNumberLimit = 1000
|
||||||
func (a *API) OrderBatchPullPhoneNumber(poiCode string, offset, limit int) (realNumberList []map[string]interface{}, err error) {
|
func (a *API) OrderBatchPullPhoneNumber(poiCode string, offset, limit int) (realNumberList []*UserRealPhoneNumberInfo, err error) {
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"offset": offset,
|
"offset": offset,
|
||||||
"limit": limit,
|
"limit": limit,
|
||||||
@@ -473,9 +497,27 @@ func (a *API) OrderBatchPullPhoneNumber(poiCode string, offset, limit int) (real
|
|||||||
}
|
}
|
||||||
result, err := a.AccessAPI("order/batchPullPhoneNumber", false, params)
|
result, err := a.AccessAPI("order/batchPullPhoneNumber", false, params)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
err = utils.Map2StructByJson(result, &realNumberList, false)
|
||||||
}
|
}
|
||||||
return nil, err
|
return realNumberList, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拉取骑手真实手机号(必接),美团2019-09-17才开始灰度上线
|
||||||
|
// https://developer.waimai.meituan.com/home/docDetail/388
|
||||||
|
// limit最大为MaxBatchPullPhoneNumberLimit = 1000
|
||||||
|
func (a *API) OrderGetRiderInfoPhoneNumber(poiCode string, offset, limit int) (realNumberList []*RiderRealPhoneNumberInfo, err error) {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"offset": offset,
|
||||||
|
"limit": limit,
|
||||||
|
}
|
||||||
|
if poiCode != "" {
|
||||||
|
params[KeyAppPoiCode] = poiCode
|
||||||
|
}
|
||||||
|
result, err := a.AccessAPI("order/getRiderInfoPhoneNumber", false, params)
|
||||||
|
if err == nil {
|
||||||
|
err = utils.Map2StructByJson(result, &realNumberList, false)
|
||||||
|
}
|
||||||
|
return realNumberList, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 专快混配送转为商家自配送
|
// 专快混配送转为商家自配送
|
||||||
|
|||||||
@@ -80,14 +80,19 @@ func TestOrderLogisticsStatus(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOrderBatchPullPhoneNumber(t *testing.T) {
|
func TestOrderBatchPullPhoneNumber(t *testing.T) {
|
||||||
result, err := api.OrderBatchPullPhoneNumber(testPoiCode, 0, 10)
|
result, err := api.OrderBatchPullPhoneNumber(testPoiCode, 0, MaxBatchPullPhoneNumberLimit)
|
||||||
|
t.Log(utils.Format4Output(result, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(result) == 0 {
|
}
|
||||||
t.Fatal("result should have value")
|
|
||||||
|
func TestOrderGetRiderInfoPhoneNumber(t *testing.T) {
|
||||||
|
result, err := api.OrderGetRiderInfoPhoneNumber(testPoiCode, 0, MaxBatchPullPhoneNumberLimit)
|
||||||
|
t.Log(utils.Format4Output(result, false))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
// t.Log(utils.Format4Output(result, false))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetOrderRefundDetail(t *testing.T) {
|
func TestGetOrderRefundDetail(t *testing.T) {
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ type PoiInfo struct {
|
|||||||
Utime int64 `json:"utime,omitempt"`
|
Utime int64 `json:"utime,omitempt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo 此函数在open_level与is_online开店,由于一些原因并没有成功时,好像并不会报错
|
||||||
|
// 经常会奇怪的报错:商家已接入美团配送,不可修改门店配送相关信息,但实际并没有修改任何与配送相关的东西
|
||||||
|
// 参见:https://developer.waimai.meituan.com/home/myquestionDetail/6194
|
||||||
func (a *API) PoiSave(poiCode string, poiParams map[string]interface{}) (err error) {
|
func (a *API) PoiSave(poiCode string, poiParams map[string]interface{}) (err error) {
|
||||||
_, err = a.AccessAPI("poi/save", false, utils.MergeMaps(utils.Params2Map(KeyAppPoiCode, poiCode), poiParams))
|
_, err = a.AccessAPI("poi/save", false, utils.MergeMaps(utils.Params2Map(KeyAppPoiCode, poiCode), poiParams))
|
||||||
return err
|
return err
|
||||||
@@ -150,6 +153,8 @@ func (a *API) PoiShipTimeUpdate(poiCode, shippingTime string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 美团要求必须是jpg|jpeg图片格式,且imgName必须以jpg或jpeg结尾
|
// 美团要求必须是jpg|jpeg图片格式,且imgName必须以jpg或jpeg结尾
|
||||||
|
// 此接口虽然要求poiCode参数,但经过测试,发现上传的图片可以跨门店使用
|
||||||
|
// imgName好像不支持中文,否则会报签名错
|
||||||
func (a *API) ImageUpload(poiCode, imgName string, imgData []byte) (imgID string, err error) {
|
func (a *API) ImageUpload(poiCode, imgName string, imgData []byte) (imgID string, err error) {
|
||||||
result, err := a.AccessAPI("image/upload", false, map[string]interface{}{
|
result, err := a.AccessAPI("image/upload", false, map[string]interface{}{
|
||||||
KeyAppPoiCode: poiCode,
|
KeyAppPoiCode: poiCode,
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ func TestPoiGetIDs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPoiMGet(t *testing.T) {
|
func TestPoiMGet(t *testing.T) {
|
||||||
result, err := api.PoiMGet([]string{testPoiCode})
|
result, err := api.PoiMGet([]string{"2461723"})
|
||||||
|
t.Log(utils.Format4Output(result, false))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -32,7 +33,6 @@ func TestPoiMGet(t *testing.T) {
|
|||||||
if result[0].AppPoiCode != testPoiCode {
|
if result[0].AppPoiCode != testPoiCode {
|
||||||
t.Fatal("test_poi_01 is not equal")
|
t.Fatal("test_poi_01 is not equal")
|
||||||
}
|
}
|
||||||
t.Log(utils.Format4Output(result, false))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoiSave(t *testing.T) {
|
func TestPoiSave(t *testing.T) {
|
||||||
@@ -80,3 +80,21 @@ func TestPoiStatus(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPoiShipTimeUpdate(t *testing.T) {
|
||||||
|
err := api.PoiShipTimeUpdate("7174130", "00:00-23:00")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = api.PoiOpen("6741258")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPoiOpen(t *testing.T) {
|
||||||
|
err := api.PoiOpen("6735933")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ type AppFoodResult struct {
|
|||||||
// 创建二级分类,secondaryName为二级分类名,
|
// 创建二级分类,secondaryName为二级分类名,
|
||||||
// (如果originName为空,同时创建一级分类,所以如果只是创建二级分类,originName与name要填一样的,此时sequence指的二级分类的sequence,一级分类的sequence为缺省值)
|
// (如果originName为空,同时创建一级分类,所以如果只是创建二级分类,originName与name要填一样的,此时sequence指的二级分类的sequence,一级分类的sequence为缺省值)
|
||||||
// 修改二级分类,originName为二级分类名,name为二级分类新名,secondaryName为空
|
// 修改二级分类,originName为二级分类名,name为二级分类新名,secondaryName为空
|
||||||
|
// https://developer.waimai.meituan.com/home/questionDetail/4669
|
||||||
func (a *API) RetailCatUpdate(poiCode, originName, name, secondaryName string, sequence int) (err error) {
|
func (a *API) RetailCatUpdate(poiCode, originName, name, secondaryName string, sequence int) (err error) {
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
KeyAppPoiCode: poiCode,
|
KeyAppPoiCode: poiCode,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -17,18 +18,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefClientTimeout = 15 * time.Second
|
DefClientTimeout = 30 * time.Second
|
||||||
DefSleepSecondWhenExceedLimit = 3 * time.Second
|
DefMaxSleepSecondWhenExceedLimit = 62 // 超频类错误最大重试间隙(秒)
|
||||||
DefMaxRecoverableRetryCount = 1
|
DefMaxExceedLimitRetryCount = 25 // 超频类错误最大重试次数
|
||||||
DefMaxExceedLimitRetryCount = 25
|
DefMaxRecoverableRetryCount = 1 // 可恢复类错误(一般指网络错),最大重试次数
|
||||||
|
|
||||||
KeyTrackInfo = "TrackInfo"
|
KeyTrackInfo = "TrackInfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type APIRetryConfig struct {
|
type APIRetryConfig struct {
|
||||||
MaxExceedLimitRetryCount int
|
MaxExceedLimitRetryCount int
|
||||||
MaxRecoverableRetryCount int
|
MaxRecoverableRetryCount int
|
||||||
SleepSecondWhenExceedLimit time.Duration
|
MaxSleepSecondWhenExceedLimit int
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIConfig struct {
|
type APIConfig struct {
|
||||||
@@ -45,9 +46,9 @@ type AccessPlatformAPIWithRetryParam struct {
|
|||||||
var (
|
var (
|
||||||
DefAPIConfig = APIConfig{
|
DefAPIConfig = APIConfig{
|
||||||
APIRetryConfig: APIRetryConfig{
|
APIRetryConfig: APIRetryConfig{
|
||||||
MaxExceedLimitRetryCount: DefMaxExceedLimitRetryCount,
|
MaxExceedLimitRetryCount: DefMaxExceedLimitRetryCount,
|
||||||
MaxRecoverableRetryCount: DefMaxRecoverableRetryCount,
|
MaxRecoverableRetryCount: DefMaxRecoverableRetryCount,
|
||||||
SleepSecondWhenExceedLimit: DefSleepSecondWhenExceedLimit,
|
MaxSleepSecondWhenExceedLimit: DefMaxSleepSecondWhenExceedLimit,
|
||||||
},
|
},
|
||||||
ClientTimeout: DefClientTimeout,
|
ClientTimeout: DefClientTimeout,
|
||||||
}
|
}
|
||||||
@@ -90,6 +91,11 @@ func getClonedData(requestURL *url.URL, r *bytes.Buffer) string {
|
|||||||
return retVal
|
return retVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDefAPIConfig() (conf *APIConfig) {
|
||||||
|
obj := DefAPIConfig
|
||||||
|
return &obj
|
||||||
|
}
|
||||||
|
|
||||||
func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.Request, config *APIConfig, handleResponse func(response *http.Response, bodyStr string, bodyMap map[string]interface{}) (string, error)) error {
|
func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.Request, config *APIConfig, handleResponse func(response *http.Response, bodyStr string, bodyMap map[string]interface{}) (string, error)) error {
|
||||||
exceedLimitRetryCount := 0
|
exceedLimitRetryCount := 0
|
||||||
recoverableErrorRetryCount := 0
|
recoverableErrorRetryCount := 0
|
||||||
@@ -101,12 +107,10 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
|
|||||||
}
|
}
|
||||||
beginTime := time.Now()
|
beginTime := time.Now()
|
||||||
trackInfo := request.Header.Get(KeyTrackInfo)
|
trackInfo := request.Header.Get(KeyTrackInfo)
|
||||||
if trackInfo == "" {
|
if trackInfo != "" {
|
||||||
trackInfo = utils.GetUUID()
|
|
||||||
// request.Header.Set(KeyTrackInfo, trackID)
|
|
||||||
} else {
|
|
||||||
request.Header.Del(KeyTrackInfo)
|
request.Header.Del(KeyTrackInfo)
|
||||||
}
|
}
|
||||||
|
trackInfo += ", " + utils.GetUUID()
|
||||||
baseapi.SugarLogger.Debugf("begin AccessPlatformAPIWithRetry:%s do:%s url:%v", trackInfo, request.Method, request.URL)
|
baseapi.SugarLogger.Debugf("begin AccessPlatformAPIWithRetry:%s do:%s url:%v", trackInfo, request.Method, request.URL)
|
||||||
response, err := client.Do(request)
|
response, err := client.Do(request)
|
||||||
baseapi.SugarLogger.Debugf("end AccessPlatformAPIWithRetry:%s do url:%v, request:%s", trackInfo, request.URL, getClonedData(request.URL, savedBuf))
|
baseapi.SugarLogger.Debugf("end AccessPlatformAPIWithRetry:%s do url:%v, request:%s", trackInfo, request.URL, getClonedData(request.URL, savedBuf))
|
||||||
@@ -174,7 +178,11 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
|
|||||||
} else if errLevel == ErrLevelExceedLimit {
|
} else if errLevel == ErrLevelExceedLimit {
|
||||||
exceedLimitRetryCount++
|
exceedLimitRetryCount++
|
||||||
if exceedLimitRetryCount <= config.MaxExceedLimitRetryCount {
|
if exceedLimitRetryCount <= config.MaxExceedLimitRetryCount {
|
||||||
time.Sleep(config.SleepSecondWhenExceedLimit)
|
sleepSeconds := int(math.Exp2(float64(exceedLimitRetryCount)))
|
||||||
|
if sleepSeconds > config.MaxSleepSecondWhenExceedLimit {
|
||||||
|
sleepSeconds = config.MaxSleepSecondWhenExceedLimit
|
||||||
|
}
|
||||||
|
time.Sleep(time.Duration(sleepSeconds) * time.Second)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if errLevel == ErrLevelRecoverableErr {
|
} else if errLevel == ErrLevelRecoverableErr {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type APICookie struct {
|
type APICookie struct {
|
||||||
locker sync.RWMutex
|
sync.RWMutex
|
||||||
storeCookies map[string]string
|
storeCookies map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,28 +44,28 @@ func (a *APICookie) SetCookieWithStr(cookieStr string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *APICookie) SetCookie(key, value string) {
|
func (a *APICookie) SetCookie(key, value string) {
|
||||||
a.locker.Lock()
|
a.Lock()
|
||||||
defer a.locker.Unlock()
|
defer a.Unlock()
|
||||||
a.createMapIfNeeded()
|
a.createMapIfNeeded()
|
||||||
a.storeCookies[key] = value
|
a.storeCookies[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APICookie) GetCookie(key string) string {
|
func (a *APICookie) GetCookie(key string) string {
|
||||||
a.locker.RLock()
|
a.RLock()
|
||||||
defer a.locker.RUnlock()
|
defer a.RUnlock()
|
||||||
a.createMapIfNeeded()
|
a.createMapIfNeeded()
|
||||||
return a.storeCookies[key]
|
return a.storeCookies[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APICookie) GetCookieCount() int {
|
func (a *APICookie) GetCookieCount() int {
|
||||||
a.locker.RLock()
|
a.RLock()
|
||||||
defer a.locker.RUnlock()
|
defer a.RUnlock()
|
||||||
return len(a.storeCookies)
|
return len(a.storeCookies)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APICookie) FillRequestCookies(r *http.Request) *http.Request {
|
func (a *APICookie) FillRequestCookies(r *http.Request) *http.Request {
|
||||||
a.locker.RLock()
|
a.RLock()
|
||||||
defer a.locker.RUnlock()
|
defer a.RUnlock()
|
||||||
for k, v := range a.storeCookies {
|
for k, v := range a.storeCookies {
|
||||||
r.AddCookie(&http.Cookie{
|
r.AddCookie(&http.Cookie{
|
||||||
Name: k,
|
Name: k,
|
||||||
|
|||||||
@@ -56,6 +56,15 @@ type TokenInfo struct {
|
|||||||
MachineCode string `json:"machine_code"`
|
MachineCode string `json:"machine_code"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PrinterOrderResult struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
OriginID string `json:"origin_id"`
|
||||||
|
PrintTime string `json:"print_time"`
|
||||||
|
ReceivingTime string `json:"receiving_time"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
func New(clientID, clientSecret string, config ...*platformapi.APIConfig) *API {
|
func New(clientID, clientSecret string, config ...*platformapi.APIConfig) *API {
|
||||||
curConfig := platformapi.DefAPIConfig
|
curConfig := platformapi.DefAPIConfig
|
||||||
if len(config) > 0 {
|
if len(config) > 0 {
|
||||||
@@ -238,7 +247,6 @@ func (a *API) GetPrinterToken(machineCode, qrKey string) (tokenInfo *TokenInfo,
|
|||||||
}, "")
|
}, "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = utils.Map2StructByJson(result, &tokenInfo, false)
|
err = utils.Map2StructByJson(result, &tokenInfo, false)
|
||||||
a.SetToken(tokenInfo.AccessToken)
|
|
||||||
}
|
}
|
||||||
return tokenInfo, err
|
return tokenInfo, err
|
||||||
}
|
}
|
||||||
@@ -257,3 +265,16 @@ func (a *API) CancelAll(machineCode, token string) (err error) {
|
|||||||
func (a *API) PlayText(machineCode, orderID, text, token string) (err error) {
|
func (a *API) PlayText(machineCode, orderID, text, token string) (err error) {
|
||||||
return a.printMsg(machineCode, orderID, fmt.Sprintf("<audio>%s,9,0</audio>", strings.Replace(text, ",", ".", -1)), token)
|
return a.printMsg(machineCode, orderID, fmt.Sprintf("<audio>%s,9,0</audio>", strings.Replace(text, ",", ".", -1)), token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pageIndex从1开始,pageSize最大为100
|
||||||
|
func (a *API) GetOrderPagingList(machineCode, token string, pageIndex, pageSize int) (orderResultList []*PrinterOrderResult, err error) {
|
||||||
|
result, err := a.AccessAPI("printer/getorderpaginglist", map[string]interface{}{
|
||||||
|
"machine_code": machineCode,
|
||||||
|
"page_index": pageIndex,
|
||||||
|
"page_size": pageSize,
|
||||||
|
}, token)
|
||||||
|
if err != nil {
|
||||||
|
err = utils.Map2StructByJson(result, &orderResultList, false)
|
||||||
|
}
|
||||||
|
return orderResultList, err
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func init() {
|
|||||||
|
|
||||||
// 自有应用
|
// 自有应用
|
||||||
api = New("1039586024", "4885d07c2997b661102e4b6099c0bf3b")
|
api = New("1039586024", "4885d07c2997b661102e4b6099c0bf3b")
|
||||||
api.SetToken("7884617f9eeb4c28933569f94a95b5c3")
|
api.SetToken("3a38e3cec7974b459a6f0a381c9b0312")
|
||||||
|
|
||||||
// 开放应用
|
// 开放应用
|
||||||
// api = New("1098307169", "d5eedb40c99e6691b1ca2ba82a363d6a")
|
// api = New("1098307169", "d5eedb40c99e6691b1ca2ba82a363d6a")
|
||||||
@@ -42,19 +42,19 @@ func TestRetrieveToken(t *testing.T) {
|
|||||||
|
|
||||||
func TestAddPrinter(t *testing.T) {
|
func TestAddPrinter(t *testing.T) {
|
||||||
// err := api.AddPrinter("4004600675", "fem2ukwvduik", "公司测试打印机1")
|
// err := api.AddPrinter("4004600675", "fem2ukwvduik", "公司测试打印机1")
|
||||||
// 4004617180 公司测试打印机2
|
// 4004617180, 381870509796 公司测试打印机2
|
||||||
err := api.AddPrinter("4004600675", "fem2ukwvduik", "测试打印机1")
|
err := api.AddPrinter("4004615546", "7nxsw668yqtk", "测试打印机1")
|
||||||
handleError(t, err)
|
handleError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeletePrinter(t *testing.T) {
|
func TestDeletePrinter(t *testing.T) {
|
||||||
err := api.DeletePrinter("4004611945")
|
err := api.DeletePrinter("4004615546")
|
||||||
handleError(t, err)
|
handleError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrintMsg(t *testing.T) {
|
func TestPrintMsg(t *testing.T) {
|
||||||
// 4004606481
|
// 4004606481
|
||||||
err := api.PrintMsg("4004600675", utils.GetUUID(), "<FS2>饿百取货码</FS2>")
|
err := api.PrintMsg("4004615546", utils.GetUUID(), "<FS2>饿百取货码</FS2>")
|
||||||
handleError(t, err)
|
handleError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,13 +65,13 @@ func TestPrintMsgWithToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetPrintStatus(t *testing.T) {
|
func TestGetPrintStatus(t *testing.T) {
|
||||||
state, err := api.GetPrintStatus("4004617180")
|
state, err := api.GetPrintStatus("4004615546")
|
||||||
handleError(t, err)
|
handleError(t, err)
|
||||||
baseapi.SugarLogger.Debug(state)
|
baseapi.SugarLogger.Debug(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetPrintStatusWithToken(t *testing.T) {
|
func TestGetPrintStatusWithToken(t *testing.T) {
|
||||||
state, err := api.GetPrintStatusWithToken("4004600675", "b1a36aa8de5647d2b08af49db11a9c9d")
|
state, err := api.GetPrintStatusWithToken("4004617242", "88de89a384714436a5d1ca23e8991e15")
|
||||||
handleError(t, err)
|
handleError(t, err)
|
||||||
baseapi.SugarLogger.Debug(state)
|
baseapi.SugarLogger.Debug(state)
|
||||||
}
|
}
|
||||||
@@ -91,3 +91,15 @@ func TestPlayText(t *testing.T) {
|
|||||||
err := api.PlayText("4004617180", utils.GetUUID(), "我们已安排%s配送员%s负责配送。^_^", "")
|
err := api.PlayText("4004617180", utils.GetUUID(), "我们已安排%s配送员%s负责配送。^_^", "")
|
||||||
handleError(t, err)
|
handleError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRefreshToken(t *testing.T) {
|
||||||
|
tokenInfo, err := api.RefreshToken("c565a8983887488eb2a708ca118ce43c")
|
||||||
|
handleError(t, err)
|
||||||
|
t.Log(utils.Format4Output(tokenInfo, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOrderPagingList(t *testing.T) {
|
||||||
|
result, err := api.GetOrderPagingList("4004613792", "", 1, 50)
|
||||||
|
handleError(t, err)
|
||||||
|
t.Log(utils.Format4Output(result, true))
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi"
|
"git.rosy.net.cn/baseapi"
|
||||||
"github.com/fatih/structs"
|
"github.com/gazeboxu/structs"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -70,15 +71,22 @@ func TryInterface2Int64(data interface{}) (num int64, err error) {
|
|||||||
if dataNumber, ok := data.(int); ok {
|
if dataNumber, ok := data.(int); ok {
|
||||||
return int64(dataNumber), nil
|
return int64(dataNumber), nil
|
||||||
}
|
}
|
||||||
dataNumber, ok := data.(json.Number)
|
if dataNumber, ok := data.(int32); ok {
|
||||||
if !ok {
|
return int64(dataNumber), nil
|
||||||
return 0, fmt.Errorf("data is not json.Number:%v to int64", data)
|
|
||||||
}
|
}
|
||||||
retVal, err := dataNumber.Int64()
|
if dataNumber, ok := data.(int16); ok {
|
||||||
if err != nil {
|
return int64(dataNumber), nil
|
||||||
return num, err
|
|
||||||
}
|
}
|
||||||
return retVal, nil
|
if dataNumber, ok := data.(int8); ok {
|
||||||
|
return int64(dataNumber), nil
|
||||||
|
}
|
||||||
|
if dataNumber, ok := data.(json.Number); ok {
|
||||||
|
return dataNumber.Int64()
|
||||||
|
}
|
||||||
|
if str, ok := data.(string); ok {
|
||||||
|
return Str2Int64WithDefault(str, 0), nil
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("data is not json.Number, it's %s, value:%v", reflect.TypeOf(data).String(), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustInterface2Int64(data interface{}) int64 {
|
func MustInterface2Int64(data interface{}) int64 {
|
||||||
@@ -114,15 +122,13 @@ func TryInterface2Float64(data interface{}) (num float64, err error) {
|
|||||||
if dataNumber, ok := data.(float32); ok {
|
if dataNumber, ok := data.(float32); ok {
|
||||||
return float64(dataNumber), nil
|
return float64(dataNumber), nil
|
||||||
}
|
}
|
||||||
dataNumber, ok := data.(json.Number)
|
if dataNumber, ok := data.(json.Number); ok {
|
||||||
if !ok {
|
return dataNumber.Float64()
|
||||||
return num, fmt.Errorf("data is not json.Number:%v", data)
|
|
||||||
}
|
}
|
||||||
retVal, err := dataNumber.Float64()
|
if str, ok := data.(string); ok {
|
||||||
if err != nil {
|
return Str2Float64WithDefault(str, 0), nil
|
||||||
return num, err
|
|
||||||
}
|
}
|
||||||
return retVal, nil
|
return 0, fmt.Errorf("data is not json.Number, it's %s, value:%v", reflect.TypeOf(data).String(), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustInterface2Float64(data interface{}) float64 {
|
func MustInterface2Float64(data interface{}) float64 {
|
||||||
@@ -329,6 +335,10 @@ func IsTimeZero(timeValue time.Time) bool {
|
|||||||
return timeValue == DefaultTimeValue || timeValue == ZeroTimeValue
|
return timeValue == DefaultTimeValue || timeValue == ZeroTimeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsPtrTimeZero(timePtr *time.Time) bool {
|
||||||
|
return timePtr == nil || *timePtr == DefaultTimeValue || *timePtr == ZeroTimeValue
|
||||||
|
}
|
||||||
|
|
||||||
func HTTPBody2Values(data []byte, needDecode bool) (url.Values, error) {
|
func HTTPBody2Values(data []byte, needDecode bool) (url.Values, error) {
|
||||||
bodyStr := string(data)
|
bodyStr := string(data)
|
||||||
if needDecode {
|
if needDecode {
|
||||||
@@ -443,36 +453,22 @@ func MergeMaps(firstMap map[string]interface{}, otherMaps ...map[string]interfac
|
|||||||
return retVal
|
return retVal
|
||||||
}
|
}
|
||||||
|
|
||||||
func Struct2MapByJson(obj interface{}) (mapData map[string]interface{}) {
|
func Struct2Map(obj interface{}, tagName string, isFlattenAnonymous bool) (mapData map[string]interface{}) {
|
||||||
|
if tagName == "" {
|
||||||
|
tagName = "json"
|
||||||
|
}
|
||||||
structsObj := structs.New(obj)
|
structsObj := structs.New(obj)
|
||||||
structsObj.TagName = "json"
|
structsObj.TagName = tagName
|
||||||
|
structsObj.IsFlattenAnonymous = true
|
||||||
return structsObj.Map()
|
return structsObj.Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 此函数将MAP中所有的子MAP中的数据提升到最上层,相同字段会覆盖父MAP的
|
func Struct2MapByJson(obj interface{}) (mapData map[string]interface{}) {
|
||||||
func FlatMap(in map[string]interface{}) map[string]interface{} {
|
return Struct2Map(obj, "", false)
|
||||||
keys := []string{}
|
|
||||||
maps := []map[string]interface{}{}
|
|
||||||
for k, v := range in {
|
|
||||||
if vMap, ok := v.(map[string]interface{}); ok {
|
|
||||||
vMap = FlatMap(vMap)
|
|
||||||
maps = append(maps, vMap)
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(maps) > 0 {
|
|
||||||
retVal := MergeMaps(in, maps...)
|
|
||||||
for _, v := range keys {
|
|
||||||
delete(retVal, v)
|
|
||||||
}
|
|
||||||
return retVal
|
|
||||||
}
|
|
||||||
return in
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Struct2FlatMap(obj interface{}) map[string]interface{} {
|
func Struct2FlatMap(obj interface{}) map[string]interface{} {
|
||||||
m := Struct2MapByJson(obj)
|
return Struct2Map(obj, "", true)
|
||||||
return FlatMap(m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// !!! 此函数好像不支持struct是内嵌结构的
|
// !!! 此函数好像不支持struct是内嵌结构的
|
||||||
|
|||||||
@@ -84,3 +84,40 @@ func TestTime(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStruct2MapByJson(t *testing.T) {
|
||||||
|
type InnerKK struct {
|
||||||
|
IntData int
|
||||||
|
StrData string
|
||||||
|
ObjData time.Time
|
||||||
|
}
|
||||||
|
type KK struct {
|
||||||
|
IntData int
|
||||||
|
A int
|
||||||
|
B string
|
||||||
|
C time.Time
|
||||||
|
InnerKK
|
||||||
|
InnerKK2 InnerKK
|
||||||
|
}
|
||||||
|
kk := &KK{
|
||||||
|
InnerKK: InnerKK{
|
||||||
|
IntData: 1,
|
||||||
|
StrData: "hello",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
mapData := Struct2MapByJson(kk)
|
||||||
|
t.Log(Format4Output(mapData, false))
|
||||||
|
// t.Log(mapData)
|
||||||
|
// t.Log(kk)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func TestStruct2MapByJson(t *testing.T) {
|
||||||
|
// mapData := Struct2MapByJson(&struct {
|
||||||
|
// IntData int `structs:"dataInt"`
|
||||||
|
// StrData string `json:"-"`
|
||||||
|
// }{
|
||||||
|
// IntData: 1,
|
||||||
|
// StrData: "2",
|
||||||
|
// })
|
||||||
|
// t.Log(mapData)
|
||||||
|
// }
|
||||||
|
|||||||
@@ -175,17 +175,6 @@ func TestTrimBlanChar(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStruct2MapByJson(t *testing.T) {
|
|
||||||
mapData := Struct2MapByJson(&struct {
|
|
||||||
IntData int `structs:"dataInt"`
|
|
||||||
StrData string `json:"-"`
|
|
||||||
}{
|
|
||||||
IntData: 1,
|
|
||||||
StrData: "2",
|
|
||||||
})
|
|
||||||
t.Log(mapData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLimitUTF8StringLen(t *testing.T) {
|
func TestLimitUTF8StringLen(t *testing.T) {
|
||||||
for _, v := range [][]interface{}{
|
for _, v := range [][]interface{}{
|
||||||
[]interface{}{
|
[]interface{}{
|
||||||
|
|||||||
69
utils/utils_type.go
Normal file
69
utils/utils_type.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func String2Pointer(value string) *string {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pointer2String(ptr *string) (value string) {
|
||||||
|
if ptr != nil {
|
||||||
|
value = *ptr
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int2Pointer(value int) *int {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pointer2Int(ptr *int) (value int) {
|
||||||
|
if ptr != nil {
|
||||||
|
value = *ptr
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Int64ToPointer(value int64) *int64 {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pointer2Int64(ptr *int64) (value int64) {
|
||||||
|
if ptr != nil {
|
||||||
|
value = *ptr
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float32ToPointer(value float32) *float32 {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pointer2Float32(ptr *float32) (value float32) {
|
||||||
|
if ptr != nil {
|
||||||
|
value = *ptr
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float64ToPointer(value float64) *float64 {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pointer2Float64(ptr *float64) (value float64) {
|
||||||
|
if ptr != nil {
|
||||||
|
value = *ptr
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Time2Pointer(value time.Time) *time.Time {
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pointer2Time(ptr *time.Time) (value time.Time) {
|
||||||
|
if ptr != nil {
|
||||||
|
value = *ptr
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user