Merge branch 'master' into get-store
This commit is contained in:
@@ -137,7 +137,7 @@ func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal Re
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
status := jsonResult1["status"].(string)
|
||||
if status == StatusCodeSuccess {
|
||||
retVal = jsonResult1
|
||||
@@ -179,11 +179,7 @@ func (a *API) CoordinateConvert(lng, lat float64, coordsys string) (retLng, retL
|
||||
|
||||
// 这里的District指的是实际的District,有些市是没有区的,比如东莞,这种情况下返回的区码是一个假的区域,即市的编码加上9000000
|
||||
func (a *API) GetCoordinateDistrictCode(lng, lat float64) (districtCode int) {
|
||||
params := map[string]interface{}{
|
||||
"location": fmt.Sprintf("%.6f,%.6f", lng, lat),
|
||||
}
|
||||
result, err := a.AccessAPI("geocode/regeo", params)
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
result, err := a.GetCoordinateAreaInfo(lng, lat)
|
||||
if err == nil {
|
||||
addressComponent := result["regeocode"].(map[string]interface{})["addressComponent"].(map[string]interface{})
|
||||
if strAdcode, ok := addressComponent["adcode"].(string); ok {
|
||||
@@ -196,6 +192,25 @@ func (a *API) GetCoordinateDistrictCode(lng, lat float64) (districtCode int) {
|
||||
return districtCode
|
||||
}
|
||||
|
||||
func (a *API) GetCoordinateAreaInfo(lng, lat float64) (areaInfo map[string]interface{}, err error) {
|
||||
params := map[string]interface{}{
|
||||
"location": fmt.Sprintf("%.6f,%.6f", lng, lat),
|
||||
}
|
||||
result, err := a.AccessAPI("geocode/regeo", params)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (a *API) GetCoordinateTownInfo(lng, lat float64) (townName, townCode string) {
|
||||
result, err := a.GetCoordinateAreaInfo(lng, lat)
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
if err == nil {
|
||||
addressComponent := result["regeocode"].(map[string]interface{})["addressComponent"].(map[string]interface{})
|
||||
townName = utils.Interface2String(addressComponent["township"])
|
||||
townCode = utils.Interface2String(addressComponent["towncode"])
|
||||
}
|
||||
return townName, townCode
|
||||
}
|
||||
|
||||
// 这里的District指的是地点,不是实际上的区,具体级别看level
|
||||
// 这个函数返回的可能不是同级别的地点
|
||||
func (a *API) GetDistricts(subDistrict int, keywords string) (districtList []*District, err error) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -63,13 +64,22 @@ func TestGetCoordinateDistrictCode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCoordinateTownInfo(t *testing.T) {
|
||||
dongguanLng := 120.74567
|
||||
dongguanLat := 31.69742
|
||||
townName, townCode := autonaviAPI.GetCoordinateTownInfo(dongguanLng, dongguanLat)
|
||||
if townName != "周市镇" || townCode != "320583102000" {
|
||||
t.Fatalf("townName:%s, townCode:%s", townName, townCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDistricts(t *testing.T) {
|
||||
districtList, err := autonaviAPI.GetDistricts(1, "东莞")
|
||||
districtList, err := autonaviAPI.GetDistricts(4, "常熟市")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(districtList) == 0 {
|
||||
t.Fatal("should have ditrict")
|
||||
}
|
||||
// t.Log(utils.Format4Output(districtList, false))
|
||||
t.Log(utils.Format4Output(districtList, false))
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ func (a *API) AccessAPI(action string, params interface{}) (retVal *ResponseResu
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
code := int(utils.MustInterface2Int64(jsonResult1["code"]))
|
||||
retVal = &ResponseResult{
|
||||
Code: code,
|
||||
|
||||
@@ -112,8 +112,8 @@ func (a *API) Decrypt(msg string) (decryptedMsg string, err error) {
|
||||
|
||||
func (a *API) RegisterCallback(callbackTagList []string, token, aesKey, urlStr string) (err error) {
|
||||
a.locker.Lock()
|
||||
oldCallbackToken := a.callbackToken
|
||||
oldCallbackAESKey := a.callbackAESKey
|
||||
// oldCallbackToken := a.callbackToken
|
||||
// oldCallbackAESKey := a.callbackAESKey
|
||||
a.callbackToken = token
|
||||
a.callbackAESKey, _ = base64.StdEncoding.DecodeString(aesKey + "=")
|
||||
a.locker.Unlock()
|
||||
@@ -126,12 +126,12 @@ func (a *API) RegisterCallback(callbackTagList []string, token, aesKey, urlStr s
|
||||
"url": urlStr,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
a.locker.Lock()
|
||||
defer a.locker.Unlock()
|
||||
a.callbackToken = oldCallbackToken
|
||||
a.callbackAESKey = oldCallbackAESKey
|
||||
}
|
||||
// if err != nil {
|
||||
// a.locker.Lock()
|
||||
// defer a.locker.Unlock()
|
||||
// a.callbackToken = oldCallbackToken
|
||||
// a.callbackAESKey = oldCallbackAESKey
|
||||
// }
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ func (a *API) AccessAPI(action string, params map[string]interface{}, bodyMap ma
|
||||
params2["access_token"] = accessToken
|
||||
} else {
|
||||
params2["accessKey"] = a.GetAppID()
|
||||
timestamp := time.Now().Unix()
|
||||
timestamp := time.Now().UnixNano() / 1000000
|
||||
params2["timestamp"] = timestamp
|
||||
params2["signature"] = a.signParams(timestamp)
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func (a *API) AccessAPI(action string, params map[string]interface{}, bodyMap ma
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
errCode := int(utils.MustInterface2Int64(jsonResult1["errcode"]))
|
||||
if errCode == ResponseCodeSuccess {
|
||||
retVal = jsonResult1
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ebaiapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
@@ -11,15 +10,17 @@ const (
|
||||
ActivityTypeDirectDown = 2 // 商品直降
|
||||
ActivityTypeFullDiscount = 8 // 品类满减
|
||||
|
||||
ActivityPFBaidu = 1
|
||||
ActivityPFELM = 2
|
||||
ActivityPFAll = 4
|
||||
ActivityPFBaidu = 1 // 星选
|
||||
ActivityPFELM = 2 // 饿了么
|
||||
ActivityPFAll = 4 // 星选&饿了么
|
||||
|
||||
ActivityConflictShare = 0
|
||||
ActivityConfilictExclude = 1
|
||||
ActivityConflictShare = 0 // 与全店满减等其他活动同享
|
||||
ActivityConfilictExclude = 1 // 与全店满减等其他活动互斥
|
||||
|
||||
ActivityShowStatusEnabled = 2
|
||||
ActivityShowStatusDisabled = 4
|
||||
MaxActivitySkuBatchSize = 100 // 使用商品id的活动商品,与商品自定义id互斥。一批最多100个
|
||||
// 下面两个是做什么用的?
|
||||
// ActivityShowStatusEnabled = 2
|
||||
// ActivityShowStatusDisabled = 4
|
||||
)
|
||||
|
||||
type ActivityRule struct {
|
||||
@@ -45,40 +46,50 @@ type ActivityInfo struct {
|
||||
PromotionSkuDesc string `json:"promotion_sku_desc,omitempty"` // 店铺页活动商品的分类名称,不超过8个字。
|
||||
Rule []*ActivityRule `json:"rule,omitempty"`
|
||||
|
||||
BaiduShopID int64 `json:"baiduShopID,omitempty"`
|
||||
ShowStatus int `json:"showStatus,omitempty"`
|
||||
BaiduShopID int64 `json:"baidu_shop_id,omitempty"` // 这个用于查询时返回值,设置时这里设置的值会被忽略
|
||||
// ShowStatus int `json:"showStatus,omitempty"`
|
||||
}
|
||||
|
||||
type ActivitySkuInfo struct {
|
||||
type ActivitySkuInfo4Add struct {
|
||||
SkuID string `json:"sku_id"`
|
||||
Stock int `json:"stock"`
|
||||
|
||||
PromotionPrice float32 `json:"special_price"` // 直降用,复用
|
||||
StoreUserLimit int `json:"store_user_limit"` // 直降用
|
||||
StoreUserLimit int `json:"store_user_limit"`
|
||||
SpecialPrice int64 `json:"special_price"`
|
||||
}
|
||||
|
||||
type ActivitySkuInfoEx struct {
|
||||
ActivitySkuInfo
|
||||
BaiduShopID int64 `json:"baidu_shop_id"`
|
||||
UpcName string `json:"upc_name"`
|
||||
OriginalPrice float32 `json:"original_price"`
|
||||
type ActivitySkuInfo4List struct {
|
||||
BaiduShopID int64 `json:"baidu_shop_id"`
|
||||
SkuID string `json:"sku_id"`
|
||||
UpcName string `json:"upc_name"`
|
||||
Stock int `json:"stock"`
|
||||
|
||||
PromotionPrice float32 `json:"promotion_price"` // 商品活动价,单位元,品类满减活动不返回活动价。
|
||||
OriginalPrice float32 `json:"original_price"` // 添加商品时商品原价,单位元。
|
||||
}
|
||||
|
||||
type ActivitySkuInfo4Update struct {
|
||||
ActivitySkuInfo
|
||||
BaiduShopID int64 `json:"baidu_shop_id"`
|
||||
ShopID string `json:"shop_id"`
|
||||
CustomSkuID string `json:"custom_sku_id"`
|
||||
BaiduShopID int64 `json:"baidu_shop_id,omitempty"`
|
||||
ShopID string `json:"shop_id,omitempty"`
|
||||
SkuID string `json:"sku_id,omitempty"`
|
||||
CustomSkuID string `json:"custom_sku_id,omitempty"`
|
||||
Stock int `json:"stock,omitempty"`
|
||||
|
||||
StoreUserLimit int `json:"store_user_limit,omitempty"`
|
||||
SpecialPrice int64 `json:"special_price,omitempty"`
|
||||
}
|
||||
|
||||
type ActivitySkuListInfo struct {
|
||||
ActivityID int64 `json:"activity_id"`
|
||||
ActivityType int `json:"activity_type"`
|
||||
ActivityName string `json:"activity_name"`
|
||||
SkuList []*ActivitySkuInfoEx `json:"sku_list"`
|
||||
ActivityID int64 `json:"activity_id"`
|
||||
ActivityType int `json:"activity_type"`
|
||||
ActivityName string `json:"activity_name"`
|
||||
SkuList []*ActivitySkuInfo4List `json:"sku_list"`
|
||||
}
|
||||
|
||||
// 创建商品营销活动
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_create
|
||||
func (a *API) ActivityCreate(shopID string, baiduShopID, supplierID int64, activity *ActivityInfo) (activityID int64, err error) {
|
||||
activity.BaiduShopID = 0
|
||||
params := utils.Struct2FlatMap(activity)
|
||||
result, err := a.AccessAPI("activity.create", utils.MergeMaps(params, a.genShopIDParams(shopID, baiduShopID, supplierID)))
|
||||
if err == nil {
|
||||
@@ -87,7 +98,10 @@ func (a *API) ActivityCreate(shopID string, baiduShopID, supplierID int64, activ
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 更新活动信息
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_update
|
||||
func (a *API) ActivityUpdate(activityID int64, shopID string, baiduShopID, supplierID int64, activity *ActivityInfo) (newActivityID int64, err error) {
|
||||
activity.BaiduShopID = 0
|
||||
params := utils.Struct2FlatMap(activity)
|
||||
params[KeyActivityID] = activityID
|
||||
result, err := a.AccessAPI("activity.update", utils.MergeMaps(params, a.genShopIDParams(shopID, baiduShopID, supplierID)))
|
||||
@@ -97,6 +111,8 @@ func (a *API) ActivityUpdate(activityID int64, shopID string, baiduShopID, suppl
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 下线商品营销活动
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_disable
|
||||
func (a *API) ActivityDisable(activityID int64, shopID string, baiduShopID, supplierID int64) (err error) {
|
||||
params := a.genShopIDParams(shopID, baiduShopID, supplierID)
|
||||
params[KeyActivityID] = activityID
|
||||
@@ -104,6 +120,8 @@ func (a *API) ActivityDisable(activityID int64, shopID string, baiduShopID, supp
|
||||
return err
|
||||
}
|
||||
|
||||
// 查看活动信息
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_get
|
||||
func (a *API) ActivityGet(activityID int64, shopID string, baiduShopID, supplierID int64) (activityInfo *ActivityInfo, err error) {
|
||||
params := a.genShopIDParams(shopID, baiduShopID, supplierID)
|
||||
params[KeyActivityID] = activityID
|
||||
@@ -115,7 +133,9 @@ func (a *API) ActivityGet(activityID int64, shopID string, baiduShopID, supplier
|
||||
return activityInfo, err
|
||||
}
|
||||
|
||||
func (a *API) ActivitySkuAddBatch(activityID int64, shopID string, baiduShopID int64, activityType int, skuList []*ActivitySkuInfo, isSkuIDCustom bool) (successIDs []string, err error) {
|
||||
// 批量添加活动商品
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_sku_add_batch
|
||||
func (a *API) ActivitySkuAddBatch(activityID int64, shopID string, baiduShopID int64, activityType int, skuList []*ActivitySkuInfo4Add, isSkuIDCustom bool) (successIDs []string, err error) {
|
||||
params := a.genShopIDParams(shopID, baiduShopID, 0)
|
||||
params[KeyActivityID] = activityID
|
||||
skusKey := "activity_skus"
|
||||
@@ -130,7 +150,7 @@ func (a *API) ActivitySkuAddBatch(activityID int64, shopID string, baiduShopID i
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func skuList2Str(activityType int, skuList []*ActivitySkuInfo, isSkuIDCustom bool) string {
|
||||
func skuList2Str(activityType int, skuList []*ActivitySkuInfo4Add, isSkuIDCustom bool) string {
|
||||
skuList2 := []string{}
|
||||
for _, v := range skuList {
|
||||
strList := []string{
|
||||
@@ -138,14 +158,18 @@ func skuList2Str(activityType int, skuList []*ActivitySkuInfo, isSkuIDCustom boo
|
||||
utils.Int2Str(v.Stock),
|
||||
}
|
||||
if activityType == ActivityTypeDirectDown {
|
||||
strList = append(strList, fmt.Sprintf("%.2f", v.PromotionPrice))
|
||||
strList = append(strList, utils.Int2Str(v.StoreUserLimit))
|
||||
strList = append(strList, utils.Int64ToStr(v.SpecialPrice))
|
||||
if v.StoreUserLimit > 0 {
|
||||
strList = append(strList, utils.Int2Str(v.StoreUserLimit))
|
||||
}
|
||||
}
|
||||
skuList2 = append(skuList2, strings.Join(strList, ":"))
|
||||
}
|
||||
return strings.Join(skuList2, ";")
|
||||
}
|
||||
|
||||
// 批量删除活动商品
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_sku_delete_batch
|
||||
func (a *API) ActivitySkuDeleteBatch(activityID int64, shopID string, baiduShopID int64, skuIDs []string, isSkuIDCustom bool) (successIDs []string, err error) {
|
||||
params := a.genShopIDParams(shopID, baiduShopID, 0)
|
||||
params[KeyActivityID] = activityID
|
||||
@@ -161,6 +185,8 @@ func (a *API) ActivitySkuDeleteBatch(activityID int64, shopID string, baiduShopI
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 批量添加活动商品
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_sku_add_batch
|
||||
func (a *API) ActivitySkuList(activityID int64, shopID string, baiduShopID, supplierID int64, skuIDs []string, isSkuIDCustom bool) (activityInfo *ActivitySkuListInfo, err error) {
|
||||
params := a.genShopIDParams(shopID, baiduShopID, supplierID)
|
||||
params[KeyActivityID] = activityID
|
||||
@@ -179,35 +205,17 @@ func (a *API) ActivitySkuList(activityID int64, shopID string, baiduShopID, supp
|
||||
params["page"] = page
|
||||
result, err = a.AccessAPI("activity.sku.list", params)
|
||||
if err == nil {
|
||||
// tmpActivityInfo := &ActivitySkuListInfo{}
|
||||
// if err = utils.Map2StructByJson(result.Data, tmpActivityInfo, true); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// if activityInfo == nil {
|
||||
// activityInfo = tmpActivityInfo
|
||||
// } else {
|
||||
// activityInfo.SkuList = append(activityInfo.SkuList, tmpActivityInfo.SkuList...)
|
||||
// }
|
||||
resultMap := result.Data.(map[string]interface{})
|
||||
if activityInfo == nil {
|
||||
activityInfo = &ActivitySkuListInfo{
|
||||
ActivityID: activityID,
|
||||
ActivityType: int(utils.Str2Int64(utils.Interface2String(resultMap["activity_type"]))),
|
||||
ActivityName: utils.Interface2String(resultMap["activity_name"]),
|
||||
if err = utils.Map2StructByJson(resultMap, &activityInfo, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, v := range resultMap["sku_list"].([]interface{}) {
|
||||
skuMap := v.(map[string]interface{})
|
||||
activityInfo.SkuList = append(activityInfo.SkuList, &ActivitySkuInfoEx{
|
||||
ActivitySkuInfo: ActivitySkuInfo{
|
||||
SkuID: utils.Interface2String(skuMap["sku_id"]),
|
||||
Stock: int(utils.Str2Int64(utils.Interface2String(skuMap["stock"]))),
|
||||
PromotionPrice: float32(utils.Interface2Float64WithDefault(skuMap["promotion_price"], 0)),
|
||||
},
|
||||
BaiduShopID: utils.Str2Int64(utils.Interface2String(skuMap["baidu_shop_id"])),
|
||||
OriginalPrice: float32(utils.Interface2Float64WithDefault(skuMap["original_price"], 0)),
|
||||
UpcName: utils.Interface2String(skuMap["upc_name"]),
|
||||
})
|
||||
} else {
|
||||
var skuList []*ActivitySkuInfo4List
|
||||
if err = utils.Map2StructByJson(resultMap["sku_list"], &skuList, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
activityInfo.SkuList = append(activityInfo.SkuList, skuList...)
|
||||
}
|
||||
if len(activityInfo.SkuList) >= int(utils.MustInterface2Int64(resultMap["total"])) {
|
||||
break
|
||||
@@ -220,6 +228,8 @@ func (a *API) ActivitySkuList(activityID int64, shopID string, baiduShopID, supp
|
||||
return activityInfo, err
|
||||
}
|
||||
|
||||
// 批量更新活动商品
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Marketing-activity_sku_update_batch
|
||||
func (a *API) ActivitySkuUpdateBatch(activityID int64, actSkuInfoList []*ActivitySkuInfo4Update) (faildInfoList []string, err error) {
|
||||
result, err := a.AccessAPI("activity.sku.update.batch", map[string]interface{}{
|
||||
KeyActivityID: activityID,
|
||||
|
||||
@@ -7,8 +7,10 @@ import (
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const testActivityID = 3000000000517188
|
||||
|
||||
func TestActivityCreate(t *testing.T) {
|
||||
activityInfo, err := api.ActivityCreate("", 2235877569, 0, &ActivityInfo{
|
||||
activityInfo, err := api.ActivityCreate("", testShopBaiduID, 0, &ActivityInfo{
|
||||
ActivityName: "测试活动0403",
|
||||
StartTime: time.Now().Unix(),
|
||||
EndTime: time.Now().Add(24 * time.Hour).Unix(),
|
||||
@@ -29,8 +31,24 @@ func TestActivityCreate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestActivitySkuAddBatch(t *testing.T) {
|
||||
result, err := api.ActivitySkuAddBatch(testActivityID, "", testShopBaiduID, ActivityTypeDirectDown, []*ActivitySkuInfo4Add{
|
||||
&ActivitySkuInfo4Add{
|
||||
SkuID: "3594",
|
||||
Stock: 9,
|
||||
SpecialPrice: 100,
|
||||
StoreUserLimit: 9,
|
||||
},
|
||||
}, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
}
|
||||
|
||||
func TestActivityUpdate(t *testing.T) {
|
||||
activityInfo, err := api.ActivityUpdate(6000268610, "", 2235877569, 0, &ActivityInfo{
|
||||
activityInfo, err := api.ActivityUpdate(6000268610, "", testShopBaiduID, 0, &ActivityInfo{
|
||||
ActivityName: "测试活动0403",
|
||||
StartTime: time.Now().Unix(),
|
||||
EndTime: time.Now().Add(24 * time.Hour).Unix(),
|
||||
@@ -52,7 +70,7 @@ func TestActivityUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActivityGet(t *testing.T) {
|
||||
activityInfo, err := api.ActivityGet(6000268610, "", 2235877569, 0)
|
||||
activityInfo, err := api.ActivityGet(3000000000517188, "", testShopBaiduID, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
@@ -61,14 +79,14 @@ func TestActivityGet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestActivityDisable(t *testing.T) {
|
||||
err := api.ActivityDisable(6000268604, "", 2235877569, 0)
|
||||
err := api.ActivityDisable(6000268604, "", testShopBaiduID, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActivitySkuList(t *testing.T) {
|
||||
activityInfo, err := api.ActivitySkuList(6000058442, "", 0, 2233065879, nil, false)
|
||||
activityInfo, err := api.ActivitySkuList(3000000000517188, "", testShopBaiduID, 0, nil, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
|
||||
@@ -37,6 +37,38 @@ type CallbackMsg struct {
|
||||
Cmd string `json:"cmd"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Body map[string]interface{} `json:"body"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type CBPartRefundInfo struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
RefundID string `json:"refund_id"`
|
||||
Type int `json:"type"`
|
||||
Status int `json:"status"`
|
||||
AdditionReason string `json:"addition_reason"`
|
||||
Photos []string `json:"photos"`
|
||||
ReasonType string `json:"reason_type"`
|
||||
Reason string `json:"reason"`
|
||||
RefundProducts []*struct {
|
||||
SkuID string `json:"sku_id"`
|
||||
Upc string `json:"upc"`
|
||||
CustomSkuID string `json:"custom_sku_id"`
|
||||
Name string `json:"name"`
|
||||
Number int `json:"number"`
|
||||
TotalRefund int64 `json:"total_refund"`
|
||||
ShopEleRefund int64 `json:"shop_ele_refund"`
|
||||
} `json:"refund_products"`
|
||||
RefundPrice int64 `json:"refund_price"`
|
||||
}
|
||||
|
||||
type CBUserCancelInfo struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
CancelReason string `json:"cancel_reason"`
|
||||
AdditionReason string `json:"addition_reason"`
|
||||
RefuseReason string `json:"refuse_reason"`
|
||||
Pictures []string `json:"pictures"`
|
||||
Type int `json:"type"`
|
||||
CancelType int `json:"cancel_type"`
|
||||
}
|
||||
|
||||
func (a *API) Err2CallbackResponse(cmd string, err error, data interface{}) *CallbackResponse {
|
||||
@@ -107,6 +139,20 @@ func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackR
|
||||
}
|
||||
msg.Cmd = GetCmd(request)
|
||||
msg.Timestamp = utils.Str2Int64(utils.Interface2String(request.FormValue("timestamp")))
|
||||
var tmpObj interface{}
|
||||
switch msg.Cmd {
|
||||
case CmdOrderPartRefund:
|
||||
var partRefundData CBPartRefundInfo
|
||||
tmpObj = &partRefundData
|
||||
case CmdOrderUserCancel:
|
||||
var userCancelData CBUserCancelInfo
|
||||
tmpObj = &userCancelData
|
||||
}
|
||||
if tmpObj != nil {
|
||||
if utils.Map2StructByJson(msg.Body, tmpObj, true) == nil {
|
||||
msg.Data = tmpObj
|
||||
}
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
return nil, a.Err2CallbackResponse("", err, nil)
|
||||
|
||||
@@ -112,7 +112,7 @@ func (a *API) AccessAPI(cmd string, body map[string]interface{}) (retVal *Respon
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
Body := jsonResult1["body"].(map[string]interface{})
|
||||
retVal = &ResponseResult{
|
||||
ErrNo: int(utils.MustInterface2Int64(Body["errno"])),
|
||||
@@ -125,7 +125,7 @@ func (a *API) AccessAPI(cmd string, body map[string]interface{}) (retVal *Respon
|
||||
baseapi.SugarLogger.Debugf("ebai AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||
newErr := utils.NewErrorIntCode(retVal.Error, retVal.ErrNo)
|
||||
// todo 临时处理超过阈值错...
|
||||
if newErr.IntCode() == 20501 && strings.Index(retVal.Error, "阈值") >= 0 {
|
||||
if (newErr.IntCode() == 20501 && strings.Index(retVal.Error, "阈值") >= 0) || (newErr.IntCode() == 20502 && strings.Index(retVal.Error, "系统繁忙") >= 0) {
|
||||
return platformapi.ErrLevelExceedLimit, newErr
|
||||
}
|
||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
testShopBaiduID = 2233976901
|
||||
testShopID = "100077"
|
||||
testShopBaiduID = 2267254343
|
||||
testShopID = "2"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -25,14 +25,13 @@ func init() {
|
||||
logger, _ := zap.NewDevelopment()
|
||||
sugarLogger = logger.Sugar()
|
||||
baseapi.Init(sugarLogger)
|
||||
|
||||
// sandbox
|
||||
api = New("62923", "aa4cdc6c1108486b")
|
||||
// sandbox,果园测试门店
|
||||
api = New("62289", "d3ec2358d6a819ea")
|
||||
// prod
|
||||
// api = New("34665", "c3db75b754ea2d89")
|
||||
|
||||
api.SetStoreCookie("WMUSS", "AADIBAABbDlEpGl47c1EyBFcJSidBTBJHFHZEXyMSdBllJTZ9AUNOKV0tZFB9FlRVM73gEAIHRjBVagwAAHh98X2oPJ34Gal0ofFJBYXZ2Xnc6LCEXWQVnVxs7LDlaKBlFNz9DPCogYyZxJQhoHGVfVRIBa2oFUkEfDm1YZxZwLEwvZMjpB18rjw%7E3CaMQAo")
|
||||
api.SetStoreCookie("WMSTOKEN", "HwXAAB9SGxnTT8pbEwWRDQsNGB3Y09_PF5rO157QUcoLRQAAAoKlgUEiVTOhIf5LjkCoFpAwwCaAAAUr-GEu-yDBeNAQAAHNneF25-uRjhYtgX4rsAAGHurh8C5GAQAA")
|
||||
api.SetStoreCookie("WMUSS", "4AAPQCAAB5PF0aUGcBVzoRTCEkOFhFIhx-Yk9vN2EfPHYoLlROKBEsQmAUQjhNUgRt0ADAP5x-RFklwAAdjxGO11iOj8xKXYSSDIJb2BcPghsaklNfQwGS10JOVRFfhAiYElhEXFXIzoJKyloCGdwdFE6Qk9FRxojUFN3FVEHNjJPZJu4Bt9nxQ13cwoMbjA")
|
||||
api.SetStoreCookie("WMSTOKEN", "AcAANQZAABbC04rUBZFc2UYanlocDAaP0dcfzZCeS1SHQ1qJ15ExgAA13A2dGLjdbcitBZJu4Bn6B_g6cZAAA0tyyFm8cdBaNAQAAwug8HTG0xRjwt1UZzbcAAN7ofRO")
|
||||
}
|
||||
|
||||
func TestTest(t *testing.T) {
|
||||
|
||||
5
platformapi/ebaiapi/error.go
Normal file
5
platformapi/ebaiapi/error.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package ebaiapi
|
||||
|
||||
const (
|
||||
ErrOrderIsNotPartRefund = 301006 // 该订单非部分退款订单
|
||||
)
|
||||
@@ -30,42 +30,42 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
WaybillStatusNew = "2"
|
||||
WaybillStatusRequestDelivery = "3"
|
||||
WaybillStatusWait4Courier = "4"
|
||||
WaybillStatusCourierAccepted = "7"
|
||||
WaybillStatusCourierPickedup = "8"
|
||||
WaybillStatusDeliveryCancled = "15"
|
||||
WaybillStatusFinished = "16"
|
||||
WaybillStatusExceptional = "17"
|
||||
WaybillStatusSelfDelivery = "18"
|
||||
WaybillStatusNotInDelivering = "19"
|
||||
WaybillStatusDeliveryRejected = "20"
|
||||
WaybillStatusNew = "2" // 生成运单
|
||||
WaybillStatusRequestDelivery = "3" // 请求配送
|
||||
WaybillStatusWait4Courier = "4" // 等待分配骑士
|
||||
WaybillStatusCourierAccepted = "7" // 骑士接单
|
||||
WaybillStatusCourierPickedup = "8" // 骑士取餐
|
||||
WaybillStatusDeliveryCancled = "15" // 配送取消
|
||||
WaybillStatusFinished = "16" // 配送完成
|
||||
WaybillStatusExceptional = "17" // 配送异常
|
||||
WaybillStatusSelfDelivery = "18" // 自行配送
|
||||
WaybillStatusDontDeliver = "19" // 不再配送
|
||||
WaybillStatusDeliveryRejected = "20" // 配送拒单
|
||||
)
|
||||
|
||||
const (
|
||||
// 订单下行 - order.partrefund.push-部分退款订单信息推送
|
||||
OrderPartRefuncTypeMerchant = "1" // 表示商户发起的部分退款
|
||||
OrderPartRefuncTypeCustomer = "2" // 表示用户发起的部分退款
|
||||
OrderPartRefuncTypeCS = "3" // 表示客服直接发起的部分退款
|
||||
OrderPartRefuncTypeMerchant = 1 // 表示商户发起的部分退款
|
||||
OrderPartRefuncTypeCustomer = 2 // 表示用户发起的部分退款
|
||||
OrderPartRefuncTypeCS = 3 // 表示客服直接发起的部分退款
|
||||
|
||||
OrderPartRefundApply = "10" // 表示商家/用户发起部分退款申请
|
||||
OrderPartRefundSuccess = "20" // 表示部分退款成功
|
||||
OrderPartRefundUserApplyArbitration = "30" // 用户申请仲裁,客服介入
|
||||
OrderPartRefundFailed = "40" // 表示部分退款失败
|
||||
OrderPartRefundMerchantRefused = "50" // 表示商家拒绝用户发起的部分退款申请
|
||||
OrderPartRefundApply = 10 // 表示商家/用户发起部分退款申请
|
||||
OrderPartRefundSuccess = 20 // 表示部分退款成功
|
||||
OrderPartRefundUserApplyArbitration = 30 // 用户申请仲裁,客服介入
|
||||
OrderPartRefundFailed = 40 // 表示部分退款失败
|
||||
OrderPartRefundMerchantRefused = 50 // 表示商家拒绝用户发起的部分退款申请
|
||||
|
||||
// 订单下行 - order.user.cancel-用户申请订单取消/退款
|
||||
OrderUserCancelApply = "10" // 发起申请
|
||||
OrderUserCancelCSIntervene = "20" // 客服介入
|
||||
OrderUserCancelCSRefused = "30" // 客服拒绝
|
||||
OrderUserCancelCSAgreed = "40" // 客服同意
|
||||
OrderUserCancelMerchantRefused = "50" // 商户拒绝
|
||||
OrderUserCancelMerchantAgreed = "60" // 商家同意
|
||||
OrderUserCancelInvalid = "70" // 申请失效
|
||||
OrderUserCancelApply = 10 // 发起申请
|
||||
OrderUserCancelCSIntervene = 20 // 客服介入
|
||||
OrderUserCancelCSRefused = 30 // 客服拒绝
|
||||
OrderUserCancelCSAgreed = 40 // 客服同意
|
||||
OrderUserCancelMerchantRefused = 50 // 商户拒绝
|
||||
OrderUserCancelMerchantAgreed = 60 // 商家同意
|
||||
OrderUserCancelInvalid = 70 // 申请失效
|
||||
|
||||
OrderUserCancelTypeBeforeSale = "1" // 表示订单完成前用户全单取消申请流程
|
||||
OrderUserCancelTypeAfterSale = "2" // 表示订单完成后用户全单退款申请流程
|
||||
OrderUserCancelTypeBeforeSale = 1 // 表示订单完成前用户全单取消申请流程
|
||||
OrderUserCancelTypeAfterSale = 2 // 表示订单完成后用户全单退款申请流程
|
||||
|
||||
SendImmediatelySelf = 6 // 饿百商家自送的配送状态
|
||||
)
|
||||
@@ -73,12 +73,19 @@ const (
|
||||
const (
|
||||
OrderFromBaidu = "1"
|
||||
OrderFromElm = "2"
|
||||
|
||||
OrderSkuDiscountTypeZhe = "g_zhe"
|
||||
OrderSkuDiscountTypeReduce = "g_reduce"
|
||||
)
|
||||
|
||||
const (
|
||||
UserApplyCancelWaitMinute = 15 // 用户申请取消订单后待处理的最大等待时间(分钟),超时自动同意
|
||||
)
|
||||
|
||||
const (
|
||||
ListOrderPageSize = 100 // order.list的每页条数
|
||||
)
|
||||
|
||||
type ExpressInfo struct {
|
||||
OrderID string `json:"order_id"`
|
||||
ExpressID string `json:"express_id"`
|
||||
@@ -97,6 +104,205 @@ type RefundSku struct {
|
||||
Number string `json:"number"`
|
||||
}
|
||||
|
||||
type ProductSubsidyInfo struct {
|
||||
AgentRate int `json:"agent_rate"`
|
||||
BaiduRate int `json:"baidu_rate"`
|
||||
Discount int `json:"discount"`
|
||||
DiscountDetail []*struct {
|
||||
ActivityID string `json:"activity_id"`
|
||||
BaiduRate int `json:"baidu_rate"`
|
||||
ShopRate int `json:"shop_rate"`
|
||||
Type string `json:"type"`
|
||||
} `json:"discount_detail"`
|
||||
LogisticsRate int `json:"logistics_rate"`
|
||||
ShopRate int `json:"shop_rate"`
|
||||
UserRate int `json:"user_rate"`
|
||||
}
|
||||
|
||||
type OrderProductInfo struct {
|
||||
BaiduProductID string `json:"baidu_product_id"`
|
||||
SkuID string `json:"sku_id"` // 部分退款信息中是这个而不是BaiduProductID
|
||||
|
||||
CustomSkuID string `json:"custom_sku_id"`
|
||||
|
||||
PackageAmount int `json:"package_amount"`
|
||||
PackageFee int `json:"package_fee"`
|
||||
PackagePrice int `json:"package_price"`
|
||||
PrescriptionID string `json:"prescription_id"`
|
||||
|
||||
ProductAmount int `json:"product_amount"`
|
||||
Number int `json:"number"` // 部分退款信息中是这个而不是ProductAmount
|
||||
|
||||
ProductAttr []interface{} `json:"product_attr"`
|
||||
ProductCustomIndex string `json:"product_custom_index"`
|
||||
ProductFeatures []interface{} `json:"product_features"`
|
||||
ProductFee int `json:"product_fee"`
|
||||
ProductName string `json:"product_name"`
|
||||
ProductPrice int `json:"product_price"`
|
||||
ProductSubsidy *ProductSubsidyInfo `json:"product_subsidy"`
|
||||
ProductType int `json:"product_type"`
|
||||
SupplyType int `json:"supply_type"`
|
||||
TotalFee int `json:"total_fee"`
|
||||
TotalWeight int `json:"total_weight"`
|
||||
Upc string `json:"upc"`
|
||||
WeightType int `json:"weight_type"`
|
||||
}
|
||||
|
||||
type OrderDetailInfo struct {
|
||||
Discount []*struct {
|
||||
ActivityID string `json:"activity_id"`
|
||||
AgentRate int `json:"agent_rate"`
|
||||
BaiduRate int `json:"baidu_rate"`
|
||||
Desc string `json:"desc"`
|
||||
Fee int `json:"fee"`
|
||||
LogisticsRate int `json:"logistics_rate"`
|
||||
Products []*struct {
|
||||
ActivityID string `json:"activity_id"`
|
||||
ActivityProductNum int `json:"activity_product_num"`
|
||||
BaiduProductID int64 `json:"baidu_product_id"`
|
||||
NowPrice int `json:"now_price"`
|
||||
OrigPrice int `json:"orig_price"`
|
||||
SavePrice int `json:"save_price"`
|
||||
} `json:"products,omitempty"`
|
||||
RuleID string `json:"rule_id"`
|
||||
ShopRate int `json:"shop_rate"`
|
||||
Type string `json:"type"`
|
||||
UserRate int `json:"user_rate,omitempty"`
|
||||
} `json:"discount"`
|
||||
Order *struct {
|
||||
AtshopTime int `json:"atshop_time"`
|
||||
CancelTime string `json:"cancel_time"`
|
||||
ColdBoxFee string `json:"cold_box_fee"`
|
||||
Commission int `json:"commission"`
|
||||
ConfirmTime string `json:"confirm_time"`
|
||||
CreateTime string `json:"create_time"`
|
||||
DeliveryParty int `json:"delivery_party"`
|
||||
DeliveryPhone string `json:"delivery_phone"`
|
||||
DeliveryTime int `json:"delivery_time"`
|
||||
DiscountFee int `json:"discount_fee"`
|
||||
DownFlag int `json:"down_flag"`
|
||||
ElemeOrderID string `json:"eleme_order_id"`
|
||||
ExpectTimeMode int `json:"expect_time_mode"`
|
||||
Ext struct {
|
||||
TaoxiFlag int `json:"taoxi_flag"`
|
||||
} `json:"ext"`
|
||||
FinishedTime string `json:"finished_time"`
|
||||
InvoiceTitle string `json:"invoice_title"`
|
||||
IsColdBoxOrder int `json:"is_cold_box_order"`
|
||||
IsPrivate int `json:"is_private"`
|
||||
LatestSendTime int `json:"latest_send_time"`
|
||||
MealNum string `json:"meal_num"`
|
||||
NeedInvoice int `json:"need_invoice"`
|
||||
OrderFlag int `json:"order_flag"`
|
||||
OrderFrom string `json:"order_from"`
|
||||
OrderID string `json:"order_id"`
|
||||
OrderIndex string `json:"order_index"`
|
||||
PackageFee int `json:"package_fee"`
|
||||
PayStatus int `json:"pay_status"`
|
||||
PayType int `json:"pay_type"`
|
||||
PickupTime int `json:"pickup_time"`
|
||||
Remark string `json:"remark"`
|
||||
ResponsibleParty string `json:"responsible_party"`
|
||||
SendFee int `json:"send_fee"`
|
||||
SendImmediately int `json:"send_immediately"`
|
||||
SendTime int `json:"send_time"`
|
||||
ShopFee int `json:"shop_fee"`
|
||||
Status int `json:"status"`
|
||||
TaxerID string `json:"taxer_id"`
|
||||
TotalFee int `json:"total_fee"`
|
||||
UserFee int `json:"user_fee"`
|
||||
} `json:"order"`
|
||||
Products [][]*OrderProductInfo `json:"products"`
|
||||
Shop *struct {
|
||||
BaiduShopID string `json:"baidu_shop_id"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"shop"`
|
||||
Source string `json:"source"`
|
||||
User *struct {
|
||||
Address string `json:"address"`
|
||||
City string `json:"city"`
|
||||
Coord *struct {
|
||||
Latitude string `json:"latitude"`
|
||||
Longitude string `json:"longitude"`
|
||||
} `json:"coord"`
|
||||
CoordAmap *struct {
|
||||
Latitude string `json:"latitude"`
|
||||
Longitude string `json:"longitude"`
|
||||
} `json:"coord_amap"`
|
||||
District string `json:"district"`
|
||||
Gender string `json:"gender"`
|
||||
Name string `json:"name"`
|
||||
Phone string `json:"phone"`
|
||||
PrivacyPhone string `json:"privacy_phone"`
|
||||
Province string `json:"province"`
|
||||
UserID string `json:"user_id"`
|
||||
} `json:"user"`
|
||||
}
|
||||
|
||||
type RefundOrderDetailInfo struct {
|
||||
CustomSkuID string `json:"custom_sku_id"`
|
||||
Name string `json:"name"`
|
||||
Number int `json:"number"`
|
||||
ProductFeatures []interface{} `json:"product_features"`
|
||||
ProductFee int `json:"product_fee"`
|
||||
ProductPrice int `json:"product_price"`
|
||||
ProductSubsidy *ProductSubsidyInfo `json:"product_subsidy"`
|
||||
SkuID string `json:"sku_id"`
|
||||
TotalWeight int `json:"total_weight"`
|
||||
Upc string `json:"upc"`
|
||||
}
|
||||
|
||||
type RefundDetailInfo struct {
|
||||
ApplyTime string `json:"apply_time"`
|
||||
CustomSkuID string `json:"custom_sku_id"`
|
||||
Desc string `json:"desc"`
|
||||
Name string `json:"name"`
|
||||
Number int `json:"number"`
|
||||
RefundID string `json:"refund_id"`
|
||||
ShopEleRefund int `json:"shop_ele_refund"`
|
||||
SkuID string `json:"sku_id"`
|
||||
Status int `json:"status"`
|
||||
TotalRefund int `json:"total_refund"`
|
||||
Type int `json:"type"`
|
||||
Upc string `json:"upc"`
|
||||
}
|
||||
|
||||
type PartRefundInfo struct {
|
||||
Commission int `json:"commission"`
|
||||
Fee int `json:"fee"`
|
||||
OrderDetail []*RefundOrderDetailInfo `json:"order_detail"`
|
||||
OrderID string `json:"order_id"`
|
||||
PackageFee int `json:"package_fee"`
|
||||
RefundDetail []*RefundDetailInfo `json:"refund_detail"`
|
||||
RefundPrice int `json:"refund_price"`
|
||||
SendFee int `json:"send_fee"`
|
||||
ShopFee int `json:"shop_fee"`
|
||||
TotalPrice int `json:"total_price"`
|
||||
Type int `json:"type"`
|
||||
UserFee int `json:"user_fee"`
|
||||
}
|
||||
|
||||
type ListOrderItemInfo struct {
|
||||
BaiduShopID int64 `json:"baidu_shop_id"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
OrderFrom int `json:"order_from"`
|
||||
OrderID string `json:"order_id"`
|
||||
OrderStatus int `json:"order_status"`
|
||||
PayStatus int `json:"pay_status"`
|
||||
PayType int `json:"pay_type"`
|
||||
ShopID string `json:"shop_id"`
|
||||
Status int `json:"status"`
|
||||
UserPhone string `json:"user_phone"`
|
||||
}
|
||||
|
||||
type ListOrderInfo struct {
|
||||
Total int `json:"total"`
|
||||
Page int `json:"Page"`
|
||||
Pages int `json:"pages"`
|
||||
List []*ListOrderItemInfo `json:"list"`
|
||||
}
|
||||
|
||||
// 提供给合作方确认订单所用。 注:1、10分钟内未确认的订单系统自动取消。2、确认失败的订单请不要做餐。 2016年7月4号起,将由百度外卖负责完成订单。届时,对接方无需调用完成订单接口,继续调用可能导致订单结算有问题。
|
||||
func (a *API) OrderConfirm(orderID string) (err error) {
|
||||
_, err = a.AccessAPI("order.confirm", map[string]interface{}{
|
||||
@@ -169,6 +375,16 @@ func (a *API) OrderGet(orderID string) (orderMap map[string]interface{}, err err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) OrderGet2(orderID string) (order *OrderDetailInfo, err error) {
|
||||
result, err := a.AccessAPI("order.get", map[string]interface{}{
|
||||
"order_id": orderID,
|
||||
})
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result.Data, &order, true)
|
||||
}
|
||||
return order, err
|
||||
}
|
||||
|
||||
// 设置订单快递单号
|
||||
func (a *API) OrderExpressCreate(shopID string, expressList []*ExpressInfo) (status int, err error) {
|
||||
result, err := a.AccessAPI("order.express.create", map[string]interface{}{
|
||||
@@ -226,8 +442,48 @@ func (a *API) OrderIdConvert(orderID string, isElemeOrder bool) (convertedOrderI
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 查看售后订单详情
|
||||
func (a *API) OrderPartrefundGet(orderID string) (orderMap map[string]interface{}, err error) {
|
||||
// 查看订单列表
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Order_Up-order_list
|
||||
// page从1开始
|
||||
func (a *API) OrderList(shopID string, baiduShopID int64, startTime, endTime int64, status int, page int) (listOrderInfo *ListOrderInfo, err error) {
|
||||
params := a.genShopIDParams(shopID, baiduShopID, 0)
|
||||
if startTime > 0 {
|
||||
params["start_time"] = startTime
|
||||
}
|
||||
if endTime > 0 {
|
||||
params["end_time"] = endTime
|
||||
}
|
||||
if status > 0 {
|
||||
params["status"] = status
|
||||
}
|
||||
if page > 0 {
|
||||
params["page"] = page
|
||||
}
|
||||
result, err := a.AccessAPI("order.list", params)
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result.Data, &listOrderInfo, true)
|
||||
}
|
||||
return listOrderInfo, err
|
||||
}
|
||||
|
||||
func (a *API) OrderListAll(shopID string, baiduShopID int64, startTime, endTime int64, status int) (listOrder []*ListOrderItemInfo, err error) {
|
||||
page := 1
|
||||
for {
|
||||
result, err := a.OrderList(shopID, baiduShopID, startTime, endTime, status, page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listOrder = append(listOrder, result.List...)
|
||||
if result.Page == result.Pages {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
return listOrder, nil
|
||||
}
|
||||
|
||||
// 查看部分退款订单详情
|
||||
func (a *API) OrderPartRefundGet(orderID string) (orderMap map[string]interface{}, err error) {
|
||||
result, err := a.AccessAPI("order.partrefund.get", map[string]interface{}{
|
||||
"order_id": orderID,
|
||||
})
|
||||
@@ -237,6 +493,14 @@ func (a *API) OrderPartrefundGet(orderID string) (orderMap map[string]interface{
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// func (a *API) OrderPartRefundGet2(orderID string) (partRefundInfo *CBPartRefundInfo, err error) {
|
||||
// result, err := a.OrderPartRefundGet(orderID)
|
||||
// if err == nil {
|
||||
// err = utils.Map2StructByJson(result, &partRefundInfo, true)
|
||||
// }
|
||||
// return partRefundInfo, err
|
||||
// }
|
||||
|
||||
func (a *API) SmartOrderIdConvert(orderID string) (convertedOrderID string, err error) {
|
||||
return a.OrderIdConvert(orderID, isOrderIDEleme(orderID))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func TestOrderGet(t *testing.T) {
|
||||
result, err := api.OrderGet("1555731848221773250")
|
||||
result, err := api.OrderGet("1560213937227424971")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
@@ -15,8 +15,44 @@ func TestOrderGet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderGet2(t *testing.T) {
|
||||
result, err := api.OrderGet2("1560213937227424971")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderList(t *testing.T) {
|
||||
result, err := api.OrderList("", 0, 0, 0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderPartRefundGet(t *testing.T) {
|
||||
result, err := api.OrderPartRefundGet("1557459492221457830")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
}
|
||||
|
||||
// func TestOrderPartRefundGet2(t *testing.T) {
|
||||
// result, err := api.OrderPartRefundGet2("1557459492221457830")
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// } else {
|
||||
// t.Log(utils.Format4Output(result, false))
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestOrderCallDelivery(t *testing.T) {
|
||||
err := api.OrderCallDelivery("15381031350154")
|
||||
err := api.OrderCallDelivery("1556617836226053651")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -59,3 +95,15 @@ func TestSmartOrderIdConvert(t *testing.T) {
|
||||
}
|
||||
t.Log(result)
|
||||
}
|
||||
|
||||
func TestOrderPartRefund(t *testing.T) {
|
||||
err := api.OrderPartRefund("3035779376398878822", []*RefundSku{
|
||||
&RefundSku{
|
||||
CustomeSkuID: "",
|
||||
Number: "1",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ const (
|
||||
|
||||
KeyCustomSkuID = "custom_sku_id"
|
||||
KeySkuID = "sku_id"
|
||||
KeyUPC = "upc"
|
||||
|
||||
KeyName = "name"
|
||||
KeyPhone = "phone"
|
||||
@@ -47,22 +48,23 @@ const (
|
||||
CoordTypeAutonavi = "amap"
|
||||
)
|
||||
|
||||
// https://open-be.ele.me/dev/api/doc/v3/#api-Shop-shop_get
|
||||
const (
|
||||
DeliveryTypeElmNone = 0
|
||||
DeliveryTypeElmXingHuoTrial = 1
|
||||
DeliveryTypeElmXingHuo = 4
|
||||
DeliveryTypeElmFengNiaoZS = 5
|
||||
DeliveryTypeElmFengNiaoZSKA = 6
|
||||
DeliveryTypeElmFengNiaoKS = 9
|
||||
DeliveryTypeElmXingHuoZBTrial = 10
|
||||
DeliveryTypeElmXingHuoZB = 11
|
||||
DeliveryTypeElmNewRetail = 12
|
||||
DeliveryTypeElmEBase = 13
|
||||
DeliveryTypeElmEPeiSong = 14
|
||||
DeliveryTypeElmFengNiaoHybrid = 15
|
||||
DeliveryTypeElmFengNiaoNiubee = 16
|
||||
DeliveryTypeElmXingHuoKA = 17
|
||||
DeliveryTypeElmXingHuoZBKA = 18
|
||||
DeliveryTypeElmNone = 0 // 暂无
|
||||
DeliveryTypeElmXingHuoTrial = 1 // 星火计划(试用)
|
||||
DeliveryTypeElmXingHuo = 4 // 星火计划
|
||||
DeliveryTypeElmFengNiaoZS = 5 // 蜂鸟专送
|
||||
DeliveryTypeElmFengNiaoZSKA = 6 // 蜂鸟专送,KA
|
||||
DeliveryTypeElmFengNiaoKS = 9 // 蜂鸟快送
|
||||
DeliveryTypeElmXingHuoZBTrial = 10 // 星火众包(试用)
|
||||
DeliveryTypeElmXingHuoZB = 11 // 星火众包
|
||||
DeliveryTypeElmNewRetail = 12 // 新零售
|
||||
DeliveryTypeElmEBase = 13 // e基础
|
||||
DeliveryTypeElmEPeiSong = 14 // e配送
|
||||
DeliveryTypeElmFengNiaoHybrid = 15 // 蜂鸟混合送
|
||||
DeliveryTypeElmFengNiaoNiubee = 16 // 蜂鸟质选
|
||||
DeliveryTypeElmXingHuoKA = 17 // 星火计划KA
|
||||
DeliveryTypeElmXingHuoZBKA = 18 // 星火众包KA
|
||||
)
|
||||
|
||||
type ShopInfo struct {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ebaiapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@@ -8,8 +9,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
SkuStatusOnline = 1
|
||||
SkuStatusOffline = 0
|
||||
SkuStatusOnline = 1 // 为上架
|
||||
SkuStatusOffline = 0 // 为下架
|
||||
SkuStatusDeleted = 2 // 为删除
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -17,7 +19,8 @@ const (
|
||||
UPCTypePrivate = 0
|
||||
)
|
||||
const (
|
||||
MaxLeftNum = 99999
|
||||
MaxLeftNum = 99999
|
||||
MaxSkuNameByteCount = 100 // skuname的最大字节数,注意不是字符数,超长饿百会报错:{"data":"","errno":20200,"error":"invalid param:[name]...
|
||||
)
|
||||
|
||||
type CategoryInfo struct {
|
||||
@@ -28,17 +31,87 @@ type CategoryInfo struct {
|
||||
Level int `json:"level"`
|
||||
}
|
||||
|
||||
type SkuListParams struct {
|
||||
Page int `json:"page,omitempty"`
|
||||
PageSize int `json:"pagesize,omitempty"`
|
||||
Upc string `json:"upc,omitempty"`
|
||||
SkuID int64 `json:"sku_id,omitempty"`
|
||||
CustomSkuID string `json:"custom_sku_id,omitempty"`
|
||||
UpcType int `json:"upc_type,omitempty"`
|
||||
GetUncate int `json:"get_uncate,omitempty"`
|
||||
Delete int `json:"delete,omitempty"`
|
||||
Enabled int `json:"enabled,omitempty"`
|
||||
StartTime int `json:"start_time,omitempty"`
|
||||
EndTime int `json:"end_time,omitempty"`
|
||||
}
|
||||
|
||||
type SkuPhotoInfo struct {
|
||||
IsMaster int `json:"is_master"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
type SkuCustomCatInfo struct {
|
||||
CustomCatID string `json:"custom_cat_id"`
|
||||
CustomCatName string `json:"custom_cat_name"`
|
||||
}
|
||||
|
||||
type SkuInfo struct {
|
||||
CustomCatIDs string `json:"custom_cat_ids"`
|
||||
CustomCatList []*SkuCustomCatInfo `json:"custom_cat_list"`
|
||||
CustomSkuID string `json:"custom_sku_id"`
|
||||
IsInActivity int `json:"is_in_activity"`
|
||||
LeftNum int `json:"left_num"`
|
||||
MarketPrice int `json:"market_price"`
|
||||
Minimum int `json:"minimum"`
|
||||
Name string `json:"name"`
|
||||
NeedIce int `json:"need_ice"`
|
||||
Photos []*SkuPhotoInfo `json:"photos"`
|
||||
PreminusWeight int `json:"preminus_weight"`
|
||||
PreparationTime string `json:"preparation_time"`
|
||||
ProductionAddr1 string `json:"production_addr1"`
|
||||
ProductionAddr2 string `json:"production_addr2"`
|
||||
ProductionAddr3 string `json:"production_addr3"`
|
||||
Rtf string `json:"rtf"`
|
||||
SalePrice int64 `json:"sale_price"`
|
||||
SaleStep string `json:"sale_step"`
|
||||
SaleUnit string `json:"sale_unit"`
|
||||
ShelfNumber string `json:"shelf_number"`
|
||||
SkuID int64 `json:"sku_id"`
|
||||
// SkuProperty []interface{} `json:"sku_property"`
|
||||
Status int `json:"status"`
|
||||
Summary string `json:"summary"`
|
||||
Upc string `json:"upc"`
|
||||
UpcType string `json:"upc_type"`
|
||||
UpdateTime string `json:"update_time"`
|
||||
Weight int `json:"weight"`
|
||||
WeightFlag int `json:"weight_flag"`
|
||||
}
|
||||
|
||||
type PageDataInfo struct {
|
||||
Total int
|
||||
Page int
|
||||
Pages int
|
||||
List []map[string]interface{}
|
||||
Total int `json:"Total"`
|
||||
Page int `json:"Page"`
|
||||
Pages int `json:"Pages"`
|
||||
List []*SkuInfo `json:"List"`
|
||||
}
|
||||
|
||||
var (
|
||||
skuExistReg = regexp.MustCompile(`\s?,\s?sku_id:(\d+)`)
|
||||
)
|
||||
|
||||
func genSkuIDParams(skuID int64, customSkuID, upc string) map[string]interface{} {
|
||||
params := map[string]interface{}{}
|
||||
if skuID != 0 {
|
||||
params[KeySkuID] = skuID
|
||||
} else if customSkuID != "" {
|
||||
params[KeyCustomSkuID] = customSkuID
|
||||
} else if upc != "" {
|
||||
params[KeyUPC] = upc
|
||||
} else {
|
||||
panic("skuID, customSkuID and upc are all no value!")
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
// category相关的函数,shop_custom_id可重
|
||||
|
||||
func (a *API) ShopCategoryCreate(shopID string, parentID int64, name string, rank int) (catID int64, err error) {
|
||||
@@ -99,21 +172,14 @@ func (a *API) SkuGetItemsByCategoryId(shopID string, categoryID int64) (skus []m
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) SkuList(shopID string, params map[string]interface{}) (skuInfo *PageDataInfo, err error) {
|
||||
defParams := map[string]interface{}{
|
||||
KeyShopID: shopID,
|
||||
}
|
||||
result, err := a.AccessAPI("sku.list", utils.MergeMaps(params, defParams))
|
||||
func (a *API) SkuList(shopID string, params *SkuListParams) (skuInfo *PageDataInfo, err error) {
|
||||
paramMap := utils.Struct2FlatMap(params)
|
||||
paramMap[KeyShopID] = shopID
|
||||
result, err := a.AccessAPI("sku.list", paramMap)
|
||||
if err == nil {
|
||||
data := result.Data.(map[string]interface{})
|
||||
return &PageDataInfo{
|
||||
Total: int(utils.MustInterface2Int64(data["total"])),
|
||||
Page: int(utils.MustInterface2Int64(data["page"])),
|
||||
Pages: int(utils.MustInterface2Int64(data["pages"])),
|
||||
List: utils.Slice2MapSlice(data["list"].([]interface{})),
|
||||
}, nil
|
||||
err = utils.Map2StructByJson(result.Data, &skuInfo, true)
|
||||
}
|
||||
return nil, err
|
||||
return skuInfo, err
|
||||
}
|
||||
|
||||
func (a *API) SkuCreate(shopID string, customSkuID int, params map[string]interface{}) (skuID int64, err error) {
|
||||
@@ -168,9 +234,6 @@ func (a *API) SkuDelete(shopID, skuIDsStr string) (err error) {
|
||||
KeySkuID: skuIDsStr,
|
||||
}
|
||||
_, err = a.AccessAPI("sku.delete", params)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -180,9 +243,6 @@ func (a *API) SkuDeleteByCustomIDs(shopID, customSkuIDsStr string) (err error) {
|
||||
KeyCustomSkuID: customSkuIDsStr,
|
||||
}
|
||||
_, err = a.AccessAPI("sku.delete", params)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -192,9 +252,13 @@ func (a *API) SkuOnline(shopID, skuIDsStr string) (err error) {
|
||||
KeySkuID: skuIDsStr,
|
||||
}
|
||||
_, err = a.AccessAPI("sku.online", params)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) SkuOnlineOne(shopID string, skuID int64, customSkuID, upc string) (err error) {
|
||||
params := genSkuIDParams(skuID, customSkuID, upc)
|
||||
params[KeyShopID] = shopID
|
||||
_, err = a.AccessAPI("sku.online.one", params)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -204,9 +268,41 @@ func (a *API) SkuOffline(shopID, skuIDsStr string) (err error) {
|
||||
KeySkuID: skuIDsStr,
|
||||
}
|
||||
_, err = a.AccessAPI("sku.offline", params)
|
||||
if err == nil {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) SkuOfflineOne(shopID string, skuID int64, customSkuID, upc string) (err error) {
|
||||
params := genSkuIDParams(skuID, customSkuID, upc)
|
||||
params[KeyShopID] = shopID
|
||||
_, err = a.AccessAPI("sku.offline.one", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func genSkuPriceParams(skuPriceStr, customSkuPriceStr, upcPriceStr string) map[string]interface{} {
|
||||
params := map[string]interface{}{}
|
||||
if skuPriceStr != "" {
|
||||
params["skuid_price"] = skuPriceStr
|
||||
} else if skuPriceStr != "" {
|
||||
params["custom_sku_id"] = customSkuPriceStr
|
||||
} else if upcPriceStr != "" {
|
||||
params["upc_price"] = upcPriceStr
|
||||
} else {
|
||||
panic("skuPriceStr, customSkuPriceStr and upcPriceStr are all empty!")
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func (a *API) SkuPriceUpdateBatch(shopID, skuPriceStr, customSkuPriceStr, upcPriceStr string) (err error) {
|
||||
params := genSkuPriceParams(skuPriceStr, customSkuPriceStr, upcPriceStr)
|
||||
params[KeyShopID] = shopID
|
||||
_, err = a.AccessAPI("sku.price.update.batch", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) SkuPriceUpdateOne(shopID, skuPriceStr, customSkuPriceStr, upcPriceStr string) (err error) {
|
||||
params := genSkuPriceParams(skuPriceStr, customSkuPriceStr, upcPriceStr)
|
||||
params[KeyShopID] = shopID
|
||||
_, err = a.AccessAPI("sku.price.update.one", params)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -217,12 +313,30 @@ func (a *API) SkuShopCategoryMap(shopID string, skuID int64, categoryIDsStr stri
|
||||
"category_id": categoryIDsStr,
|
||||
}
|
||||
_, err = a.AccessAPI("sku.shop.category.map", params)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 饿百的这个API有点怪,虽然有shopID参数,但返回的链接可以跨店使用
|
||||
func (a *API) SkuUploadRTF(shopID, rtfDetail string) (rtfURL string, err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyShopID: shopID,
|
||||
"rtf_detail": rtfDetail,
|
||||
}
|
||||
result, err := a.AccessAPI("sku.uploadrtf", params)
|
||||
if err == nil {
|
||||
rtfURL = utils.Interface2String(result.Data.(map[string]interface{})["url"])
|
||||
}
|
||||
return rtfURL, err
|
||||
}
|
||||
|
||||
func BuildRFTFromImgs(imgList ...string) string {
|
||||
imgList2 := make([]string, len(imgList))
|
||||
for index, img := range imgList {
|
||||
imgList2[index] = fmt.Sprintf(`<img align="absmiddle" src="%s" alt="%s" />`, img, img)
|
||||
}
|
||||
return strings.Join(imgList2, "\n")
|
||||
}
|
||||
|
||||
//
|
||||
func interface2CatList(data interface{}, level int) (cats []*CategoryInfo) {
|
||||
maps, ok := data.([]interface{})
|
||||
|
||||
@@ -48,9 +48,8 @@ func TestSkuGetItemsByCategoryId(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSkuList(t *testing.T) {
|
||||
result, err := api.SkuList(testShopID, map[string]interface{}{
|
||||
// KeySkuID: 153879464137191,
|
||||
// "delete": 1,
|
||||
result, err := api.SkuList(testShopID, &SkuListParams{
|
||||
SkuID: 15579787500720732,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -59,6 +58,16 @@ func TestSkuList(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSkuUploadRTF(t *testing.T) {
|
||||
rtfDetail := BuildRFTFromImgs("https://image.jxc4.com/sijidou.jpg")
|
||||
t.Log(rtfDetail)
|
||||
result, err := api.SkuUploadRTF("2", rtfDetail)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(result)
|
||||
}
|
||||
|
||||
func TestSkuCreate(t *testing.T) {
|
||||
result, err := api.SkuCreate(testShopID, 17, map[string]interface{}{
|
||||
"name": "测试商品",
|
||||
@@ -83,6 +92,21 @@ func TestSkuCreate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSkuUpdate(t *testing.T) {
|
||||
// 15579787500720732 高级
|
||||
|
||||
result, err := api.SkuUpdate("2", 1557043939079105, map[string]interface{}{
|
||||
// "name": "高级商品2015a333约1100g/份",
|
||||
// "rtf": "http://www.rosy.net.cn/rtf.html",
|
||||
"shelf_number": 12,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSkuDelete(t *testing.T) {
|
||||
err := api.SkuDelete(testShopID, "153922044227304")
|
||||
if err != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@ package ebaiapi
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
@@ -11,8 +12,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
storeURL = "https://be.ele.me"
|
||||
getStoreURL = "https://newretail.ele.me"
|
||||
storeURL = "https://be.ele.me"
|
||||
getStoreURL = "https://newretail.ele.me"
|
||||
swithShopURL = "crm/manager/switchshop"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -32,6 +34,131 @@ const (
|
||||
CommentContentNoContent = 0
|
||||
)
|
||||
|
||||
type PageShopUserInfo struct {
|
||||
CategoryID string `json:"category_id"`
|
||||
CityID string `json:"city_id"`
|
||||
CityName string `json:"city_name"`
|
||||
DeliveryParty string `json:"delivery_party"`
|
||||
EleID string `json:"ele_id"`
|
||||
EleSoaToken string `json:"ele_soa_token"`
|
||||
IsAPI int `json:"is_api"`
|
||||
IsStore interface{} `json:"is_store"`
|
||||
MerchantID string `json:"merchant_id"`
|
||||
MerchantName string `json:"merchant_name"`
|
||||
Role struct {
|
||||
Ename string `json:"ename"`
|
||||
Name string `json:"name"`
|
||||
ShopRoleID int64 `json:"shop_role_id"`
|
||||
} `json:"role"`
|
||||
SalesID string `json:"sales_id"`
|
||||
SalesName string `json:"sales_name"`
|
||||
ServicePackage struct {
|
||||
BaiduSign int `json:"baiduSign"`
|
||||
EleSign int `json:"eleSign"`
|
||||
} `json:"service_package"`
|
||||
ShopInfo struct {
|
||||
AreaID string `json:"area_id"`
|
||||
BaiduBusinessState string `json:"baidu_business_state"`
|
||||
BaiduOnlineStatus string `json:"baidu_online_status"`
|
||||
BaiduTakeoutLogo string `json:"baidu_takeout_logo"`
|
||||
CategoryID string `json:"category_id"`
|
||||
CategoryIds string `json:"category_ids"`
|
||||
CategoryName string `json:"category_name"`
|
||||
County string `json:"county"`
|
||||
CreateType string `json:"create_type"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
CrmOncallType int `json:"crm_oncall_type"`
|
||||
EffectiveAt string `json:"effective_at"`
|
||||
EleBusinessState string `json:"ele_business_state"`
|
||||
EleDeliveryParty string `json:"ele_delivery_party"`
|
||||
EleID string `json:"ele_id"`
|
||||
EleOnlineStatus string `json:"ele_online_status"`
|
||||
EleShopLogo interface{} `json:"ele_shop_logo"`
|
||||
IsSignZhongbao string `json:"is_sign_zhongbao"`
|
||||
OnlineStatus string `json:"online_status"`
|
||||
Phone string `json:"phone"`
|
||||
ServStatus string `json:"serv_status"`
|
||||
ShopTransactionOpen int `json:"shop_transaction_open"`
|
||||
SourceName string `json:"source_name"`
|
||||
SupplierID string `json:"supplier_id"`
|
||||
TakeoutBoxPrice string `json:"takeout_box_price"`
|
||||
TakeoutDispatchTime []struct {
|
||||
End string `json:"end"`
|
||||
Start string `json:"start"`
|
||||
} `json:"takeout_dispatch_time"`
|
||||
TakeoutOncallType string `json:"takeout_oncall_type"`
|
||||
TakeoutOpenTime []struct {
|
||||
End string `json:"end"`
|
||||
Start string `json:"start"`
|
||||
} `json:"takeout_open_time"`
|
||||
TakeoutServicePhone string `json:"takeout_service_phone"`
|
||||
TakeoutShopLogo string `json:"takeout_shop_logo"`
|
||||
TransferStatus string `json:"transfer_status"`
|
||||
} `json:"shop_info"`
|
||||
ShopRole int `json:"shop_role"`
|
||||
ShopUserID string `json:"shop_user_id"`
|
||||
SwitchFromSupplier int `json:"switch_from_supplier"`
|
||||
UserName string `json:"user_name"`
|
||||
UserPhone string `json:"user_phone"`
|
||||
YellowPrompt struct {
|
||||
Capacity int `json:"capacity"`
|
||||
Complete int `json:"complete"`
|
||||
Display bool `json:"display"`
|
||||
Msg string `json:"msg"`
|
||||
MsgCount int `json:"msg_count"`
|
||||
MsgList []interface{} `json:"msg_list"`
|
||||
Online int `json:"online"`
|
||||
PcURL string `json:"pc_url"`
|
||||
TransferStatus string `json:"transfer_status"`
|
||||
Type int `json:"type"`
|
||||
URL string `json:"url"`
|
||||
} `json:"yellow_prompt"`
|
||||
}
|
||||
|
||||
type PageShopHealthInfo struct {
|
||||
MerchantID string `json:"merchant_id"`
|
||||
MerchantName string `json:"merchant_name"`
|
||||
|
||||
BadOrderRate string `json:"bad_order_rate"`
|
||||
Category2 string `json:"category_2"`
|
||||
Data string `json:"data"`
|
||||
EndTime string `json:"endTime"`
|
||||
HasPhotoRate string `json:"has_photo_rate"`
|
||||
Hours string `json:"hours"`
|
||||
ID string `json:"id"`
|
||||
IsButie string `json:"is_butie"`
|
||||
IsCp string `json:"is_cp"`
|
||||
IsDeliverFee string `json:"is_deliver_fee"`
|
||||
IsGood string `json:"is_good"`
|
||||
IsHealthy string `json:"is_healthy"`
|
||||
IsJiedan string `json:"is_jiedan"`
|
||||
IsManjian string `json:"is_manjian"`
|
||||
IsQisong string `json:"is_qisong"`
|
||||
IsShopNew string `json:"is_shop_new"`
|
||||
IsSku string `json:"is_sku"`
|
||||
IsYinye string `json:"is_yinye"`
|
||||
IsYoutu string `json:"is_youtu"`
|
||||
IsZs string `json:"is_zs"`
|
||||
MinDeliveryFee string `json:"min_delivery_fee"`
|
||||
MinDeliveryPrice string `json:"min_delivery_price"`
|
||||
RestaurantSubsidy string `json:"restaurant_subsidy"`
|
||||
ShopCategory string `json:"shop_category"`
|
||||
ShopID string `json:"shop_id"`
|
||||
SkuNum string `json:"sku_num"`
|
||||
StartTime string `json:"startTime"`
|
||||
TargetButie string `json:"target_butie"`
|
||||
TargetCp string `json:"target_cp"`
|
||||
TargetDeliverFee string `json:"target_deliver_fee"`
|
||||
TargetJiedan string `json:"target_jiedan"`
|
||||
TargetQisong string `json:"target_qisong"`
|
||||
TargetSku string `json:"target_sku"`
|
||||
TargetYinye string `json:"target_yinye"`
|
||||
TargetYoutu string `json:"target_youtu"`
|
||||
UnvalidOrderNum string `json:"unvalid_order_num"`
|
||||
UpdateTime string `json:"update_time"`
|
||||
Week string `json:"week"`
|
||||
}
|
||||
|
||||
func (a *API) SetStoreCookie(key, value string) {
|
||||
a.locker.Lock()
|
||||
defer a.locker.Unlock()
|
||||
@@ -44,7 +171,7 @@ func (a *API) GetStoreCookie(key string) string {
|
||||
return a.storeCookies[key]
|
||||
}
|
||||
|
||||
func (a *API) AccessStorePage(subURL string) (retVal map[string]interface{}, err error) {
|
||||
func (a *API) AccessStorePage2(subURL string, params map[string]interface{}, cookies map[string]string) (retVal map[string]interface{}, err error) {
|
||||
a.locker.RLock()
|
||||
storeCookieLen := len(a.storeCookies)
|
||||
a.locker.RUnlock()
|
||||
@@ -53,11 +180,15 @@ func (a *API) AccessStorePage(subURL string) (retVal map[string]interface{}, err
|
||||
}
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
var request *http.Request
|
||||
fullURL := utils.GenerateGetURL(storeURL, subURL, nil)
|
||||
// baseapi.SugarLogger.Debug(fullURL)
|
||||
request, _ := http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
if params == nil {
|
||||
// baseapi.SugarLogger.Debug(fullURL)
|
||||
request, _ = http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
} else {
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
|
||||
request.Header.Set("charset", "UTF-8")
|
||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
a.locker.RLock()
|
||||
for k, v := range a.storeCookies {
|
||||
@@ -66,15 +197,30 @@ func (a *API) AccessStorePage(subURL string) (retVal map[string]interface{}, err
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
for k, v := range cookies {
|
||||
request.AddCookie(&http.Cookie{
|
||||
Name: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
a.locker.RUnlock()
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
retVal = jsonResult1
|
||||
code := int(utils.MustInterface2Int64(jsonResult1["errno"]))
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1["data"].(map[string]interface{})
|
||||
if subURL == swithShopURL {
|
||||
for _, v := range response.Cookies() {
|
||||
if v.Name == "SWITCH_SHOP" {
|
||||
retVal = utils.Struct2FlatMap(v)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
retVal, _ = jsonResult1["data"].(map[string]interface{})
|
||||
}
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
}
|
||||
newErr := utils.NewErrorIntCode(jsonResult1["errmsg"].(string), code)
|
||||
@@ -87,6 +233,10 @@ func (a *API) AccessStorePage(subURL string) (retVal map[string]interface{}, err
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func (a *API) AccessStorePage(subURL string, params map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||
return a.AccessStorePage2(subURL, params, nil)
|
||||
}
|
||||
|
||||
func (a *API) GetRealMobile4Order(orderId string) (mobile string, err error) {
|
||||
retVal, err := a.GetStoreOrderInfo(orderId)
|
||||
if err == nil {
|
||||
@@ -96,7 +246,7 @@ func (a *API) GetRealMobile4Order(orderId string) (mobile string, err error) {
|
||||
}
|
||||
|
||||
func (a *API) GetStoreOrderInfo(orderId string) (storeOrderInfo map[string]interface{}, err error) {
|
||||
retVal, err := a.AccessStorePage(fmt.Sprintf("crm/orderlist?keyword=%s", orderId))
|
||||
retVal, err := a.AccessStorePage(fmt.Sprintf("crm/orderlist?keyword=%s", orderId), nil)
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
||||
if err == nil {
|
||||
resultList := retVal["order_list"].([]interface{})
|
||||
@@ -123,7 +273,7 @@ func (a *API) GetStoreOrderInfoList(fromTime, toTime string, shopID string, orde
|
||||
}
|
||||
fixedURL := fmt.Sprintf(urlTemplate, params...)
|
||||
for {
|
||||
retVal, err2 := a.AccessStorePage(fixedURL + "&page=" + utils.Int2Str(pageNo))
|
||||
retVal, err2 := a.AccessStorePage(fixedURL+"&page="+utils.Int2Str(pageNo), nil)
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
||||
if err = err2; err == nil {
|
||||
resultList := retVal["order_list"].([]interface{})
|
||||
@@ -173,7 +323,7 @@ func (a *API) getCommentList(isElm bool, fromTime, toTime time.Time, shopID, sup
|
||||
}
|
||||
fixedURL := fmt.Sprintf(urlTemplate, params...)
|
||||
for {
|
||||
retVal, err2 := a.AccessStorePage(fixedURL + "&page_num=" + utils.Int2Str(pageNo))
|
||||
retVal, err2 := a.AccessStorePage(fixedURL+"&page_num="+utils.Int2Str(pageNo), nil)
|
||||
if err = err2; err == nil {
|
||||
for _, comment := range retVal["comment_list"].([]interface{}) {
|
||||
commentMap := comment.(map[string]interface{})
|
||||
@@ -213,7 +363,7 @@ func (a *API) PageGetSkuList(baiduShopID int64) (skuList []map[string]interface{
|
||||
}
|
||||
fixedURL := fmt.Sprintf(urlTemplate, params...)
|
||||
for {
|
||||
retVal, err2 := a.AccessStorePage(fixedURL + "&curpage=" + utils.Int2Str(pageNo))
|
||||
retVal, err2 := a.AccessStorePage(fixedURL+"&curpage="+utils.Int2Str(pageNo), nil)
|
||||
if err = err2; err == nil {
|
||||
for _, sku := range retVal["sku_list"].([]interface{}) {
|
||||
skuList = append(skuList, sku.(map[string]interface{}))
|
||||
@@ -236,7 +386,7 @@ func (a *API) PageGetCustomSkuList(baiduShopID int64, customCatID int64) (skuLis
|
||||
customCatID,
|
||||
}
|
||||
fixedURL := fmt.Sprintf(urlTemplate, params...)
|
||||
retVal, err := a.AccessStorePage(fixedURL)
|
||||
retVal, err := a.AccessStorePage(fixedURL, nil)
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(retVal["sku_list"].([]interface{})), nil
|
||||
}
|
||||
@@ -249,7 +399,7 @@ func (a *API) PageGetCustomCatList(baiduShopID int64) (catList []map[string]inte
|
||||
baiduShopID,
|
||||
}
|
||||
fixedURL := fmt.Sprintf(urlTemplate, params...)
|
||||
retVal, err := a.AccessStorePage(fixedURL)
|
||||
retVal, err := a.AccessStorePage(fixedURL, nil)
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(retVal["cat_list"].([]interface{})), nil
|
||||
}
|
||||
@@ -257,15 +407,17 @@ func (a *API) PageGetCustomCatList(baiduShopID int64) (catList []map[string]inte
|
||||
}
|
||||
|
||||
func (a *API) GetStoreInfo(storeId string) (storeInfo map[string]interface{}, err error) {
|
||||
retVal, err := a.AccessStorePage2(storeId)
|
||||
retVal, err := a.AccessStorePageNoCookie(fmt.Sprintf("newretail/shop/getshopinfo?&lat=0&lng=0&shop_id=%s", storeId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if retVal != nil {
|
||||
retVal["shop_id"] = storeId
|
||||
}
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func (a *API) AccessStorePage2(storeId string) (retVal map[string]interface{}, err error) {
|
||||
subURL := fmt.Sprintf("newretail/shop/getshopinfo?&lat=0&lng=0&shop_id=%s", storeId)
|
||||
func (a *API) AccessStorePageNoCookie(subURL string) (retVal map[string]interface{}, err error) {
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
fullURL := utils.GenerateGetURL(getStoreURL, subURL, nil)
|
||||
@@ -276,16 +428,12 @@ func (a *API) AccessStorePage2(storeId string) (retVal map[string]interface{}, e
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := int(utils.MustInterface2Int64(jsonResult1["error_no"]))
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1["result"].(map[string]interface{})
|
||||
retVal["shop_id"] = storeId
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
} else if code == GetStoreSuccessButUnderfind {
|
||||
retVal = make(map[string]interface{})
|
||||
retVal["shop_id"] = storeId
|
||||
retVal["storeIsUnderfind"] = 1
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
}
|
||||
newErr := utils.NewErrorIntCode(jsonResult1["error_msg"].(string), code)
|
||||
@@ -295,29 +443,61 @@ func (a *API) AccessStorePage2(storeId string) (retVal map[string]interface{}, e
|
||||
}
|
||||
|
||||
func (a *API) GetStoreList(lng string, lat string) (retVal map[string]interface{}, err error) {
|
||||
retVal, err = a.AccessStorePage3(fmt.Sprintf("/newretail/main/shoplist?channel=kitchen&pn=1&rn=999&lng=%s&lat=%s", lng, lat))
|
||||
retVal, err = a.AccessStorePageNoCookie(fmt.Sprintf("/newretail/main/shoplist?channel=kitchen&pn=1&rn=999&lng=%s&lat=%s", lng, lat))
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func (a *API) AccessStorePage3(subURL string) (retVal map[string]interface{}, err error) {
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
fullURL := utils.GenerateGetURL(getStoreURL, subURL, nil)
|
||||
request, _ := http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := int(utils.MustInterface2Int64(jsonResult1["error_no"]))
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1["result"].(map[string]interface{})
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
}
|
||||
newErr := utils.NewErrorIntCode(jsonResult1["error_msg"].(string), code)
|
||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||
})
|
||||
return retVal, err
|
||||
func (a *API) SwitchShop(baiduShopID int64) (switchShopCookie string, err error) {
|
||||
result, err := a.AccessStorePage("crm/manager/switchshop", map[string]interface{}{
|
||||
"switch_shop_id": baiduShopID,
|
||||
})
|
||||
if err == nil {
|
||||
switchShopCookie = utils.Interface2String(result["Value"])
|
||||
}
|
||||
return switchShopCookie, err
|
||||
}
|
||||
|
||||
func (a *API) GetShopUserInfo2(switchShopCookie string) (shopUserInfo *PageShopUserInfo, err error) {
|
||||
shopInfo, err := a.AccessStorePage2("crm/account/getshopuserinfo", nil, map[string]string{
|
||||
"SWITCH_SHOP": switchShopCookie,
|
||||
})
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(shopInfo, &shopUserInfo, true)
|
||||
}
|
||||
return shopUserInfo, err
|
||||
}
|
||||
|
||||
func (a *API) GetShopUserInfo(baiduShopID int64) (shopUserInfo *PageShopUserInfo, err error) {
|
||||
switchShopCookie, err := a.SwitchShop(baiduShopID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.GetShopUserInfo2(switchShopCookie)
|
||||
}
|
||||
|
||||
func (a *API) GetShopHealthByDetail2(switchShopCookie string) (shopHealthDetail *PageShopHealthInfo, err error) {
|
||||
shopInfo, err := a.GetShopUserInfo2(switchShopCookie)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := a.AccessStorePage2("crm/getshophealthydetail", map[string]interface{}{
|
||||
"shop_id": shopInfo.EleID,
|
||||
}, map[string]string{
|
||||
"SWITCH_SHOP": switchShopCookie,
|
||||
})
|
||||
if err == nil {
|
||||
if err = utils.Map2StructByJson(result, &shopHealthDetail, true); err == nil {
|
||||
shopHealthDetail.MerchantID = shopInfo.MerchantID
|
||||
shopHealthDetail.MerchantName = shopInfo.MerchantName
|
||||
}
|
||||
}
|
||||
return shopHealthDetail, err
|
||||
}
|
||||
|
||||
func (a *API) GetShopHealthByDetail(baiduShopID int64) (shopHealthDetail *PageShopHealthInfo, err error) {
|
||||
switchShopCookie, err := a.SwitchShop(baiduShopID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a.GetShopHealthByDetail2(switchShopCookie)
|
||||
}
|
||||
|
||||
@@ -81,3 +81,43 @@ func TestPageGetCustomCatList(t *testing.T) {
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(catList, false))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSwitchShop(t *testing.T) {
|
||||
cookie, err := api.SwitchShop(2233065941)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(cookie)
|
||||
}
|
||||
|
||||
func TestGetShopUserInfo(t *testing.T) {
|
||||
result, err := api.GetShopUserInfo(32267034127)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetShopHealthByDetail(t *testing.T) {
|
||||
result, err := api.GetShopHealthByDetail(32267034127)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetStoreList(t *testing.T) {
|
||||
result, err := api.GetStoreList("104.057218", "30.6949")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetStoreInfo(t *testing.T) {
|
||||
result, err := api.GetStoreInfo("170879219")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal *R
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
resultError, _ := jsonResult1["error"].(map[string]interface{})
|
||||
retVal = &ResponseResult{
|
||||
ID: jsonResult1["id"].(string),
|
||||
@@ -216,7 +216,7 @@ func (a *API) AcccessAPI2(baseURL string, params map[string]interface{}, method
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
retVal = jsonResult1
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
})
|
||||
|
||||
@@ -121,7 +121,7 @@ func (a *API) AccessAPI(apiName string, apiParams map[string]interface{}) (retVa
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := int(utils.Interface2Int64WithDefault(jsonResult1["ret"], ResponseCodeSuccess))
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1["data"]
|
||||
|
||||
@@ -2,19 +2,102 @@ package jdapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
CallbackPrefix = "/djsw/"
|
||||
)
|
||||
|
||||
// 如下的常量其实都是京东回调消息的
|
||||
const (
|
||||
OrderStatusAddComment = "12001"
|
||||
OrderStatusModifyComment = "12006"
|
||||
OrderStatusTipChanged = "12008"
|
||||
|
||||
OrderStatusPurchased = "41000" // 也即待处理,JD的消息很怪,新订单消息发过来是32000,但如果不是自动接单的,去查却是41000?,接单后才变为32000
|
||||
|
||||
OrderStatusPayed = "31020" // 已付款
|
||||
|
||||
StatusIDNewOrder = "32000"
|
||||
OrderStatusWaitOutStore = "32000"
|
||||
OrderStatusAdjust = "33080"
|
||||
StatusIDWaitOutStore = "32001"
|
||||
OrderStatusFinishedPickup = "2"
|
||||
OrderStatusDelivering = "33040"
|
||||
|
||||
OrderStatusDelivered = "33060"
|
||||
OrderStatusFinished = "90000"
|
||||
OrderStatusCanceled = "20020"
|
||||
|
||||
OrderStatusUserApplyCancel = "20030" // 这个其实不是一个状态,是一个动作
|
||||
OrderStatusLocked = "20010"
|
||||
OrderStatusUnlocked = "20050"
|
||||
OrderStatusInfoChanged = "1" // 订单信息变更消息
|
||||
|
||||
OrderStatusPayFinishedSettle = "330901" // 订单支付完成应结
|
||||
OrderStatusAdjustSettle = "330902" // 订单调整后应结
|
||||
OrderStatusSwitch2SelfSettle = "330903" // 订单众包配送转自送后应结
|
||||
)
|
||||
|
||||
const (
|
||||
StatusIDAddStore = "12003" // 新增门店消息
|
||||
StatusIDDelStore = "12004" // 删除门店消息
|
||||
StatusIDUpdateStore = "12009" // 修改门店消息
|
||||
)
|
||||
|
||||
const (
|
||||
AfsServiceStateWaiting4Audit = "10" // 待审核
|
||||
AfsServiceStateWaiting4UserFeedback = "11" // 待用户反馈
|
||||
AfsServiceStateWaiting4CSFeedback = "12" // 待客服反馈
|
||||
AfsServiceStateWaiting4GetGoods = "20" // 待取件
|
||||
AfsServiceStateRefundProcessing = "30" // 退款处理中
|
||||
AfsServiceStateWaiting4MerchantReceiveGoods = "31" // 待商家收货审核
|
||||
AfsServiceStateRefundSuccess = "32" // 退款成功
|
||||
AfsServiceStateRefundFailed = "33" // 退款失败
|
||||
AfsServiceStateAuditRefused = "40" // 审核不通过-驳回
|
||||
AfsServiceStateUserCanceled = "50" // 客户取消
|
||||
AfsServiceStateMerchantFailedReceiveGoods = "60" // 商家收货审核不通过
|
||||
AfsServiceStateSolved = "70" // 已解决
|
||||
AfsServiceStateWaiting4DirectCompensate = "90" // 待直陪
|
||||
AfsServiceStateDirectCompensate = "91" // 直赔
|
||||
AfsServiceStateDirectCompensateSuccess = "92" // 直赔成功
|
||||
AfsServiceStateDirectCompensateFailed = "93" // 直赔失败
|
||||
|
||||
AfsServiceStateWaiting4ReturnGoods = "110" // 待退货
|
||||
AfsServiceStateGetGoodsSuccess = "111" // 取货成功
|
||||
AfsServiceStateGettingGoods = "1101" // 取货中
|
||||
AfsServiceStateGetGoods2Shop = "1111" // 退货成功-商品已送至门店
|
||||
AfsServiceStateGetGoodsConfirmed = "1112" // 退货成功-商家已确认收货
|
||||
|
||||
AfsServiceStateGetGoodsWaiting4Refund = "112" // 退货成功-待退款
|
||||
AfsServiceStateReturnGoodsFailed = "113" // 退货失败
|
||||
AfsServiceStateReturnGoodsSuccess = "114" // 退货成功
|
||||
)
|
||||
|
||||
const (
|
||||
// 订单
|
||||
CallbackMsgDeliveryCarrierModify = "deliveryCarrierModify" // 订单转自送消息(是指转自送成功后,用处不大)
|
||||
CallbackMsgOrderAccounting = "orderAccounting" // 订单应结消息
|
||||
|
||||
// 账务
|
||||
CallbackMsgEndOrderFinance = "endOrderFinance" // 订单金额拆分完成消息
|
||||
CallbackMsgFinanceAdjustment = "financeAdjustment" // 财务调整单消息
|
||||
|
||||
// 售后
|
||||
CallbackMsgNewApplyAfterSaleBill = "newApplyAfterSaleBill" // 新建售后单申请消息
|
||||
CallbackMsgUpdateApplyAfterSaleBill = "updateApplyAfterSaleBill" // 修改售后单申请消息
|
||||
CallbackMsgNewAfterSaleBill = "newAfterSaleBill" // 新建售后单消息
|
||||
CallbackMsgAfterSaleBillStatus = "afterSaleBillStatus" // 售后单状态消息
|
||||
)
|
||||
|
||||
type CallbackResponse struct {
|
||||
Code string `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
@@ -22,7 +105,7 @@ type CallbackResponse struct {
|
||||
}
|
||||
|
||||
type CallbackOrderMsg struct {
|
||||
ID int `json:"-"` // 用于传递Jdorder的主键值,减少一次读库操作
|
||||
MsgURL string `json:"msgURL"`
|
||||
BillID string `json:"billId"`
|
||||
OutBillID string `json:"outBillId"`
|
||||
StatusID string `json:"statusId"`
|
||||
@@ -31,6 +114,7 @@ type CallbackOrderMsg struct {
|
||||
}
|
||||
|
||||
type CallbackDeliveryStatusMsg struct {
|
||||
MsgURL string `json:"msgURL"`
|
||||
OrderID string `json:"orderId"`
|
||||
DeliveryStatusTime string `json:"deliveryStatusTime"`
|
||||
DeliveryManNo string `json:"deliveryManNo"`
|
||||
@@ -62,12 +146,8 @@ const (
|
||||
OpenSourceBatchTask = 14
|
||||
)
|
||||
|
||||
const (
|
||||
SaleBillStatusRefundSuccess = "32"
|
||||
SaleBillStatusSaleReturnSuccess = "114"
|
||||
)
|
||||
|
||||
type CallbackStoreStockMsg struct {
|
||||
MsgURL string `json:"msgURL"`
|
||||
StationNo string `json:"stationNo"`
|
||||
SkuId int64 `json:"skuId"`
|
||||
Have bool `json:"have"`
|
||||
@@ -115,7 +195,12 @@ func (a *API) CheckCallbackValidation(values url.Values) (callbackResponse *Call
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *API) getCommonOrderCallbackMsg(data []byte, msg interface{}, needDecode bool) (callbackResponse *CallbackResponse) {
|
||||
func (a *API) getCommonOrderCallbackMsg(request *http.Request, msg interface{}, needDecode bool) (callbackResponse *CallbackResponse) {
|
||||
data, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
return Err2CallbackResponse(err, "")
|
||||
}
|
||||
// baseapi.SugarLogger.Debug(string(data))
|
||||
result, err := utils.HTTPBody2Values(data, needDecode)
|
||||
if err != nil {
|
||||
return FormatErrorResponse
|
||||
@@ -132,28 +217,34 @@ func (a *API) getCommonOrderCallbackMsg(data []byte, msg interface{}, needDecode
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *API) GetOrderCallbackMsg(data []byte) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
|
||||
func (a *API) GetOrderCallbackMsg(request *http.Request) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
|
||||
msg = new(CallbackOrderMsg)
|
||||
callbackResponse = a.getCommonOrderCallbackMsg(data, msg, false)
|
||||
if callbackResponse = a.getCommonOrderCallbackMsg(request, msg, false); callbackResponse == nil {
|
||||
msg.MsgURL = getMsgURLFromRequest(request)
|
||||
}
|
||||
return msg, callbackResponse
|
||||
}
|
||||
|
||||
func (a *API) GetOrderApplyCancelCallbackMsg(data []byte) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
|
||||
func (a *API) GetOrderApplyCancelCallbackMsg(request *http.Request) (msg *CallbackOrderMsg, callbackResponse *CallbackResponse) {
|
||||
msg = new(CallbackOrderMsg)
|
||||
callbackResponse = a.getCommonOrderCallbackMsg(data, msg, true)
|
||||
if callbackResponse = a.getCommonOrderCallbackMsg(request, msg, true); callbackResponse == nil {
|
||||
msg.MsgURL = getMsgURLFromRequest(request)
|
||||
}
|
||||
return msg, callbackResponse
|
||||
}
|
||||
|
||||
func (a *API) GetOrderDeliveryCallbackMsg(data []byte) (msg *CallbackDeliveryStatusMsg, callbackResponse *CallbackResponse) {
|
||||
msg = new(CallbackDeliveryStatusMsg)
|
||||
callbackResponse = a.getCommonOrderCallbackMsg(data, msg, true)
|
||||
func (a *API) GetOrderDeliveryCallbackMsg(request *http.Request) (msg *CallbackDeliveryStatusMsg, callbackResponse *CallbackResponse) {
|
||||
if callbackResponse = a.getCommonOrderCallbackMsg(request, &msg, true); callbackResponse == nil {
|
||||
msg.MsgURL = getMsgURLFromRequest(request)
|
||||
}
|
||||
return msg, callbackResponse
|
||||
}
|
||||
|
||||
func (a *API) GetStoreStockCallbackMsg(data []byte) (msg *CallbackStoreStockMsg, callbackResponse *CallbackResponse) {
|
||||
func (a *API) GetStoreStockCallbackMsg(request *http.Request) (msg *CallbackStoreStockMsg, callbackResponse *CallbackResponse) {
|
||||
msg = new(CallbackStoreStockMsg)
|
||||
msg.MsgURL = getMsgURLFromRequest(request)
|
||||
var tmpMsg map[string]interface{}
|
||||
callbackResponse = a.getCommonOrderCallbackMsg(data, &tmpMsg, true)
|
||||
callbackResponse = a.getCommonOrderCallbackMsg(request, &tmpMsg, true)
|
||||
if callbackResponse == nil {
|
||||
msg.StationNo = utils.Interface2String(tmpMsg["stationNo"])
|
||||
msg.SkuId = utils.Str2Int64(utils.Interface2String(tmpMsg["skuId"]))
|
||||
@@ -161,12 +252,15 @@ func (a *API) GetStoreStockCallbackMsg(data []byte) (msg *CallbackStoreStockMsg,
|
||||
msg.OperPin = utils.Interface2String(tmpMsg["operPin"])
|
||||
msg.OperTime = utils.Str2Int64(utils.Interface2String(tmpMsg["operTime"]))
|
||||
msg.OperSource = int(utils.Str2Int64((utils.Interface2String(tmpMsg["operSource"]))))
|
||||
have := utils.Interface2String(tmpMsg["have"])
|
||||
if have == "true" {
|
||||
msg.Have = true
|
||||
} else {
|
||||
msg.Have = false
|
||||
}
|
||||
msg.Have = utils.Interface2String(tmpMsg["have"]) == "true"
|
||||
}
|
||||
return msg, callbackResponse
|
||||
}
|
||||
|
||||
func getMsgURLFromRequest(request *http.Request) (msgURL string) {
|
||||
index := strings.Index(request.URL.Path, CallbackPrefix)
|
||||
if index >= 0 {
|
||||
msgURL = request.URL.Path[index+len(CallbackPrefix):]
|
||||
}
|
||||
return msgURL
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ func (a *API) AccessAPI(apiStr string, jdParams map[string]interface{}) (retVal
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := jsonResult1["code"].(string)
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1
|
||||
|
||||
@@ -27,7 +27,7 @@ func init() {
|
||||
// 天天果园
|
||||
// api = New("84541069-fbe2-424b-b625-9b2ba1d4c9e6", "5d5577a2506f41b8b4ec520ba83490f5", "0b01b9eeb15b41dab1c3d05d95c17a26")
|
||||
|
||||
api.SetStoreCookie("YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHBUOPCIUXDX4MQEAYEPUFFOAD4WJECT4R3K22T24MKC7OMIRDLX7S55243TDVXLO25PP4UYSPTTPMNRUFXDNP4WPE566Q6V4AH32F7HT")
|
||||
api.SetStoreCookie("YYJV3NHVBPHLD36FWP6F3EM5PTXJ2XZQS7U4HWRIDPP4IWGUKUIB4XG5N26CZRDLDF7PKOXBPD6BNTUAJLETLZOIWMCVFI3K6MYZIY4QBIXIMXYDJNUKFGJVQTN5356SAD6WPCIHWNQAG7DDMF7L7S3SHDYZP7PPVMRGO4VWG2JRBMKFTOGIWZ5L2XHXC3SXQ4OLX7EL4RKUPZQT6GOH63KE3EVK37L5LG7TGSDGXFQP4377YK72UB5YZG6IJH6PY25YLLCJYPMDSHKPGYBUFJ4MMMKGN6MWB37CP7XVDBBZJ3U462ENTEXH744AWCQCIG2AAE2PKYVHC")
|
||||
}
|
||||
|
||||
func TestTest(t *testing.T) {
|
||||
|
||||
@@ -2,34 +2,15 @@ package jdapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
OrderStatusAddComment = "12001"
|
||||
OrderStatusModifyComment = "12006"
|
||||
OrderStatusTipChanged = "12008"
|
||||
|
||||
OrderStatusPurchased = "41000" // 也即待处理,JD的消息很怪,新订单消息发过来是32000,但如果不是自动接单的,去查却是41000?,接单后才变为32000
|
||||
OrderStatusNew = "32000"
|
||||
OrderStatusAdjust = "33080"
|
||||
OrderStatusWaitOutStore = "32001"
|
||||
OrderStatusFinishedPickup = "2"
|
||||
OrderStatusDelivering = "33040"
|
||||
|
||||
OrderStatusDelivered = "33060"
|
||||
OrderStatusFinished = "90000"
|
||||
OrderStatusCanceled = "20020"
|
||||
|
||||
OrderStatusUserApplyCancel = "20030" // 这个其实不是一个状态,是一个动作
|
||||
OrderStatusLocked = "20010"
|
||||
OrderStatusUnlocked = "20050"
|
||||
OrderStatusInfoChanged = "1"
|
||||
|
||||
OrderStatusPayFinishedSettle = "330901" // 订单支付完成应结
|
||||
OrderStatusAdjustSettle = "330902" // 订单调整后应结
|
||||
OrderStatusSwitch2SelfSettle = "330903" // 订单众包配送转自送后应结
|
||||
AfsPicPrefix = "http://img10.360buyimg.com/o2o"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -71,20 +52,139 @@ const (
|
||||
QueryOrderRetryCount = 1 // 因为京东到家当前不存在的订单也返回-4,暂时不重试
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCanNotFindOrder = errors.New("can not find order")
|
||||
const (
|
||||
AfsApproveTypeRefund = 1 // 退款
|
||||
AfsApproveTypeReturnGoods = 2 // 退货
|
||||
AfsApproveTypeRefused = 3 // 驳回
|
||||
)
|
||||
|
||||
var (
|
||||
orderOperationResultParser = genNoPageResultParser("code", "msg", "detail", "0")
|
||||
const (
|
||||
AfsReasonTypeGoodsQuality = 201 // 商品质量问题/做工粗糙/有瑕疵
|
||||
AfsReasonTypeWrongGoods = 202 // 发错货
|
||||
AfsReasonTypeMissingGoods = 203 // 部分商品未收到
|
||||
AfsReasonTypeNoGoods = 501 // 全部商品未收到
|
||||
AfsReasonTypeDamagedGoods = 208 // 外表损伤(压坏,磕坏等)
|
||||
AfsReasonTypeGoodsQuantity = 207 // 缺斤少两
|
||||
AfsReasonTypeAgreedByMerchant = 209 // 与商家协商一致
|
||||
AfsReasonTypeGoodsSizeNoSame = 302 // 大小尺寸与商品描述不符
|
||||
AfsReasonTypeGoodsColorNoSame = 303 // 颜色/款式/图案与描述不符
|
||||
AfsReasonWrongPurchase = 402 // 误购
|
||||
AfsReasonNotReceivedIntime = 502 // 未在时效内送达
|
||||
)
|
||||
|
||||
const (
|
||||
AfsDealTypeRefund = "10" // 仅退款
|
||||
AfsDealTypeDirectCompensate = "30" // 直赔
|
||||
AfsDealTypeReturnGoodsRefund = "40" // 退货退款
|
||||
)
|
||||
|
||||
type AfsSkuDiscount struct {
|
||||
DetailDiscountType int `json:"detailDiscountType"`
|
||||
DiscountType int `json:"discountType"`
|
||||
PlatPayMoney int64 `json:"platPayMoney"`
|
||||
VenderPayMoney int64 `json:"venderPayMoney"`
|
||||
}
|
||||
|
||||
type AfsServiceDetail struct {
|
||||
SkuIDIsv string `json:"skuIdIsv"`
|
||||
WareID int64 `json:"wareId"`
|
||||
WareName string `json:"wareName"`
|
||||
WareNum int `json:"wareNum"`
|
||||
SkuCount int `json:"skuCount"`
|
||||
PromotionType int `json:"promotionType"`
|
||||
Weight float64 `json:"weight"`
|
||||
|
||||
AfsMoney int64 `json:"afsMoney"`
|
||||
PlatPayMoney int64 `json:"platPayMoney"`
|
||||
|
||||
AfsSkuDiscountList []*AfsSkuDiscount `json:"afsSkuDiscountList"`
|
||||
}
|
||||
|
||||
type AfsServiceResponse struct {
|
||||
AfsServiceID int64 `json:"afsServiceId"`
|
||||
AfsServiceOrder string `json:"afsServiceOrder"`
|
||||
AfsServiceState int `json:"afsServiceState"`
|
||||
CreateTime *utils.JavaDate `json:"createTime"`
|
||||
UpdateTime *utils.JavaDate `json:"updateTime"`
|
||||
CustomerMobilePhone string `json:"customerMobilePhone"`
|
||||
CustomerName string `json:"customerName"`
|
||||
OrderID string `json:"orderId"`
|
||||
OrderSource int `json:"orderSource"`
|
||||
OrderStatus int `json:"orderStatus"`
|
||||
OrderType int `json:"orderType"`
|
||||
PickwareAddress string `json:"pickwareAddress"`
|
||||
|
||||
OrderFreightMoney int64 `json:"orderFreightMoney"`
|
||||
AfsFreight int64 `json:"afsFreight"`
|
||||
PackagingMoney int64 `json:"packagingMoney"`
|
||||
TongchengFreightMoney int64 `json:"tongchengFreightMoney"`
|
||||
MealBoxMoney int64 `json:"mealBoxMoney"`
|
||||
|
||||
QuestionDesc string `json:"questionDesc"`
|
||||
QuestionPic string `json:"questionPic"`
|
||||
QuestionTypeCid int `json:"questionTypeCid"`
|
||||
|
||||
ApplyDeal string `json:"applyDeal"`
|
||||
DeliveryState string `json:"deliveryState"`
|
||||
DeliveryMan string `json:"deliveryMan"`
|
||||
DeliveryMobile string `json:"deliveryMobile"`
|
||||
|
||||
StationID string `json:"stationId"`
|
||||
StationName string `json:"stationName"`
|
||||
StationNumOutSystem string `json:"stationNumOutSystem"`
|
||||
VenderID string `json:"venderId"`
|
||||
|
||||
AfsDetailList []*AfsServiceDetail `json:"afsDetailList"`
|
||||
}
|
||||
|
||||
type OAOSAdjustDTO struct {
|
||||
SkuID int64 `json:"skuId,omitempty"`
|
||||
OutSkuID string `json:"outSkuId,omitempty"`
|
||||
SkuCount int `json:"skuCount"`
|
||||
}
|
||||
|
||||
type VenderAfsSkuDTO struct {
|
||||
SkuID int64 `json:"skuId"`
|
||||
SkuCount int `json:"skuCount"`
|
||||
PromotionType int `json:"promotionType"`
|
||||
}
|
||||
|
||||
type OrderSettlementInfo struct {
|
||||
AllAfterSaleFreight int64 `json:"allAfterSaleFreight"`
|
||||
AllAfterSalePackageMoney int64 `json:"allAfterSalePackageMoney"`
|
||||
BillTime *utils.JavaDate `json:"billTime"`
|
||||
DistanceFreightMoney int64 `json:"distanceFreightMoney"`
|
||||
FreightCommission int64 `json:"freightCommission"`
|
||||
GoodsCommission int64 `json:"goodsCommission"`
|
||||
GuaranteedCommission int64 `json:"guaranteedCommission"`
|
||||
OrderCashOnDeliveryMoney int64 `json:"orderCashOnDeliveryMoney"`
|
||||
OrderGiftCardMoney int64 `json:"orderGiftCardMoney"`
|
||||
OrderID int64 `json:"orderId"`
|
||||
OrgCode string `json:"orgCode"`
|
||||
PackageCommission int64 `json:"packageCommission"`
|
||||
PackageMoney int64 `json:"packageMoney"`
|
||||
PlatDeliveryFreight int64 `json:"platDeliveryFreight"`
|
||||
PlatFreightDiscountMoney int64 `json:"platFreightDiscountMoney"`
|
||||
PlatOrderGoodsDiscountMoney int64 `json:"platOrderGoodsDiscountMoney"`
|
||||
PlatSkuGoodsDiscountMoney int64 `json:"platSkuGoodsDiscountMoney"`
|
||||
SettlementAmount int64 `json:"settlementAmount"`
|
||||
StationNo string `json:"stationNo"`
|
||||
UserActualPaidGoodsMoney int64 `json:"userActualPaidGoodsMoney"`
|
||||
VenderDeliveryFreight int64 `json:"venderDeliveryFreight"`
|
||||
VenderFreightDiscountMoney int64 `json:"venderFreightDiscountMoney"`
|
||||
VenderOrderGoodsDiscountMoney int64 `json:"venderOrderGoodsDiscountMoney"`
|
||||
VenderPaidTips int64 `json:"venderPaidTips"`
|
||||
VenderSkuGoodsDiscountMoney int64 `json:"venderSkuGoodsDiscountMoney"`
|
||||
}
|
||||
|
||||
var (
|
||||
ErrCanNotFindOrder = errors.New("can not find order")
|
||||
)
|
||||
|
||||
var (
|
||||
orderOperationResultParser = genNoPageResultParser("code", "detail", "detail", "0")
|
||||
)
|
||||
|
||||
// 订单列表查询接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=169&apiid=ba3027848c3c4fda9674966e2a466482
|
||||
func (a *API) OrderQuery(jdParams map[string]interface{}) (retVal []interface{}, totalCount int, err error) {
|
||||
@@ -226,6 +326,14 @@ func (a *API) OrderShoudSettlementService(orderId string) (map[string]interface{
|
||||
return result.(map[string]interface{}), nil
|
||||
}
|
||||
|
||||
func (a *API) OrderShoudSettlementService2(orderId string) (orderSettlement *OrderSettlementInfo, err error) {
|
||||
result, err := a.OrderShoudSettlementService(orderId)
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &orderSettlement, false)
|
||||
}
|
||||
return orderSettlement, err
|
||||
}
|
||||
|
||||
// 查询售后单详情接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=6805ed690b7b4776b058067312c57d98
|
||||
func (a *API) GetAfsService(orderId string) (map[string]interface{}, error) {
|
||||
@@ -239,23 +347,35 @@ func (a *API) GetAfsService(orderId string) (map[string]interface{}, error) {
|
||||
return result.(map[string]interface{}), nil
|
||||
}
|
||||
|
||||
func (a *API) GetAfsService2(afsOrderID string) (afsOrderInfo *AfsServiceResponse, err error) {
|
||||
result, err := a.GetAfsService(afsOrderID)
|
||||
if err == nil {
|
||||
if err = utils.Map2StructByJson(result, &afsOrderInfo, false); err != nil {
|
||||
baseapi.SugarLogger.Warnf("GetAfsService2, result:%s failed with error:%v", utils.Format4Output(result, true), err)
|
||||
}
|
||||
}
|
||||
return afsOrderInfo, err
|
||||
}
|
||||
|
||||
// 商家审核用户取消申请接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=906b430307764a3ca3698c05c72f33d0
|
||||
func (a *API) OrderCancelOperate(orderId string, isAgreed bool, operator, remark string) (err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"orderId": orderId,
|
||||
"isAgreed": isAgreed,
|
||||
"operator": operator,
|
||||
"operator": utils.GetAPIOperator(operator),
|
||||
"remark": remark,
|
||||
}
|
||||
_, err = a.AccessAPINoPage("ocs/orderCancelOperate", jdParams, nil, nil, nullResultParser)
|
||||
return err
|
||||
}
|
||||
|
||||
// 订单调整接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=169&apiid=a7378109fd7243eea9efbb6231a7401c
|
||||
func (a *API) AdjustOrder(orderId, operPin, remark string, oaosAdjustDTOList []*OAOSAdjustDTO) (err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"orderId": orderId,
|
||||
"operPin": operPin,
|
||||
"operPin": utils.GetAPIOperator(operPin),
|
||||
"remark": remark,
|
||||
"oaosAdjustDTOList": oaosAdjustDTOList,
|
||||
}
|
||||
@@ -269,7 +389,7 @@ func (a *API) ReceiveFailedAudit(orderId string, isAgreed bool, operator, remark
|
||||
jdParams := map[string]interface{}{
|
||||
"orderId": orderId,
|
||||
"isAgreed": isAgreed,
|
||||
"operator": operator,
|
||||
"operator": utils.GetAPIOperator(operator),
|
||||
"remark": remark,
|
||||
}
|
||||
_, err = a.AccessAPINoPage("order/receiveFailedAudit", jdParams, nil, nil, nullResultParser)
|
||||
@@ -281,7 +401,7 @@ func (a *API) ReceiveFailedAudit(orderId string, isAgreed bool, operator, remark
|
||||
func (a *API) UrgeDispatching(orderId, updatePin string) (err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"orderId": orderId,
|
||||
"updatePin": updatePin,
|
||||
"updatePin": utils.GetAPIOperator(updatePin),
|
||||
}
|
||||
_, err = a.AccessAPINoPage("bm/urgeDispatching", jdParams, nil, nil, nullResultParser)
|
||||
return err
|
||||
@@ -297,3 +417,71 @@ func (a *API) ConfirmReceiveGoods(orderId string) (err error) {
|
||||
_, err = a.AccessAPINoPage("order/confirmReceiveGoods", jdParams, nil, nil, nullResultParser)
|
||||
return err
|
||||
}
|
||||
|
||||
// 申请售后单审核接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=1690f6efc0144d59823b236e0d8506a1
|
||||
func (a *API) AfsOpenApprove(afsOrderID string, afsApproveType int, rejectReason string, optPin string) (err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"serviceOrder": afsOrderID,
|
||||
"approveType": afsApproveType,
|
||||
"optPin": utils.GetAPIOperator(optPin),
|
||||
}
|
||||
if rejectReason != "" {
|
||||
jdParams["rejectReason"] = rejectReason
|
||||
}
|
||||
_, err = a.AccessAPINoPage("afs/afsOpenApprove", jdParams, nil, nil, nullResultParser)
|
||||
return err
|
||||
}
|
||||
|
||||
// 售后单确认收货接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=4826086e81934405980ae26f80d956e0
|
||||
func (a *API) ConfirmReceipt(afsOrderID, pin string) (err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"serviceOrder": afsOrderID,
|
||||
"pin": utils.GetAPIOperator(pin),
|
||||
}
|
||||
_, err = a.AccessAPINoPage("afs/confirmReceipt", jdParams, nil, nil, nullResultParser)
|
||||
return err
|
||||
}
|
||||
|
||||
// 商家自主发起售后接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=170&apiid=b8d1ddacb03846a8a2e78c79723c752f
|
||||
func (a *API) AfsSubmit(OrderID, pin, questionTypeCode, questionDesc, questionPic, customerName, customerMobilePhone, address string, skuList []*VenderAfsSkuDTO) (afsOrderID string, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"orderId": OrderID,
|
||||
"pin": utils.GetAPIOperator(pin),
|
||||
"questionTypeCode": questionTypeCode,
|
||||
}
|
||||
if questionDesc != "" {
|
||||
jdParams["questionDesc"] = questionDesc
|
||||
}
|
||||
if questionPic != "" {
|
||||
jdParams["questionPic"] = questionPic
|
||||
}
|
||||
if customerName != "" {
|
||||
jdParams["customerName"] = customerName
|
||||
}
|
||||
if customerMobilePhone != "" {
|
||||
jdParams["customerMobilePhone"] = customerMobilePhone
|
||||
}
|
||||
if address != "" {
|
||||
jdParams["address"] = address
|
||||
}
|
||||
result, err := a.AccessAPINoPage("afs/submit", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "0"))
|
||||
if err == nil {
|
||||
afsOrderID = utils.Interface2String(result.(map[string]interface{})["serviceOrder"])
|
||||
}
|
||||
return afsOrderID, err
|
||||
}
|
||||
|
||||
func ProcessQuestionPic(questionPic string) (outQuestionPic string) {
|
||||
if questionPic != "" {
|
||||
picList := strings.Split(questionPic, ",")
|
||||
picList2 := make([]string, len(picList))
|
||||
for index, pic := range picList {
|
||||
picList2[index] = AfsPicPrefix + "/" + pic
|
||||
}
|
||||
outQuestionPic = strings.Join(picList2, ",")
|
||||
}
|
||||
return outQuestionPic
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func TestOrderQuery(t *testing.T) {
|
||||
|
||||
func TestGetOrderCallbackMsg(t *testing.T) {
|
||||
callbackStr := "timestamp=2018-06-27+12%3A43%3A51&sign=84096ADFAB81E224D6231269AD1F6AAB&v=1.0&jd_param_json=%7B%22billId%22%3A%22815338526000221%22%2C%22statusId%22%3A%2232000%22%2C%22timestamp%22%3A%222018-06-27+12%3A42%3A34%22%7D&token=91633f2a-c5f5-4982-a925-a220d19095c3&app_key=1dba76d40cac446ca500c0391a0b6c9d&format=json"
|
||||
result, resp := api.GetOrderCallbackMsg([]byte(callbackStr))
|
||||
result, resp := api.GetOrderCallbackMsg(utils.BuildRequest(http.MethodPost, "", callbackStr, ""))
|
||||
|
||||
if resp != nil {
|
||||
t.Fatal(resp)
|
||||
@@ -60,7 +60,7 @@ func TestGetOrderCallbackMsg(t *testing.T) {
|
||||
|
||||
func TestGetOrderDeliveryCallbackMsg(t *testing.T) {
|
||||
callbackStr := "timestamp=2018-06-27%2B09%253A08%253A41&sign=54D9A8515BB5650DC3B81366E3286570&v=1.0&jd_param_json=%257B%2522createPin%2522%253A%2522JD_21134dac1c251d2%2522%252C%2522deliveryCarrierName%2522%253A%2522%25E8%25BE%25BE%25E8%25BE%25BE%25E4%25B8%2593%25E9%2580%2581%2522%252C%2522deliveryCarrierNo%2522%253A%25229966%2522%252C%2522deliveryStatus%2522%253A%252210%2522%252C%2522deliveryStatusTime%2522%253A%25222018-06-27%2B09%253A08%253A41%2522%252C%2522inputTime%2522%253A%25222018-06-27%2B09%253A08%253A41%2522%252C%2522orderId%2522%253A%2522815324888000121%2522%257D&token=91633f2a-c5f5-4982-a925-a220d19095c3&app_key=1dba76d40cac446ca500c0391a0b6c9d&format=json"
|
||||
result, resp := api.GetOrderDeliveryCallbackMsg([]byte(callbackStr))
|
||||
result, resp := api.GetOrderDeliveryCallbackMsg(utils.BuildRequest(http.MethodPost, "", callbackStr, ""))
|
||||
|
||||
if resp != nil {
|
||||
t.Fatal(resp)
|
||||
@@ -70,7 +70,7 @@ func TestGetOrderDeliveryCallbackMsg(t *testing.T) {
|
||||
|
||||
func TestGetOrderApplyCancelCallbackMsg(t *testing.T) {
|
||||
callbackStr := "timestamp=2018-06-27%2B13%253A35%253A29&sign=F1398D658514D8864FFB56F5EF2C4792&v=1.0&jd_param_json=%257B%2522billId%2522%253A%2522815339944000322%2522%252C%2522remark%2522%253A%2522%25E5%2595%2586%25E5%25AE%25B6%25E7%25BC%25BA%25E8%25B4%25A7%2522%252C%2522statusId%2522%253A%252220030%2522%252C%2522timestamp%2522%253A%25222018-06-27%2B13%253A35%253A24%2522%257D&token=91633f2a-c5f5-4982-a925-a220d19095c3&app_key=1dba76d40cac446ca500c0391a0b6c9d&format=json"
|
||||
result, resp := api.GetOrderApplyCancelCallbackMsg([]byte(callbackStr))
|
||||
result, resp := api.GetOrderApplyCancelCallbackMsg(utils.BuildRequest(http.MethodPost, "", callbackStr, ""))
|
||||
|
||||
if resp != nil {
|
||||
t.Fatal(resp)
|
||||
@@ -81,7 +81,7 @@ func TestGetOrderApplyCancelCallbackMsg(t *testing.T) {
|
||||
func TestSimulateSendNewOrderMsg(t *testing.T) {
|
||||
orderInfo := &CallbackOrderMsg{
|
||||
BillID: "813344594000041",
|
||||
StatusID: OrderStatusNew,
|
||||
StatusID: OrderStatusPurchased,
|
||||
Timestamp: utils.GetCurTimeStr(),
|
||||
}
|
||||
params := make(url.Values)
|
||||
@@ -163,7 +163,7 @@ func TestOrderAcceptOperate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOrderJDZBDelivery(t *testing.T) {
|
||||
result, err := api.OrderJDZBDelivery("813344594000041", "")
|
||||
result, err := api.OrderJDZBDelivery("911350836000622", "")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
@@ -171,7 +171,7 @@ func TestOrderJDZBDelivery(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifySellerDelivery(t *testing.T) {
|
||||
result, err := api.ModifySellerDelivery("813344594000041", "")
|
||||
result, err := api.ModifySellerDelivery("914376668000422", "")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
@@ -193,3 +193,27 @@ func TestDeliveryEndOrder(t *testing.T) {
|
||||
}
|
||||
sugarLogger.Debug(result)
|
||||
}
|
||||
|
||||
func TestGetAfsService(t *testing.T) {
|
||||
result, err := api.GetAfsService("22565438")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
sugarLogger.Debug(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetAfsService2(t *testing.T) {
|
||||
result, err := api.GetAfsService2("22565438")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
sugarLogger.Debug(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestOrderShoudSettlementService2(t *testing.T) {
|
||||
result, err := api.OrderShoudSettlementService2("914508761000241")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
sugarLogger.Debug(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
108
platformapi/jdapi/promotion_audit.go
Normal file
108
platformapi/jdapi/promotion_audit.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package jdapi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
AuditPromotionStateNew = 101 // 待开始
|
||||
AuditPromotionStateOnGoing = 102 // 进行中
|
||||
AuditPromotionStateEnded = 103 // 结束
|
||||
AuditPromotionStateCanceled = 104 // 取消
|
||||
AuditPromotionStateAll = 105 // 全部
|
||||
)
|
||||
|
||||
type OpenPlatActivityQResponse struct {
|
||||
AddLadderList []struct {
|
||||
BenefitMaxCount int `json:"benefitMaxCount"`
|
||||
DiscountAmount int `json:"discountAmount"`
|
||||
DiscountRate float32 `json:"discountRate"`
|
||||
LowMoney int `json:"lowMoney"`
|
||||
LowerLimitCount int `json:"lowerLimitCount"`
|
||||
OrderLadder string `json:"orderLadder"`
|
||||
} `json:"addLadderList"`
|
||||
Awords string `json:"awords"`
|
||||
BeginDate *utils.JavaDate `json:"beginDate"`
|
||||
CostRadios int `json:"costRadios"`
|
||||
EndDate *utils.JavaDate `json:"endDate"`
|
||||
ID int `json:"id"`
|
||||
IsMerchant int `json:"isMerchant"`
|
||||
OrderLadder string `json:"orderLadder"`
|
||||
OrgCode string `json:"orgCode"`
|
||||
OutActivityID string `json:"outActivityId"`
|
||||
PromotionName string `json:"promotionName"`
|
||||
SkuBeanList []struct {
|
||||
SkuID int64 `json:"skuId"`
|
||||
SkuName int64 `json:"skuName"`
|
||||
} `json:"skuBeanList"`
|
||||
State int `json:"state"`
|
||||
StationBeanList []struct {
|
||||
OrgCode interface{} `json:"orgCode"`
|
||||
OrgName string `json:"orgName"`
|
||||
OutStationNo string `json:"outStationNo"`
|
||||
StationName string `json:"stationName"`
|
||||
StationNo int `json:"stationNo"`
|
||||
} `json:"stationBeanList"`
|
||||
}
|
||||
|
||||
type PromotionLspQuerySkuResult struct {
|
||||
BeginTime *utils.JavaDate `json:"beginTime"`
|
||||
EndTime *utils.JavaDate `json:"endTime"`
|
||||
LimitDaily int `json:"limitDaily"`
|
||||
LimitDevice int `json:"limitDevice"`
|
||||
LimitPin int `json:"limitPin"`
|
||||
PlatformRatio int `json:"platformRatio"`
|
||||
PromotionPrice int `json:"promotionPrice"`
|
||||
PromotionState int `json:"promotionState"`
|
||||
PromotionType int `json:"promotionType"`
|
||||
SkuID int64 `json:"skuId"`
|
||||
Source string `json:"source"`
|
||||
StationNo int64 `json:"stationNo"`
|
||||
StoreRatio int `json:"storeRatio"`
|
||||
}
|
||||
|
||||
type PromotionLspQueryInfoResult struct {
|
||||
BeginTime *utils.JavaDate `json:"beginTime"`
|
||||
EndTime *utils.JavaDate `json:"endTime"`
|
||||
PromotionInfoID int64 `json:"promotionInfoId"`
|
||||
PromotionState int `json:"promotionState"`
|
||||
PromotionType int `json:"promotionType"`
|
||||
SkuResultList []*PromotionLspQuerySkuResult `json:"skuResultList"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
|
||||
// 此接口逐渐会被[新版订单级促销]中相应接口替换
|
||||
// 根据到家活动ID查询订单级活动明细接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=196&apiid=ff1ade31ac1b4a50be760854c777b567
|
||||
func (a *API) OrderDiscountQueryActivityInfoById(activityID int64, promotionType, state int, operator string) (response *OpenPlatActivityQResponse, err error) {
|
||||
params := map[string]interface{}{
|
||||
"activityId": activityID,
|
||||
"type": promotionType,
|
||||
"traceId": utils.GetUUID(),
|
||||
"operator": operator,
|
||||
"requestTime": time.Now().UnixNano() / 1000000,
|
||||
}
|
||||
if state > 0 {
|
||||
params["state"] = state
|
||||
}
|
||||
result, err := a.AccessAPINoPage("orderdiscount/queryActivityInfoById", params, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "10000"))
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &response, false)
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
// 根据到家活动ID查询单品级促销活动接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=196&apiid=a47520a9757f4b0dbac1e6d36fd1103d
|
||||
func (a *API) QueryPromotionInfo(promotionInfoId int64) (promotionInfo *PromotionLspQueryInfoResult, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"promotionInfoId": promotionInfoId,
|
||||
}
|
||||
result, err := a.AccessAPINoPage("singlePromote/queryPromotionInfo", jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "0"))
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &promotionInfo, false)
|
||||
}
|
||||
return promotionInfo, err
|
||||
}
|
||||
23
platformapi/jdapi/promotion_audit_test.go
Normal file
23
platformapi/jdapi/promotion_audit_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package jdapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestOrderDiscountQueryActivityInfoById(t *testing.T) {
|
||||
result, err := api.OrderDiscountQueryActivityInfoById(1297945, OrderDiscountActivityTypeManJian, 0, "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestQueryPromotionInfo(t *testing.T) {
|
||||
result, err := api.QueryPromotionInfo(43430316)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package jdapi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
// 新版订单级促销
|
||||
|
||||
const (
|
||||
OrderDiscountActivityTypeManJian = 1 // 满减
|
||||
OrderDiscountActivityTypeHuanGou = 1202 // 换购
|
||||
@@ -32,7 +32,7 @@ type OrderDiscountRuleRequest struct {
|
||||
DiscountRate float32 `json:"discountRate,omitempty"`
|
||||
AddPrice int `json:"addPrice,omitempty"` // 分
|
||||
GiftList []*OrderDiscountGift `json:"giftList,omitempty"`
|
||||
LadderLimit int `json:"ladderLimit,omitempty"`
|
||||
LadderLimit int `json:"ladderLimit"`
|
||||
}
|
||||
|
||||
type OrderDiscountActivity struct {
|
||||
@@ -44,11 +44,11 @@ type OrderDiscountActivity struct {
|
||||
ParticipationMode int `json:"participationMode"` // 必须
|
||||
OutStationNos []string `json:"outStationNos,omitempty"`
|
||||
StationNos []string `json:"stationNos,omitempty"`
|
||||
OutSkuIds []string `json:"outSkuIds,omitempty"`
|
||||
SkuIds []string `json:"skuIds,omitempty"`
|
||||
LimitOrderTotalNumber int `json:"limitOrderTotalNumber"` // 必须
|
||||
LimitUserTotalNumber int `json:"limitUserTotalNumber,omitempty"`
|
||||
Display string `json:"display"` // 必须
|
||||
OutSkuIDs []string `json:"outSkuIds,omitempty"`
|
||||
SkuIDs []string `json:"skuIds,omitempty"`
|
||||
LimitOrderTotalNumber int `json:"limitOrderTotalNumber"` // 必须, 活动限购单量(0为不限,不超过10万)
|
||||
LimitUserTotalNumber int `json:"limitUserTotalNumber,omitempty"` // 用户限购单量(0为不限,不超过100,仅满减和每满减有效)
|
||||
Display string `json:"display"` // 必须
|
||||
RuleRequestList []*OrderDiscountRuleRequest `json:"ruleRequestList,omitempty"`
|
||||
}
|
||||
|
||||
@@ -69,19 +69,45 @@ type ActivityOpQueryResultResponse struct {
|
||||
}
|
||||
|
||||
type ActivityOpQueryInfoResponse struct {
|
||||
ActivityID int64 `json:"activityID"`
|
||||
OutActivityID string `json:"outActivityId"`
|
||||
PromotionName string `json:"promotionName"`
|
||||
BeginDate time.Time `json:"beginDate"`
|
||||
EndDate time.Time `json:"endDate"`
|
||||
Awords string `json:"awords"`
|
||||
State int `json:"state"`
|
||||
OrderLadder string `json:"orderLadder"`
|
||||
StationList []int `json:"stationList"`
|
||||
SkuList []int `json:"skuList"`
|
||||
LadderList []int `json:"ladderList"`
|
||||
ActivityID int64 `json:"activityID"`
|
||||
OutActivityID string `json:"outActivityId"`
|
||||
PromotionName string `json:"promotionName"`
|
||||
BeginDate *utils.JavaDate `json:"beginDate"`
|
||||
EndDate *utils.JavaDate `json:"endDate"`
|
||||
Awords string `json:"awords"`
|
||||
State int `json:"state"`
|
||||
OrderLadder string `json:"orderLadder"`
|
||||
StationList []struct {
|
||||
OrgName string `json:"orgName"`
|
||||
StationNo int64 `json:"stationNo"`
|
||||
OutStationNo string `json:"outStationNo"`
|
||||
StationName string `json:"stationName"`
|
||||
} `json:"stationList"`
|
||||
SkuList []struct {
|
||||
OrgName string `json:"orgName"`
|
||||
SkuID int64 `json:"skuId"`
|
||||
OutSkuID string `json:"outSkuId"`
|
||||
SkuName string `json:"skuName"`
|
||||
} `json:"skuList"`
|
||||
LadderList []struct {
|
||||
BenefitMaxCount int `json:"benefitMaxCount"`
|
||||
DiscountAmount int `json:"discountAmount"`
|
||||
DiscountRate float32 `json:"discountRate"`
|
||||
LowMoney int `json:"lowMoney"`
|
||||
LowerLimitCount int `json:"lowerLimitCount"`
|
||||
OpGiftSkuList []struct {
|
||||
OrgName string `json:"orgName"`
|
||||
SkuID int64 `json:"skuId"`
|
||||
OutSkuID string `json:"outSkuId"`
|
||||
SkuName string `json:"skuName"`
|
||||
StockCount int `json:"stockCount"`
|
||||
} `json:"opGiftSkuList"`
|
||||
OrderLadder string `json:"orderLadder"`
|
||||
} `json:"ladderList"`
|
||||
}
|
||||
|
||||
// 订单级促销活动提交接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=cf98af94d4124ca287af6cfe48f0f3aa
|
||||
func (a *API) OrderDiscountSubmitActivity(actInfo *OrderDiscountActivity) (activityID int64, err error) {
|
||||
result, err := a.AccessAPINoPage("orderdiscount/submitActivity", utils.Struct2FlatMap(actInfo), nil, nil, nil)
|
||||
if err == nil {
|
||||
@@ -90,60 +116,46 @@ func (a *API) OrderDiscountSubmitActivity(actInfo *OrderDiscountActivity) (activ
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// 订单级促销活动查询活动提交处理结果接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=b04e5426948349a78db1c5c9585d8df7
|
||||
func (a *API) OrderDiscountQuerySubmitActivityResult(activityID int64) (response *ActivityOpQueryResultResponse, err error) {
|
||||
result, err := a.AccessAPINoPage("orderdiscount/querySubmitActivityResult", map[string]interface{}{
|
||||
"activityId": activityID,
|
||||
"operator": "jxc4",
|
||||
"operator": utils.APIPin,
|
||||
"traceId": utils.GetUUID(),
|
||||
}, nil, nil, nil)
|
||||
}, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
|
||||
if err == nil {
|
||||
resultMap := result.(map[string]interface{})
|
||||
response = &ActivityOpQueryResultResponse{
|
||||
SubCode: utils.Interface2String(resultMap["subCode"]),
|
||||
SubMsg: utils.Interface2String(resultMap["subMsg"]),
|
||||
}
|
||||
for _, v := range resultMap["resultList"].([]interface{}) {
|
||||
vMap := v.(map[string]interface{})
|
||||
response.ResultList = append(response.ResultList, &ActivityOpResultInfo{
|
||||
ActivityID: utils.MustInterface2Int64(vMap["activityId"]),
|
||||
PromName: utils.Interface2String(vMap["promName"]),
|
||||
StationNo: utils.MustInterface2Int64(vMap["stationNo"]),
|
||||
SkuID: utils.MustInterface2Int64(vMap["skuId"]),
|
||||
OutActivityID: utils.Interface2String(vMap["outActivityId"]),
|
||||
OutSkuID: utils.Interface2String(vMap["outSkuId"]),
|
||||
OutStationNo: utils.Interface2String(vMap["outStationNo"]),
|
||||
})
|
||||
}
|
||||
err = utils.Map2StructByJson(result.([]interface{})[0], &response, true) // todo,只取第一个?
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
// func (a *API) OrderDiscountQueryActivityInfo(activityID int64) (response *OrderDiscountResultResponse, err error) {
|
||||
// result, err := a.AccessAPINoPage("orderdiscount/queryActivityInfo", map[string]interface{}{
|
||||
// "activityId": activityID,
|
||||
// "sourceFrom": 3,
|
||||
// "operator": "",
|
||||
// "traceId": "",
|
||||
// "version": "",
|
||||
// }, nil, nil, nil)
|
||||
// if err == nil {
|
||||
// resultMap := result.(map[string]interface{})
|
||||
// response = &OrderDiscountResultResponse{
|
||||
// SubCode: utils.Interface2String(resultMap["subCode"]),
|
||||
// SubMsg: utils.Interface2String(resultMap["subMsg"]),
|
||||
// }
|
||||
// for _, v := range resultMap["resultList"].([]interface{}) {
|
||||
// vMap := v.(map[string]interface{})
|
||||
// response.ResultList = append(response.ResultList, &OrderDiscountResultInfo{
|
||||
// ActivityID: utils.MustInterface2Int64(vMap["activityId"]),
|
||||
// PromName: utils.Interface2String(vMap["promName"]),
|
||||
// StationNo: utils.MustInterface2Int64(vMap["stationNo"]),
|
||||
// SkuID: utils.MustInterface2Int64(vMap["skuId"]),
|
||||
// OutActivityId: utils.Interface2String(vMap["outActivityId"]),
|
||||
// OutSkuId: utils.Interface2String(vMap["outSkuId"]),
|
||||
// OutStationNo: utils.Interface2String(vMap["outStationNo"]),
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// return response, err
|
||||
// }
|
||||
// 订单级促销活动查询促销详情接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=116d7dfe0b4e4122be300ce26b4e5381
|
||||
func (a *API) OrderDiscountQueryActivityInfo(activityID int64) (response *ActivityOpQueryInfoResponse, err error) {
|
||||
result, err := a.AccessAPINoPage("orderdiscount/queryActivityInfo", map[string]interface{}{
|
||||
"activityId": activityID,
|
||||
"sourceFrom": 3,
|
||||
"operator": utils.APIPin,
|
||||
"traceId": "",
|
||||
"version": "",
|
||||
}, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &response, true)
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
// 订单级促销活动取消接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=211&apiid=42509fdfeec14105a516b07b774a3055
|
||||
func (a *API) OrderDiscountCancelActivity(activityID int64, operator, traceID string) (err error) {
|
||||
if traceID == "" {
|
||||
traceID = utils.GetUUID()
|
||||
}
|
||||
_, err = a.AccessAPINoPage("orderdiscount/cancelActivity", map[string]interface{}{
|
||||
"activityId": activityID,
|
||||
"operator": utils.GetAPIOperator(operator),
|
||||
"traceId": traceID,
|
||||
}, nil, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -9,21 +9,22 @@ import (
|
||||
|
||||
func TestOrderDiscountSubmitActivity(t *testing.T) {
|
||||
actInfo := &OrderDiscountActivity{
|
||||
OutActivityID: utils.GetUUID(),
|
||||
PromName: "测试0404",
|
||||
PromType: OrderDiscountActivityTypeManJian,
|
||||
BeginTime: utils.Time2Str(time.Now().Add(1 * time.Hour)),
|
||||
EndTime: utils.Time2Str(time.Now().Add(48 * time.Hour)),
|
||||
ParticipationMode: ParticipationModeAllSku,
|
||||
Display: "hello",
|
||||
OutStationNos: []string{"25"},
|
||||
OutSkuIds: []string{"5199"},
|
||||
OutActivityID: utils.GetUUID(),
|
||||
PromName: "测试0404",
|
||||
PromType: OrderDiscountActivityTypeManJian,
|
||||
BeginTime: utils.Time2Str(time.Now().Add(1 * time.Hour)),
|
||||
EndTime: utils.Time2Str(time.Now().Add(48 * time.Hour)),
|
||||
ParticipationMode: ParticipationModePartSku,
|
||||
Display: "hello",
|
||||
OutStationNos: []string{"2"},
|
||||
// OutSkuIDs: []string{"5199"},
|
||||
SkuIDs: []string{"2023747677"},
|
||||
LimitUserTotalNumber: 1,
|
||||
RuleRequestList: []*OrderDiscountRuleRequest{
|
||||
&OrderDiscountRuleRequest{
|
||||
LowerLimitAmount: 100,
|
||||
DiscountAmount: 1000,
|
||||
DiscountRate: 0.5,
|
||||
LowerLimitAmount: 1000,
|
||||
DiscountAmount: 100,
|
||||
DiscountRate: 8.5,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -35,9 +36,24 @@ func TestOrderDiscountSubmitActivity(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOrderDiscountQuerySubmitActivityResult(t *testing.T) {
|
||||
result, err := api.OrderDiscountQuerySubmitActivityResult(3)
|
||||
result, err := api.OrderDiscountQuerySubmitActivityResult(10000051)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(result)
|
||||
}
|
||||
|
||||
func TestOrderDiscountQueryActivityInfo(t *testing.T) {
|
||||
result, err := api.OrderDiscountQueryActivityInfo(10000051)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestOrderDiscountCancelActivity(t *testing.T) {
|
||||
err := api.OrderDiscountCancelActivity(10000049, "test", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,30 +29,24 @@ const (
|
||||
PromotionStateEnded = 9
|
||||
)
|
||||
|
||||
type PromotionSkuResult struct {
|
||||
LimitDaily int
|
||||
LimitDevice int
|
||||
LimitPin int
|
||||
PlatformRatio int
|
||||
PromotionPrice int
|
||||
SkuId int64
|
||||
StationNo int64
|
||||
StoreRatio int
|
||||
}
|
||||
type PromotionSku struct {
|
||||
SkuID int64 `json:"skuId,omitempty"`
|
||||
OutSkuID string `json:"outSkuId,omitempty"`
|
||||
StationNo int64 `json:"stationNo,omitempty"`
|
||||
OutStationNo string `json:"outStationNo,omitempty"`
|
||||
|
||||
type PromotionInfo struct {
|
||||
BeginTime time.Time
|
||||
EndTime time.Time
|
||||
PromotionInfoId int64
|
||||
PromotionState int
|
||||
PromotionType int
|
||||
Source string
|
||||
SkuResultList []*PromotionSkuResult
|
||||
PromotionPrice int64 `json:"promotionPrice,omitempty"`
|
||||
LimitSkuCount int `json:"limitSkuCount,omitempty"`
|
||||
FailReason string `json:"failReason,omitempty"`
|
||||
}
|
||||
|
||||
func getPromotionCmd(inCmd string, promotionType int) (outCmd string) {
|
||||
if promotionType == PromotionTypeDirectDown {
|
||||
outCmd = "singlePromote/" + inCmd
|
||||
if inCmd == "adjustPromotionSku" || inCmd == "adjustPromotionTime" {
|
||||
outCmd = "promotesku/" + inCmd
|
||||
} else {
|
||||
outCmd = "singlePromote/" + inCmd
|
||||
}
|
||||
} else if promotionType == PromotionTypeLimitedTime {
|
||||
outCmd = "limitTime/" + inCmd
|
||||
} else {
|
||||
@@ -63,86 +57,115 @@ func getPromotionCmd(inCmd string, promotionType int) (outCmd string) {
|
||||
|
||||
// 单品直降添加主活动信息接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=ee8685c9be9b4aa5bdc41468c5ebc33b
|
||||
func (a *API) CreatePromotionInfosSingle(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
|
||||
return a.createPromotionInfos(PromotionTypeDirectDown, name, beginDate, endDate, outInfoId, advertising)
|
||||
func (a *API) CreatePromotionInfosSingle(name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
|
||||
return a.createPromotionInfos(PromotionTypeDirectDown, name, beginDate, endDate, outInfoId, advertising, traceId)
|
||||
}
|
||||
|
||||
// 单品直降添加活动规则信息接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=900a9577cb304bbbb59abb7c2c33854d
|
||||
func (a *API) CreatePromotionRulesSingle(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
|
||||
return a.createPromotionRules(PromotionTypeDirectDown, infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
|
||||
}
|
||||
|
||||
// 单品直降添加活动商品信息接口
|
||||
// 最多200条
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=0ad0715e0aaa42489cbeac36398e916d
|
||||
func (a *API) CreatePromotionSkuSingle(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
|
||||
return a.createPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus)
|
||||
func (a *API) CreatePromotionSkuSingle(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
|
||||
return a.createPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus, traceId)
|
||||
}
|
||||
|
||||
// 单品直降活动提交保存接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=b84e14eb341e470db8ed9b60f78edb16
|
||||
func (a *API) ConfirmPromotionSingle(infoId int64, outInfoId string) (err error) {
|
||||
return a.confirmPromotion(PromotionTypeDirectDown, infoId, outInfoId)
|
||||
func (a *API) ConfirmPromotionSingle(infoId int64, outInfoId, traceId string) (err error) {
|
||||
return a.confirmPromotion(PromotionTypeDirectDown, infoId, outInfoId, traceId)
|
||||
}
|
||||
|
||||
// 单品直降活动部分商品取消接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=cfd14470b3fe4625bd2405b20bf8cec4
|
||||
func (a *API) CancelPromotionSkuSingle(infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
|
||||
return a.cancelPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, cancelSkus, traceId)
|
||||
}
|
||||
|
||||
// 单品直降整个活动取消接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=178&apiid=3d02c2acad714bea86d20d498a1aa074
|
||||
func (a *API) CancelPromotionSingle(infoId int64, outInfoId string) (err error) {
|
||||
return a.cancelPromotion(PromotionTypeDirectDown, infoId, outInfoId)
|
||||
func (a *API) CancelPromotionSingle(infoId int64, outInfoId, traceId string) (err error) {
|
||||
return a.cancelPromotion(PromotionTypeDirectDown, infoId, outInfoId, traceId)
|
||||
}
|
||||
|
||||
// 单品实时促销活动结束时间调整接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=0abab0c4b81d45e5bc555cc7dfbeb1ad
|
||||
func (a *API) AdjustPromotionTimeSingle(infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
|
||||
return a.adjustPromotionTime(PromotionTypeDirectDown, infoId, outInfoId, endDate, traceId)
|
||||
}
|
||||
|
||||
// 单品实时促销商品促销数量调整接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=178&apiid=82964e5e0f9c448db072a54ed20e00c4
|
||||
func (a *API) AdjustPromotionSkuSingle(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
|
||||
return a.adjustPromotionSku(PromotionTypeDirectDown, infoId, outInfoId, skus, traceId)
|
||||
}
|
||||
|
||||
// 以下为限时抢
|
||||
|
||||
// 限时抢添加活动主信息接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=7d8b7ff86c9e457bb8a46963cb575769
|
||||
func (a *API) CreatePromotionInfosLimitTime(name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
|
||||
return a.createPromotionInfos(PromotionTypeLimitedTime, name, beginDate, endDate, outInfoId, advertising)
|
||||
func (a *API) CreatePromotionInfosLimitTime(name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
|
||||
return a.createPromotionInfos(PromotionTypeLimitedTime, name, beginDate, endDate, outInfoId, advertising, traceId)
|
||||
}
|
||||
|
||||
// 限时抢添加活动规则信息接口(直降也是调用此接口)
|
||||
// 限时抢添加活动规则信息接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=e80674791d3542f0a87502753c0d0592
|
||||
func (a *API) CreatePromotionRules(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int) (err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"limitDevice": limitDevice,
|
||||
"limitPin": limitPin,
|
||||
"limitCount": limitCount,
|
||||
"limitDaily": limitDaily,
|
||||
"timeStamp": utils.GetCurTimeStr(),
|
||||
}
|
||||
if infoId != 0 {
|
||||
jdParams[KeyInfoId] = infoId
|
||||
} else {
|
||||
jdParams[KeyOutInfoId] = outInfoId
|
||||
}
|
||||
_, err = a.AccessAPINoPage("limitTime/createPromotionRules", jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
|
||||
return err
|
||||
func (a *API) CreatePromotionRulesLimitTime(infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
|
||||
return a.createPromotionRules(PromotionTypeLimitedTime, infoId, outInfoId, limitDevice, limitPin, limitCount, limitDaily, traceId)
|
||||
}
|
||||
|
||||
// 限时抢添加活动商品信息接口
|
||||
// 最多200条
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=65fecef4883c40c6b23bbdb6123f5d80
|
||||
func (a *API) CreatePromotionSkuLimitTime(infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
|
||||
return a.createPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus)
|
||||
func (a *API) CreatePromotionSkuLimitTime(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
|
||||
return a.createPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus, traceId)
|
||||
}
|
||||
|
||||
// 限时抢活动提交保存接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=3991063e2f0d435094e9fe44754f3490
|
||||
func (a *API) ConfirmPromotionLimitTime(infoId int64, outInfoId string) (err error) {
|
||||
return a.confirmPromotion(PromotionTypeLimitedTime, infoId, outInfoId)
|
||||
func (a *API) ConfirmPromotionLimitTime(infoId int64, outInfoId, traceId string) (err error) {
|
||||
return a.confirmPromotion(PromotionTypeLimitedTime, infoId, outInfoId, traceId)
|
||||
}
|
||||
|
||||
// 限时抢活动取消部分商品接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=01bd37df882749af91be4b040873ccc6
|
||||
func (a *API) CancelPromotionSkuLimitTime(infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
|
||||
return a.cancelPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, cancelSkus, traceId)
|
||||
}
|
||||
|
||||
// 限时抢整个活动取消接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=184&apiid=97b6678d30624f73bc13cb68987e6a6d
|
||||
func (a *API) CancelPromotionLimitTime(infoId int64, outInfoId string) (err error) {
|
||||
return a.cancelPromotion(PromotionTypeLimitedTime, infoId, outInfoId)
|
||||
func (a *API) CancelPromotionLimitTime(infoId int64, outInfoId, traceId string) (err error) {
|
||||
return a.cancelPromotion(PromotionTypeLimitedTime, infoId, outInfoId, traceId)
|
||||
}
|
||||
|
||||
func (a *API) createPromotionInfos(promotionType int, name string, beginDate, endDate time.Time, outInfoId, advertising string) (infoId int64, err error) {
|
||||
// 限时抢活动结束时间调整接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=f91035295cd54a9bbd2db9dfc800484c
|
||||
func (a *API) AdjustPromotionTimeLimitTime(infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
|
||||
return a.adjustPromotionTime(PromotionTypeLimitedTime, infoId, outInfoId, endDate, traceId)
|
||||
}
|
||||
|
||||
// 限时抢商品促销数量调整接口
|
||||
// https://openo2o.jddj.com/staticnew/widgets/resources.html?groupid=184&apiid=aa878a000dfb4a248634ee755af1f1d3
|
||||
func (a *API) AdjustPromotionSkuLimitTime(infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
|
||||
return a.adjustPromotionSku(PromotionTypeLimitedTime, infoId, outInfoId, skus, traceId)
|
||||
}
|
||||
|
||||
func (a *API) createPromotionInfos(promotionType int, name string, beginDate, endDate time.Time, outInfoId, advertising, traceId string) (infoId int64, err error) {
|
||||
if outInfoId == "" {
|
||||
outInfoId = fmt.Sprintf("%X", md5.Sum([]byte(name)))
|
||||
}
|
||||
jdParams := map[string]interface{}{
|
||||
"promotionName": name,
|
||||
"beginDate": utils.Time2Str(beginDate),
|
||||
"endDate": utils.Time2Str(endDate),
|
||||
"advertising": advertising,
|
||||
"promotionType": promotionType,
|
||||
"timeStamp": utils.GetCurTimeStr(),
|
||||
KeyOutInfoId: outInfoId,
|
||||
}
|
||||
jdParams := getCommonSkuPromotionParams(0, outInfoId, traceId)
|
||||
jdParams["promotionName"] = name
|
||||
jdParams["beginDate"] = utils.Time2Str(beginDate)
|
||||
jdParams["endDate"] = utils.Time2Str(endDate)
|
||||
jdParams["advertising"] = advertising
|
||||
jdParams["promotionType"] = promotionType
|
||||
jdParams["advertising"] = advertising
|
||||
result, err := a.AccessAPINoPage(getPromotionCmd("createPromotionInfos", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "0"))
|
||||
if err == nil {
|
||||
return utils.MustInterface2Int64(result), nil
|
||||
@@ -150,35 +173,64 @@ func (a *API) createPromotionInfos(promotionType int, name string, beginDate, en
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// todo skusResult 返回值没有意义,为了兼容暂时保留
|
||||
func (a *API) createPromotionSku(promotionType int, infoId int64, outInfoId string, skus []map[string]interface{}) (skusResult []map[string]interface{}, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"skus": skus,
|
||||
"timeStamp": utils.GetCurTimeStr(),
|
||||
}
|
||||
if infoId != 0 {
|
||||
jdParams[KeyInfoId] = infoId
|
||||
} else {
|
||||
jdParams[KeyOutInfoId] = outInfoId
|
||||
}
|
||||
_, err = a.AccessAPINoPage(getPromotionCmd("createPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
|
||||
return nil, err
|
||||
func (a *API) createPromotionRules(promotionType int, infoId int64, outInfoId string, limitDevice, limitPin, limitCount, limitDaily int, traceId string) (err error) {
|
||||
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
|
||||
jdParams["limitDevice"] = limitDevice
|
||||
jdParams["limitPin"] = limitPin
|
||||
jdParams["limitCount"] = limitCount
|
||||
jdParams["limitDaily"] = limitDaily
|
||||
_, err = a.AccessAPINoPage(getPromotionCmd("createPromotionRules", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) confirmPromotion(promotionType int, infoId int64, outInfoId string) (err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"timeStamp": utils.GetCurTimeStr(),
|
||||
}
|
||||
if infoId != 0 {
|
||||
jdParams[KeyInfoId] = infoId
|
||||
} else {
|
||||
jdParams[KeyOutInfoId] = outInfoId
|
||||
// todo skusResult 返回值没有意义,为了兼容暂时保留
|
||||
func (a *API) createPromotionSku(promotionType int, infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
|
||||
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
|
||||
jdParams["skus"] = skus
|
||||
// todo 当前是在出错时,把data中的数据当成错误信息处理的
|
||||
result, err := a.AccessAPINoPage(getPromotionCmd("createPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
|
||||
if err == nil && result != nil {
|
||||
err = utils.Map2StructByJson(result, &skusResult, false)
|
||||
}
|
||||
return skusResult, err
|
||||
}
|
||||
|
||||
func (a *API) confirmPromotion(promotionType int, infoId int64, outInfoId, traceId string) (err error) {
|
||||
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
|
||||
_, err = a.AccessAPINoPage(getPromotionCmd("confirmPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) cancelPromotion(promotionType int, infoId int64, outInfoId string) (err error) {
|
||||
func (a *API) cancelPromotionSku(promotionType int, infoId int64, outInfoId string, cancelSkus []*PromotionSku, traceId string) (err error) {
|
||||
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
|
||||
jdParams["cancelSkus"] = cancelSkus
|
||||
_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) cancelPromotion(promotionType int, infoId int64, outInfoId, traceId string) (err error) {
|
||||
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
|
||||
_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) adjustPromotionTime(promotionType int, infoId int64, outInfoId string, endDate time.Time, traceId string) (err error) {
|
||||
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
|
||||
_, err = a.AccessAPINoPage(getPromotionCmd("adjustPromotionTime", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) adjustPromotionSku(promotionType int, infoId int64, outInfoId string, skus []*PromotionSku, traceId string) (skusResult []*PromotionSku, err error) {
|
||||
jdParams := getCommonSkuPromotionParams(infoId, outInfoId, traceId)
|
||||
jdParams["skus"] = skus
|
||||
result, err := a.AccessAPINoPage(getPromotionCmd("adjustPromotionSku", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "data", "", "0"))
|
||||
if err == nil && result != nil {
|
||||
err = utils.Map2StructByJson(result, &skusResult, false)
|
||||
}
|
||||
return skusResult, err
|
||||
}
|
||||
|
||||
func getCommonSkuPromotionParams(infoId int64, outInfoId, traceId string) map[string]interface{} {
|
||||
jdParams := map[string]interface{}{
|
||||
"timeStamp": utils.GetCurTimeStr(),
|
||||
}
|
||||
@@ -187,42 +239,8 @@ func (a *API) cancelPromotion(promotionType int, infoId int64, outInfoId string)
|
||||
} else {
|
||||
jdParams[KeyOutInfoId] = outInfoId
|
||||
}
|
||||
_, err = a.AccessAPINoPage(getPromotionCmd("cancelPromotion", promotionType), jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "", "0"))
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) QueryPromotionInfo(promotionInfoId int64) (promotionInfo *PromotionInfo, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"promotionInfoId": promotionInfoId,
|
||||
if traceId != "" {
|
||||
jdParams["traceId"] = traceId
|
||||
}
|
||||
result, err := a.AccessAPINoPage("singlePromote/queryPromotionInfo", jdParams, nil, nil, genNoPageResultParser("errorCode", "errorInfos", "data", "0"))
|
||||
if err == nil {
|
||||
data := result.(map[string]interface{})
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(data, false))
|
||||
promotionInfo = &PromotionInfo{
|
||||
BeginTime: utils.Timestamp2Time(utils.MustInterface2Int64(data["beginTime"].(map[string]interface{})["time"]) / 1000),
|
||||
EndTime: utils.Timestamp2Time(utils.MustInterface2Int64(data["endTime"].(map[string]interface{})["time"]) / 1000),
|
||||
PromotionInfoId: utils.MustInterface2Int64(data["promotionInfoId"]),
|
||||
PromotionState: int(utils.MustInterface2Int64(data["promotionState"])),
|
||||
PromotionType: int(utils.MustInterface2Int64(data["promotionType"])),
|
||||
Source: utils.Interface2String(data["source"]),
|
||||
}
|
||||
skuResultList := data["skuResultList"].([]interface{})
|
||||
promotionInfo.SkuResultList = make([]*PromotionSkuResult, len(skuResultList))
|
||||
for k, v := range skuResultList {
|
||||
skuResult := v.(map[string]interface{})
|
||||
promotionInfo.SkuResultList[k] = &PromotionSkuResult{
|
||||
LimitDaily: int(utils.MustInterface2Int64(skuResult["limitDaily"])),
|
||||
LimitDevice: int(utils.MustInterface2Int64(skuResult["limitDevice"])),
|
||||
LimitPin: int(utils.MustInterface2Int64(skuResult["limitPin"])),
|
||||
PlatformRatio: int(utils.MustInterface2Int64(skuResult["platformRatio"])),
|
||||
PromotionPrice: int(utils.MustInterface2Int64(skuResult["promotionPrice"])),
|
||||
SkuId: utils.MustInterface2Int64(skuResult["skuId"]),
|
||||
StationNo: utils.MustInterface2Int64(skuResult["stationNo"]),
|
||||
StoreRatio: int(utils.MustInterface2Int64(skuResult["storeRatio"])),
|
||||
}
|
||||
}
|
||||
return promotionInfo, nil
|
||||
}
|
||||
return nil, err
|
||||
return jdParams
|
||||
}
|
||||
|
||||
@@ -6,67 +6,57 @@ import (
|
||||
)
|
||||
|
||||
func TestCreatePromotionSingle(t *testing.T) {
|
||||
infoId, err := api.CreatePromotionInfosSingle("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "")
|
||||
infoId, err := api.CreatePromotionInfosSingle("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(infoId)
|
||||
err = api.CreatePromotionRules(infoId, "", 1, 1, 1, 1)
|
||||
err = api.CreatePromotionRulesSingle(infoId, "", 1, 1, 1, 1, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
skuInfos, err := api.CreatePromotionSkuSingle(infoId, "", []map[string]interface{}{
|
||||
{
|
||||
KeyOutSkuId: "2216",
|
||||
KeyStationNo: 11682042,
|
||||
KeyPromotionPrice: 500,
|
||||
KeyLimitSkuCount: 2,
|
||||
skuInfos, err := api.CreatePromotionSkuSingle(infoId, "", []*PromotionSku{
|
||||
&PromotionSku{
|
||||
OutSkuID: "2216",
|
||||
StationNo: 11682042,
|
||||
PromotionPrice: 500,
|
||||
LimitSkuCount: 2,
|
||||
},
|
||||
})
|
||||
}, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(skuInfos)
|
||||
err = api.ConfirmPromotionSingle(infoId, "")
|
||||
err = api.ConfirmPromotionSingle(infoId, "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePromotionLimitTime(t *testing.T) {
|
||||
infoId, err := api.CreatePromotionInfosLimitTime("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "")
|
||||
infoId, err := api.CreatePromotionInfosLimitTime("测试1", time.Now(), time.Now().Add(24*time.Hour), "", "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(infoId)
|
||||
err = api.CreatePromotionRules(infoId, "", 1, 1, 5, 1)
|
||||
err = api.CreatePromotionRulesLimitTime(infoId, "", 1, 1, 5, 1, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
skuInfos, err := api.CreatePromotionSkuLimitTime(infoId, "", []map[string]interface{}{
|
||||
{
|
||||
KeyOutSkuId: "2216",
|
||||
KeyStationNo: 11682042,
|
||||
KeyPromotionPrice: 300,
|
||||
KeyLimitSkuCount: 2,
|
||||
skuInfos, err := api.CreatePromotionSkuLimitTime(infoId, "", []*PromotionSku{
|
||||
&PromotionSku{
|
||||
OutSkuID: "2216",
|
||||
StationNo: 11682042,
|
||||
PromotionPrice: 300,
|
||||
LimitSkuCount: 2,
|
||||
},
|
||||
})
|
||||
}, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(skuInfos)
|
||||
err = api.ConfirmPromotionLimitTime(infoId, "")
|
||||
err = api.ConfirmPromotionLimitTime(infoId, "", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryPromotionInfo(t *testing.T) {
|
||||
result, err := api.QueryPromotionInfo(14885272)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result.SkuResultList) == 0 {
|
||||
t.Fatal("should have SkuResultList")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
MaxSkuNameLen = 45 // skuname最长字符数
|
||||
MaxSkuNameCharCount = 45 // skuname最长字符数
|
||||
SaleAttrIDBase = 1001
|
||||
SaleAttrValueIDBase = 10
|
||||
)
|
||||
@@ -399,13 +399,7 @@ func (a *API) QueryKeyWordDicInfo(pageNo, pageSize int, keyValue string) (values
|
||||
// 商家商品状态同步接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=5e29d6c9317847e58b8cbcc70702fd52
|
||||
func (a *API) SyncProduct(storeId, skuId string) (retVal bool, err error) {
|
||||
result, err := a.AccessAPINoPage("search/syncProduct", utils.Params2Map(KeyStoreId, storeId, KeySkuId, skuId), nil, nil, func(data map[string]interface{}) (interface{}, error) {
|
||||
status := utils.MustInterface2Int64(data["status"])
|
||||
if status == 200 {
|
||||
return data["synchronized"].(bool), nil
|
||||
}
|
||||
return nil, utils.NewErrorIntCode(data["message"].(string), int(status))
|
||||
})
|
||||
result, err := a.AccessAPINoPage("search/syncProduct", utils.Params2Map(KeyStoreId, storeId, KeySkuId, skuId), nil, nil, genNoPageResultParser("status", "message", "synchronized", "200"))
|
||||
if err == nil {
|
||||
return result.(bool), nil
|
||||
}
|
||||
|
||||
@@ -58,12 +58,12 @@ func TestBatchUpdateOutSkuId(t *testing.T) {
|
||||
|
||||
func TestQuerySkuInfos(t *testing.T) {
|
||||
pageSize := 20
|
||||
result, totalCount, err := api.QuerySkuInfos("", 0, 0, pageSize, true)
|
||||
result, totalCount, err := api.QuerySkuInfos("一个高级商品", 0, 0, pageSize, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) != pageSize || totalCount == 0 {
|
||||
baseapi.SugarLogger.Debug(result)
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(result, false))
|
||||
t.Fatalf("QuerySkuInfos result size is not same as requested:%d", pageSize)
|
||||
}
|
||||
}
|
||||
@@ -95,32 +95,32 @@ func TestQueryKeyWordDicInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSyncProduct(t *testing.T) {
|
||||
result, err := api.SyncProduct("11732425", "2015717812")
|
||||
result, err := api.SyncProduct(mustExistStoreID, "2022250244")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
baseapi.SugarLogger.Debug(result)
|
||||
result, err = api.SyncProduct("wrongstoreid", "2015717812")
|
||||
result, err = api.SyncProduct("wrongstoreid", "2022250244")
|
||||
if err == nil {
|
||||
t.Fatal("SyncProduct should return error")
|
||||
}
|
||||
result, err = api.SyncProduct("11732425", "wrongskuid")
|
||||
result, err = api.SyncProduct(mustExistStoreID, "wrongskuid")
|
||||
if err == nil {
|
||||
t.Fatal("SyncProduct should return error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetProductStatust(t *testing.T) {
|
||||
result, err := api.GetProductStatus("11732425", "2015717812")
|
||||
result, err := api.GetProductStatus(mustExistStoreID, "2022250244")
|
||||
if err != nil || result == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// baseapi.SugarLogger.Debug(result)
|
||||
result, err = api.GetProductStatus("wrongstoreid", "2015717812")
|
||||
result, err = api.GetProductStatus("wrongstoreid", "2022250244")
|
||||
if err == nil {
|
||||
t.Fatal("GetProductStatus should return error")
|
||||
}
|
||||
result, err = api.GetProductStatus("11732425", "wrongskuid")
|
||||
result, err = api.GetProductStatus(mustExistStoreID, "wrongskuid")
|
||||
if err == nil {
|
||||
t.Fatal("GetProductStatus should return error")
|
||||
}
|
||||
|
||||
@@ -35,6 +35,23 @@ type CreateShopResult struct {
|
||||
StationNo string `json:"stationNo"`
|
||||
}
|
||||
|
||||
type CityInfo struct {
|
||||
AreaCode int `json:"areaCode"`
|
||||
AreaLevel int `json:"areaLevel"`
|
||||
AreaName string `json:"areaName"`
|
||||
ParentAreaID int `json:"parentAreaId"`
|
||||
TencentAddressCode int `json:"tencentAddressCode"`
|
||||
Yn int `json:"yn"`
|
||||
}
|
||||
|
||||
func (a *API) GetAllCities() (cities []*CityInfo, err error) {
|
||||
result, err := a.AccessAPINoPage("address/allcities", nil, nil, nil, genNoPageResultParser("code", "msg", "result", "0"))
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &cities, false)
|
||||
}
|
||||
return cities, err
|
||||
}
|
||||
|
||||
// 获取门店编码列表接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=194&apiid=138426aa19b54c48ae8464af1ca3b681
|
||||
func (a *API) GetStationsByVenderId() ([]string, error) {
|
||||
@@ -125,7 +142,7 @@ func (a *API) OrgReplyComment(orderID int64, storeID, content, replayPin string)
|
||||
"orderId": orderID,
|
||||
"storeId": storeID,
|
||||
"content": content,
|
||||
"replyPin": replayPin,
|
||||
"replyPin": utils.GetAPIOperator(replayPin),
|
||||
}
|
||||
_, err := a.AccessAPINoPage("commentOutApi/orgReplyComment", jdParams, nil, nil, genNoPageResultParser("code", "msg", "result", "200"))
|
||||
return err
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi"
|
||||
"git.rosy.net.cn/baseapi/platformapi"
|
||||
@@ -11,8 +12,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
accessStorePageCookieName = "shop.o2o.jd.com1"
|
||||
getStoreURL = "https://daojia.jd.com"
|
||||
getStoreURL = "https://daojia.jd.com"
|
||||
accessStorePageCookieName = "shop.o2o.jd.com1"
|
||||
accessStorePageCookieName2 = "lsp-store1.jddj.com"
|
||||
)
|
||||
|
||||
type SkuPageImg struct {
|
||||
@@ -21,6 +23,48 @@ type SkuPageImg struct {
|
||||
Small string `json:"small"`
|
||||
}
|
||||
|
||||
type CorporationInfo struct {
|
||||
Scope string `json:"scope"`
|
||||
OperName string `json:"oper_name"`
|
||||
Status string `json:"status"`
|
||||
BelongOrg string `json:"belong_org"`
|
||||
CreditNo string `json:"credit_no"`
|
||||
RegNo string `json:"reg_no"`
|
||||
ID string `json:"id"`
|
||||
OrgNo string `json:"org_no"`
|
||||
EconKind string `json:"econ_kind"`
|
||||
EndDate string `json:"end_date"`
|
||||
TermEnd string `json:"term_end"`
|
||||
NeedID bool `json:"needID"`
|
||||
Address string `json:"address"`
|
||||
Partners []struct {
|
||||
IdentifyType string `json:"identify_type"`
|
||||
ShouldCapiItems []interface{} `json:"should_capi_items"`
|
||||
StockType string `json:"stock_type"`
|
||||
IdentifyNo string `json:"identify_no"`
|
||||
RealCapiItems []interface{} `json:"real_capi_items"`
|
||||
Name string `json:"name"`
|
||||
} `json:"partners"`
|
||||
Name string `json:"name"`
|
||||
Province string `json:"province"`
|
||||
TermStart string `json:"term_start"`
|
||||
AbnormalItems []interface{} `json:"abnormal_items"`
|
||||
CheckDate string `json:"check_date"`
|
||||
RegistCapi string `json:"regist_capi"`
|
||||
StartDate string `json:"start_date"`
|
||||
Changerecords []struct {
|
||||
BeforeContent string `json:"before_content"`
|
||||
ChangeDate string `json:"change_date"`
|
||||
ChangeItem string `json:"change_item"`
|
||||
AfterContent string `json:"after_content"`
|
||||
} `json:"changerecords"`
|
||||
Branches []interface{} `json:"branches"`
|
||||
Employees []struct {
|
||||
JobTitle string `json:"job_title"`
|
||||
Name string `json:"name"`
|
||||
} `json:"employees"`
|
||||
}
|
||||
|
||||
func (a *API) SetStoreCookie(storeCookie string) {
|
||||
a.locker.Lock()
|
||||
defer a.locker.Unlock()
|
||||
@@ -33,14 +77,21 @@ func (a *API) GetStoreCookie() string {
|
||||
return a.storeCookie
|
||||
}
|
||||
|
||||
func (a *API) AccessStorePage(fullURL string) (retVal map[string]interface{}, err error) {
|
||||
func (a *API) AccessStorePage(fullURL string, formData map[string]interface{}) (retVal map[string]interface{}, err error) {
|
||||
storeCookie := a.GetStoreCookie()
|
||||
if storeCookie == "" {
|
||||
return nil, fmt.Errorf("需要设置Store Cookie才能使用此方法")
|
||||
}
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
request, _ := http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
var request *http.Request
|
||||
if formData == nil {
|
||||
request, _ = http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
} else {
|
||||
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(formData).Encode()))
|
||||
request.Header.Set("charset", "UTF-8")
|
||||
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -48,10 +99,14 @@ func (a *API) AccessStorePage(fullURL string) (retVal map[string]interface{}, er
|
||||
Name: accessStorePageCookieName,
|
||||
Value: storeCookie,
|
||||
})
|
||||
request.AddCookie(&http.Cookie{
|
||||
Name: accessStorePageCookieName2,
|
||||
Value: storeCookie,
|
||||
})
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
retVal = jsonResult1
|
||||
code := jsonResult1["code"].(string)
|
||||
if code == ResponseCodeSuccess {
|
||||
@@ -84,7 +139,7 @@ func (a *API) GetStoreOrderInfo(orderId, stationNo string) (storeOrderInfo map[s
|
||||
if stationNo != "" {
|
||||
urlStr += "&stationNo=" + stationNo
|
||||
}
|
||||
retVal, err := a.AccessStorePage(urlStr)
|
||||
retVal, err := a.AccessStorePage(urlStr, nil)
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
||||
if err == nil {
|
||||
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
|
||||
@@ -102,7 +157,7 @@ func (a *API) GetStoreOrderInfoList(fromTime, toTime string) (storeOrderList []m
|
||||
pageNo := 1
|
||||
urlTemplate := "http://store.jddj.com/order/newManager/tabQuery/all?o2oOrderType=10000&pageNo=%d&pageSize=%d&orderBy=&desc=true&startTimeQuery=%s&endTimeQuery=%s&stationNo="
|
||||
for {
|
||||
retVal, err := a.AccessStorePage(fmt.Sprintf(urlTemplate, pageNo, pageSize, url.QueryEscape(fromTime), url.QueryEscape(toTime)))
|
||||
retVal, err := a.AccessStorePage(fmt.Sprintf(urlTemplate, pageNo, pageSize, url.QueryEscape(fromTime), url.QueryEscape(toTime)), nil)
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(retVal, false))
|
||||
if err == nil {
|
||||
newOrderinfoMains := retVal["newOrderinfoMains"].(map[string]interface{})
|
||||
@@ -124,10 +179,7 @@ func (a *API) GetSkuPageInfo(skuId int64) (skuPageInfo map[string]interface{}, e
|
||||
"skuId": utils.Int64ToStr(skuId),
|
||||
"storeId": "0",
|
||||
}
|
||||
skuPageInfo, err = a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?platCode=H5&functionId=product/detailV6_0&body=%s", utils.Format4Output(skuIDMap, true)))
|
||||
if err == nil {
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(skuPageInfo, false))
|
||||
}
|
||||
skuPageInfo, err = a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?platCode=H5&functionId=product/detailV6_0&body=%s", utils.Format4Output(skuIDMap, true)), nil)
|
||||
return skuPageInfo, err
|
||||
}
|
||||
|
||||
@@ -140,34 +192,22 @@ func (a *API) GetSkuPageImageInfo(skuId int64) (imgList []*SkuPageImg, err error
|
||||
}
|
||||
|
||||
func (a *API) GetStoreInfo(storeId string) (storeInfo map[string]interface{}, err error) {
|
||||
retVal, err := a.AccessStorePage2(fmt.Sprintf("client?functionId=store/storeDetailV220&body={\"storeId\":\"%s\"}&appVersion=6.1.0", storeId))
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func (a *API) AccessStorePage2(subURL string) (retVal map[string]interface{}, err error) {
|
||||
err = platformapi.AccessPlatformAPIWithRetry(a.client,
|
||||
func() *http.Request {
|
||||
fullURL := utils.GenerateGetURL(getStoreURL, subURL, nil)
|
||||
request, _ := http.NewRequest(http.MethodGet, fullURL, nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := jsonResult1["code"].(string)
|
||||
if code == ResponseCodeSuccess && jsonResult1["result"] != nil {
|
||||
retVal = jsonResult1["result"].(map[string]interface{})
|
||||
return platformapi.ErrLevelSuccess, nil
|
||||
}
|
||||
newErr := utils.NewErrorCode(jsonResult1["msg"].(string), code)
|
||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||
})
|
||||
retVal, err := a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?functionId=store/storeDetailV220&body={\"storeId\":\"%s\"}&appVersion=6.1.0", storeId), nil)
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func (a *API) GetStoreList(lng string, lat string) (retVal map[string]interface{}, err error) {
|
||||
retVal, err = a.AccessStorePage2(fmt.Sprintf("client?platCode=h5&appVersion=6.5.0&functionId=zone/recommendStoreList&body={\"channelId\":\"3997\",\"currentPage\":1,\"pageSize\":999,\"coordType\":\"2\",\"platform\":\"1\"}&signKey=b63f63fa9e27123b84a0c80ef5cd210d&lng=%s&lat=%s", lng, lat))
|
||||
retVal, err = a.AccessStorePage(fmt.Sprintf("https://daojia.jd.com/client?platCode=h5&appVersion=6.5.0&functionId=zone/recommendStoreList&body={\"channelId\":\"3997\",\"currentPage\":1,\"pageSize\":999,\"coordType\":\"2\",\"platform\":\"1\"}&signKey=b63f63fa9e27123b84a0c80ef5cd210d&lng=%s&lat=%s", lng, lat), nil)
|
||||
return retVal, err
|
||||
}
|
||||
|
||||
func (a *API) GetCorporationInfo(stationNo, qualifyNumber string) (corporatonInfo *CorporationInfo, err error) {
|
||||
result, err := a.AccessStorePage("https://sta-store.jddj.com/store/requestQualify.o2o", map[string]interface{}{
|
||||
"stationNo": stationNo,
|
||||
"qualifyNumber": qualifyNumber,
|
||||
})
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &corporatonInfo, false)
|
||||
}
|
||||
return corporatonInfo, err
|
||||
}
|
||||
|
||||
@@ -54,3 +54,27 @@ func TestGetSkuPageImageInfo(t *testing.T) {
|
||||
}
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(imgList, false))
|
||||
}
|
||||
|
||||
func TestGetCorporationInfo(t *testing.T) {
|
||||
imgList, err := api.GetCorporationInfo("", "915101003431062533")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
baseapi.SugarLogger.Debug(utils.Format4Output(imgList, false))
|
||||
}
|
||||
|
||||
func TestGetStoreList(t *testing.T) {
|
||||
result, err := api.GetStoreList("104.057218", "30.6949")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetStoreInfo(t *testing.T) {
|
||||
result, err := api.GetStoreInfo("11750116")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
@@ -41,6 +41,38 @@ type SkuIdEntity struct {
|
||||
OutSkuId string `json:"outSkuId"`
|
||||
}
|
||||
|
||||
type StorePriceInfo struct {
|
||||
MarketPrice int64 `json:"marketPrice"`
|
||||
Pin string `json:"pin"`
|
||||
Price int64 `json:"price"`
|
||||
PromoteVipPrice int64 `json:"promoteVipPrice"`
|
||||
SkuID int64 `json:"skuId"`
|
||||
StationNo string `json:"stationNo"`
|
||||
VenderID string `json:"venderId"`
|
||||
VipPrice int64 `json:"vipPrice"`
|
||||
}
|
||||
|
||||
type QueryStockResponse struct {
|
||||
SkuID int64 `json:"skuId"`
|
||||
StationNo string `json:"stationNo"`
|
||||
UsableQty int `json:"usableQty"`
|
||||
LockQty int `json:"lockQty"`
|
||||
OrderQty int `json:"orderQty"`
|
||||
Vendibility int `json:"vendibility"`
|
||||
}
|
||||
|
||||
type UpdateVendibilityResponse struct {
|
||||
Code int `json:"code"`
|
||||
CurrentQty int `json:"currentQty"`
|
||||
LockQty int `json:"lockQty"`
|
||||
Msg string `json:"msg"`
|
||||
OrderQty int `json:"orderQty"`
|
||||
OutSkuID string `json:"outSkuId"`
|
||||
SkuID int64 `json:"skuId"`
|
||||
UsableQty int `json:"usableQty"`
|
||||
Vendibility int `json:"vendibility"`
|
||||
}
|
||||
|
||||
// 传入为数组的,最多一次为50个
|
||||
// 有好些功能有两个类似的函数,一个为到家ID,一个为商家ID,建议都只用商家ID的那个,因为:
|
||||
// 1,这类函数一般可以批量操作
|
||||
@@ -85,16 +117,16 @@ func (a *API) UpdateStationPrice(skuId int64, stationNo string, price int) (stri
|
||||
|
||||
// 根据到家商品编码和到家门店编码批量查询商品门店价格信息接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=205&apiid=21ccd5a00d3a4582b4c9a8ef0ae238fc
|
||||
func (a *API) GetStationInfoList(stationNo string, skuIds []int64) ([]map[string]interface{}, error) {
|
||||
func (a *API) GetStationInfoList(stationNo string, skuIds []int64) (priceInfo []*StorePriceInfo, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"skuIds": skuIds,
|
||||
"stationNo": stationNo,
|
||||
}
|
||||
result, err := a.AccessAPINoPage("price/getStationInfoList", jdParams, nil, nil, nil)
|
||||
result, err := a.AccessAPINoPage("price/getStationInfoList", jdParams, nil, nil, genNoPageResultParser("code", "detail", "result", "0"))
|
||||
if err == nil && result != nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
err = utils.Map2StructByJson(result, &priceInfo, false)
|
||||
}
|
||||
return nil, err
|
||||
return priceInfo, err
|
||||
}
|
||||
|
||||
// 根据商家商品编码和商家门店编码批量修改现货库存接口
|
||||
@@ -105,7 +137,7 @@ func (a *API) BatchUpdateCurrentQtys(outStationNo, stationNo string, skuStockLis
|
||||
}
|
||||
jdParams := map[string]interface{}{
|
||||
"skuStockList": skuStockList,
|
||||
"userPin": userPin,
|
||||
"userPin": utils.GetAPIOperator(userPin),
|
||||
}
|
||||
if outStationNo != "" {
|
||||
jdParams["outStationNo"] = outStationNo
|
||||
@@ -157,7 +189,7 @@ func (a *API) BatchUpdateVendibility(outStationNo, stationNo string, stockVendib
|
||||
}
|
||||
jdParams := map[string]interface{}{
|
||||
"stockVendibilityList": stockVendibilityList,
|
||||
"userPin": userPin,
|
||||
"userPin": utils.GetAPIOperator(userPin),
|
||||
}
|
||||
if outStationNo != "" {
|
||||
jdParams["outStationNo"] = outStationNo
|
||||
@@ -174,28 +206,28 @@ func (a *API) BatchUpdateVendibility(outStationNo, stationNo string, stockVendib
|
||||
// 根据到家商品编码和门店编码批量查询商品库存及可售状态信息接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=bc6ad75e8fd34580856e06b5eb149aad
|
||||
// 尽量不用这个接口,用下面那个
|
||||
func (a *API) QueryOpenUseable(listBaseStockCenterRequest []*BaseStockCenterRequest) ([]map[string]interface{}, error) {
|
||||
func (a *API) QueryOpenUseable(listBaseStockCenterRequest []*BaseStockCenterRequest) (stockResponse []*QueryStockResponse, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"listBaseStockCenterRequest": listBaseStockCenterRequest,
|
||||
}
|
||||
result, err := a.AccessAPINoPage("stock/queryOpenUseable", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
|
||||
if err == nil && result != nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
err = utils.Map2StructByJson(result, &stockResponse, false)
|
||||
}
|
||||
return nil, err
|
||||
return stockResponse, err
|
||||
}
|
||||
|
||||
// 根据商家商品编码和门店编码批量查询商品库存及可售状态信息接口
|
||||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=200&apiid=ba70316bb84f425f8c088d3c19b2570d
|
||||
func (a *API) QueryStockCenter(outStationNo string, skuIds []*SkuIdEntity, userPin string) ([]map[string]interface{}, error) {
|
||||
func (a *API) QueryStockCenter(outStationNo string, skuIds []*SkuIdEntity, userPin string) (vendibilityResponse []*UpdateVendibilityResponse, err error) {
|
||||
jdParams := map[string]interface{}{
|
||||
"outStationNo": outStationNo,
|
||||
"skuIds": skuIds,
|
||||
"userPin": userPin,
|
||||
"userPin": utils.GetAPIOperator(userPin),
|
||||
}
|
||||
result, err := a.AccessAPINoPage("stock/queryStockCenter", jdParams, nil, nil, genNoPageResultParser("retCode", "retMsg", "data", "0"))
|
||||
if err == nil && result != nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
err = utils.Map2StructByJson(result, &vendibilityResponse, false)
|
||||
}
|
||||
return nil, err
|
||||
return vendibilityResponse, err
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
mustExistSkuID = 2017194325
|
||||
mustExistSkuJXID = "21206"
|
||||
mustExistSkuID = 2023747677
|
||||
mustExistSkuJXID = "5246"
|
||||
)
|
||||
|
||||
func TestGetStationInfoList(t *testing.T) {
|
||||
@@ -17,9 +17,7 @@ func TestGetStationInfoList(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, v := range result {
|
||||
baseapi.SugarLogger.Debug(v)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestQueryOpenUseable(t *testing.T) {
|
||||
@@ -32,9 +30,7 @@ func TestQueryOpenUseable(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, v := range result {
|
||||
baseapi.SugarLogger.Debug(v)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestQueryStockCenter(t *testing.T) {
|
||||
@@ -46,9 +42,7 @@ func TestQueryStockCenter(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, v := range result {
|
||||
baseapi.SugarLogger.Debug(v)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestBatchUpdateVendibility(t *testing.T) {
|
||||
|
||||
@@ -9,10 +9,18 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
mustExistStoreID = "11738324"
|
||||
mustExistStoreJXID = "100285"
|
||||
mustExistStoreID = "11053496"
|
||||
mustExistStoreJXID = "2"
|
||||
)
|
||||
|
||||
func TestGetAllCities(t *testing.T) {
|
||||
result, err := api.GetAllCities()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetStationsByVenderId(t *testing.T) {
|
||||
result, err := api.GetStationsByVenderId()
|
||||
if err != nil {
|
||||
|
||||
@@ -215,7 +215,7 @@ func (a *API) AccessAPI(action string, params map[string]interface{}) (retVal *R
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
code := int(utils.MustInterface2Int64(jsonResult1["code"]))
|
||||
retVal = &ResponseResult{
|
||||
Code: code,
|
||||
|
||||
@@ -42,7 +42,7 @@ const (
|
||||
type FullDiscountActInfo struct {
|
||||
ActIDs string `json:"act_ids"`
|
||||
ActName string `json:"act_name"`
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单s位秒
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单位秒
|
||||
EndTime int64 `json:"end_time"` // 活动结束时间,单位秒
|
||||
ActType int `json:"act_type"`
|
||||
Status int `json:"-"`
|
||||
@@ -79,52 +79,105 @@ type ShippingFeeActDetail struct {
|
||||
LimitPrice float64 `json:"limit_price"`
|
||||
DiscountPrice float64 `json:"discount_price"`
|
||||
|
||||
PoiCharge float64 `json:"-"`
|
||||
MtCharge float64 `json:"-"`
|
||||
// list时用
|
||||
PoiCharge float64 `json:"poi_charge,omitempty"`
|
||||
MtCharge float64 `json:"mt_charge,omitempty"`
|
||||
}
|
||||
|
||||
type ShippingFeeActData struct {
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单s位秒
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单位秒
|
||||
EndTime int64 `json:"end_time"` // 活动结束时间,单位秒
|
||||
WeeksTime string `json:"weeks_time,omitempty"`
|
||||
Period string `json:"period,omitempty"`
|
||||
ActDetail []*ShippingFeeActDetail `json:"act_detail"`
|
||||
MaxPrice float64 `json:"max_price,omitempty"`
|
||||
|
||||
AppPoiCode string `json:"-"`
|
||||
ActID string `json:"-"`
|
||||
ActStatus string `json:"-"`
|
||||
// list时用
|
||||
AppPoiCode string `json:"app_poi_code,omitempty"`
|
||||
ActID int64 `json:"act_id,omitempty"`
|
||||
ActStatus string `json:"actStatus,omitempty"`
|
||||
}
|
||||
|
||||
type RetailActData struct {
|
||||
type RetailDiscountActData struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
UserType int `json:"user_type"`
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单s位秒
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单位秒
|
||||
EndTime int64 `json:"end_time"` // 活动结束时间,单位秒
|
||||
OrderLimit int `json:"order_limit"`
|
||||
DayLimit int `json:"day_limit"`
|
||||
WeeksTime string `json:"weeks_time"`
|
||||
Period string `json:"period"`
|
||||
WeeksTime string `json:"weeks_time"`
|
||||
SettingType int `json:"setting_type"`
|
||||
ActPrice float64 `json:"act_price"` // 折扣价格(单位元):必须为大于0的数字,且不能超过2位小数。
|
||||
DiscountCoefficient float64 `json:"discount_coefficient"` // 折扣系数:必须大于0小于9.8,最多支持两位小数。如输入3,即为3折
|
||||
Sequence int `json:"sequence,omitempty"`
|
||||
ItemID int64 `json:"item_id,omitempty"` // 活动ID,为什么这里又是int64
|
||||
|
||||
// 以下参数只有查询时用到
|
||||
OriginalPrice float64 `json:"-"` // 商品原价,单位元
|
||||
Stock int `json:"-"` // 当日剩余活动商品数量。只有当发起查询时间处于活动生效时段内时(start_time、end_time、period、weeks_time均需满足),该字段才代表实际剩余活动商品数量,否则显示的是创建活动时规定的当日活动库存
|
||||
Status int `json:"-"` // 活动状态,0:已过期,1:已生效,2:待生效。
|
||||
Name string `json:"-"`
|
||||
// list时用
|
||||
OriginalPrice float64 `json:"origin_price,omitempty"` // 商品原价,单位元
|
||||
Stock int `json:"stock,omitempty"` // 当日剩余活动商品数量。只有当发起查询时间处于活动生效时段内时(start_time、end_time、period、weeks_time均需满足),该字段才代表实际剩余活动商品数量,否则显示的是创建活动时规定的当日活动库存
|
||||
Status int `json:"status,omitempty"` // 活动状态,0:已过期,1:已生效,2:待生效。
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
||||
type RetailActDataLimit struct {
|
||||
type RetailDiscountActResult struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单位秒
|
||||
EndTime int64 `json:"end_time"` // 活动结束时间,单位秒
|
||||
ActID int64 `json:"act_id,omitempty"`
|
||||
Period string `json:"period"`
|
||||
WeeksTime string `json:"weeks_time"`
|
||||
}
|
||||
|
||||
type RetailDiscountActDataLimit struct {
|
||||
ItemID int64 `json:"item_id"` // 活动ID,为什么这里又是int64
|
||||
DayLimit int `json:"day_limit,omitempty"` // 当日活动库存,只能为正整数或-1,-1表示无限库存
|
||||
OrderLimit int `json:"order_limit,omitempty"` // 每单可购买的折扣商品数量
|
||||
}
|
||||
|
||||
func (a *API) FullDiscountBatchSave(poiCode string, actInfo *FullDiscountActInfo, actList []*FullDiscountActDetail, actSkuList []*FullDiscountSku) (actID int64, err error) {
|
||||
type LimitTime struct {
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单位秒
|
||||
EndTime int64 `json:"end_time"` // 活动结束时间,单位秒
|
||||
}
|
||||
|
||||
type CouponInfo struct {
|
||||
LimitPrice float64 `json:"limit_price"` //使用门槛,单位元
|
||||
CouponPrice float64 `json:"coupon_price"` // 优惠券金额,单位元
|
||||
UserType int `json:"user_type"` // 可领用户类型,新客、老客、全部
|
||||
ValidityDays int `json:"validity_days"` //使用有效期,用户领用了此商家券后在领用日起多久内可有效使用
|
||||
Stock int `json:"stock"`
|
||||
}
|
||||
|
||||
type CouponResult struct {
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单位秒
|
||||
EndTime int64 `json:"end_time"` // 活动结束时间,单位秒
|
||||
ActID int64 `json:"act_id,omitempty"`
|
||||
}
|
||||
|
||||
type CouponData struct {
|
||||
LimitPrice float64 `json:"limit_price"` //使用门槛,单位元
|
||||
CouponPrice float64 `json:"coupon_price"` // 优惠券金额,单位元
|
||||
UserType int `json:"user_type"` // 可领用户类型,新客、老客、全部
|
||||
ValidityDays int `json:"validity_days"` //使用有效期,用户领用了此商家券后在领用日起多久内可有效使用
|
||||
Stock int `json:"stock"`
|
||||
|
||||
UseCount int `json:"use_count"` // 劵已使用数量
|
||||
SentCount int `json:"sent_count"` // 劵已发数量
|
||||
}
|
||||
|
||||
type CouponActInfo struct {
|
||||
AppPoiCode string `json:"app_poi_code"`
|
||||
StartTime int64 `json:"start_time"` // 活动开始时间,单位秒
|
||||
EndTime int64 `json:"end_time"` // 活动结束时间,单位秒
|
||||
ActData []*CouponData `json:"act_data"` // 活动数据
|
||||
ActID int64 `json:"actId"`
|
||||
RemainDays int `json:"remain_days"` // 活动剩余天数
|
||||
Status int `json:"status"` // 活动状态
|
||||
}
|
||||
|
||||
// 批量创建指定商品满减活动或创建店内满减活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/255
|
||||
func (a *API) FullDiscountBatchSave(poiCode string, actInfo *FullDiscountActInfo, actList []*FullDiscountActDetail, actSkuList []*FullDiscountSku) (actIDList []int64, err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"act_info": string(utils.MustMarshal(actInfo)),
|
||||
@@ -135,11 +188,13 @@ func (a *API) FullDiscountBatchSave(poiCode string, actInfo *FullDiscountActInfo
|
||||
}
|
||||
result, err := a.AccessAPI2("act/full/discount/batchsave", false, params, resultKeyMsg)
|
||||
if err == nil {
|
||||
return utils.MustInterface2Int64(result.([]interface{})[0].(map[string]interface{})["act_id"]), nil
|
||||
err = utils.UnmarshalUseNumber([]byte(result.(string)), &actIDList)
|
||||
}
|
||||
return 0, err
|
||||
return actIDList, err
|
||||
}
|
||||
|
||||
// 批量查询指定商品满减活动或店内满减活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/256
|
||||
func (a *API) FullDiscountList(poiCode string, actType int) (actInfoList []*FullDiscountActData, err error) {
|
||||
result, err := a.AccessAPI("act/full/discount/list", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -151,6 +206,8 @@ func (a *API) FullDiscountList(poiCode string, actType int) (actInfoList []*Full
|
||||
return actInfoList, err
|
||||
}
|
||||
|
||||
// 批量删除指定商品满减活动或店内满减活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/257
|
||||
func (a *API) FullDiscountDelete(poiCode string, actIDList []string, actType int) (err error) {
|
||||
_, err = a.AccessAPI("act/full/discount/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -160,6 +217,8 @@ func (a *API) FullDiscountDelete(poiCode string, actIDList []string, actType int
|
||||
return err
|
||||
}
|
||||
|
||||
// 批量添加活动商品至指定商品满减活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/258
|
||||
func (a *API) FullDiscountFoodsBatchSave(poiCode, actID string, appFoodList []*FullDiscountSku) (err error) {
|
||||
_, err = a.AccessAPI("act/full/discount/foods/batchsave", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -169,6 +228,8 @@ func (a *API) FullDiscountFoodsBatchSave(poiCode, actID string, appFoodList []*F
|
||||
return err
|
||||
}
|
||||
|
||||
// 批量查询指定商品满减活动中的活动商品
|
||||
// http://developer.waimai.meituan.com/home/docDetail/259
|
||||
func (a *API) FullDiscountFoodsList(poiCode, actID string) (actFoodsInfo *FullDiscountFoodsInfo, err error) {
|
||||
limit := 200
|
||||
for {
|
||||
@@ -201,6 +262,7 @@ func (a *API) FullDiscountFoodsList(poiCode, actID string) (actFoodsInfo *FullDi
|
||||
|
||||
// 批量删除活动商品至指定商品满减活动
|
||||
// appFoodCodeList 删除商品数量上限为100,如果删除门店多个活动商品,用英文逗号隔开
|
||||
// http://developer.waimai.meituan.com/home/docDetail/260
|
||||
func (a *API) FullDiscountFoodsDelete(poiCode, actID string, appFoodCodeList []string) (err error) {
|
||||
_, err = a.AccessAPI("act/full/discount/foods/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -211,6 +273,7 @@ func (a *API) FullDiscountFoodsDelete(poiCode, actID string, appFoodCodeList []s
|
||||
}
|
||||
|
||||
// 批量修改指定商品满减活动中商品的当日活动库存
|
||||
// http://developer.waimai.meituan.com/home/docDetail/261
|
||||
func (a *API) FullDiscountFoodsDayLimit(poiCode, actID string, appFoodList []*FullDiscountSku) (err error) {
|
||||
_, err = a.AccessAPI("act/full/discount/foods/daylimit", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -222,6 +285,7 @@ func (a *API) FullDiscountFoodsDayLimit(poiCode, actID string, appFoodList []*Fu
|
||||
|
||||
// 阶梯满减配送费活动一个门店只可能有一个活动,所以不涉及actID的概念
|
||||
// 批量创建阶梯满减配送费活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/281
|
||||
func (a *API) FulllDiscountShippingFeeBatchSave(poiCode string, actData []*ShippingFeeActData) (err error) {
|
||||
_, err = a.AccessAPI("act/full/discount/shippingfee/batchsave", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -231,6 +295,7 @@ func (a *API) FulllDiscountShippingFeeBatchSave(poiCode string, actData []*Shipp
|
||||
}
|
||||
|
||||
// 查询阶梯满减配送费活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/282
|
||||
func (a *API) FulllDiscountShippingFeeList(poiCode string) (actList []*ShippingFeeActData, err error) {
|
||||
result, err := a.AccessAPI("act/full/discount/shippingfee/list", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -241,20 +306,32 @@ func (a *API) FulllDiscountShippingFeeList(poiCode string) (actList []*ShippingF
|
||||
return actList, err
|
||||
}
|
||||
|
||||
// 批量删除阶梯满减配送费活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/283
|
||||
func (a *API) FulllDiscountShippingFeeBatchDelete(poiCode string, actIDList []string) (err error) {
|
||||
_, err = a.AccessAPI("act/full/discount/shippingfee/batchdelete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"act_ids": strings.Join(actIDList, ","),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 批量创建或更新零售折扣商品
|
||||
func (a *API) RetailDiscountBatchSave(poiCode string, actData []*RetailActData) (actID int64, err error) {
|
||||
// http://developer.waimai.meituan.com/home/docDetail/287
|
||||
func (a *API) RetailDiscountBatchSave(poiCode string, actData []*RetailDiscountActData) (actResult []*RetailDiscountActResult, err error) {
|
||||
result, err := a.AccessAPI2("act/retail/discount/batchsave", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"act_data": string(utils.MustMarshal(actData)),
|
||||
}, resultKeyMsg)
|
||||
if err == nil {
|
||||
return utils.MustInterface2Int64(result.([]interface{})[0].(map[string]interface{})["act_id"]), nil
|
||||
err = utils.UnmarshalUseNumber([]byte(result.(string)), &actResult)
|
||||
}
|
||||
return 0, err
|
||||
return actResult, err
|
||||
}
|
||||
|
||||
// 查询门店零售折扣商品
|
||||
func (a *API) RetailDiscountList(poiCode string) (actList []*RetailActData, err error) {
|
||||
// http://developer.waimai.meituan.com/home/docDetail/288
|
||||
func (a *API) RetailDiscountList(poiCode string) (actList []*RetailDiscountActData, err error) {
|
||||
limit := 200
|
||||
offset := 0
|
||||
for {
|
||||
@@ -264,7 +341,7 @@ func (a *API) RetailDiscountList(poiCode string) (actList []*RetailActData, err
|
||||
"offset": offset,
|
||||
})
|
||||
if err == nil {
|
||||
var tmpActList []*RetailActData
|
||||
var tmpActList []*RetailDiscountActData
|
||||
if err = utils.Map2StructByJson(result, &tmpActList, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -281,6 +358,7 @@ func (a *API) RetailDiscountList(poiCode string) (actList []*RetailActData, err
|
||||
}
|
||||
|
||||
// 批量删除零售折扣商品
|
||||
// http://developer.waimai.meituan.com/home/docDetail/289
|
||||
func (a *API) RetailDiscountDelete(poiCode string, actIDList []string) (err error) {
|
||||
_, err = a.AccessAPI("act/retail/discount/batchdelete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
@@ -290,7 +368,8 @@ func (a *API) RetailDiscountDelete(poiCode string, actIDList []string) (err erro
|
||||
}
|
||||
|
||||
// 批量修改零售折扣商品当日活动库存
|
||||
func (a *API) RetailDiscountBatchStock(poiCode, actDataList []*RetailActDataLimit) (err error) {
|
||||
// http://developer.waimai.meituan.com/home/docDetail/290
|
||||
func (a *API) RetailDiscountBatchStock(poiCode, actDataList []*RetailDiscountActDataLimit) (err error) {
|
||||
_, err = a.AccessAPI("act/retail/discount/batchstock", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"act_data": string(utils.MustMarshal(actDataList)),
|
||||
@@ -299,10 +378,50 @@ func (a *API) RetailDiscountBatchStock(poiCode, actDataList []*RetailActDataLimi
|
||||
}
|
||||
|
||||
// 批量修改零售折扣商品每单限购数量
|
||||
func (a *API) RetailDiscountBatchLimit(poiCode, actDataList []*RetailActDataLimit) (err error) {
|
||||
// http://developer.waimai.meituan.com/home/docDetail/291
|
||||
func (a *API) RetailDiscountBatchLimit(poiCode, actDataList []*RetailDiscountActDataLimit) (err error) {
|
||||
_, err = a.AccessAPI("act/retail/discount/batchlimit", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"act_data": string(utils.MustMarshal(actDataList)),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 批量新增商家券(店内发券)活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/312
|
||||
func (a *API) InStoreCouponBatchSave(poiCode string, limitTime *LimitTime, couponInfoList []*CouponInfo) (couponResultList []*CouponResult, err error) {
|
||||
result, err := a.AccessAPI2("act/instore/coupon/batchsave", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"limit_time": string(utils.MustMarshal(limitTime)),
|
||||
"act_data": string(utils.MustMarshal(couponInfoList)),
|
||||
}, resultKeyMsg)
|
||||
if err == nil {
|
||||
err = utils.UnmarshalUseNumber([]byte(result.(string)), &couponResultList)
|
||||
}
|
||||
return couponResultList, err
|
||||
}
|
||||
|
||||
// 批量删除商家券(店内发券)活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/313
|
||||
func (a *API) InStoreCouponDelete(poiCode string, actIDList []string) (err error) {
|
||||
_, err = a.AccessAPI("act/instore/coupon/delete", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"act_ids": strings.Join(actIDList, ","),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// 查询商家券(店内发券)活动
|
||||
// http://developer.waimai.meituan.com/home/docDetail/314
|
||||
// 页码从1开始
|
||||
func (a *API) InStoreCouponList(poiCode string, pageNum, pageSize int) (couponActList []*CouponActInfo, err error) {
|
||||
result, err := a.AccessAPI("act/instore/coupon/list", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"page_num": pageNum,
|
||||
"page_size": pageSize,
|
||||
})
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &couponActList, false)
|
||||
}
|
||||
return couponActList, err
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestFullDiscountBatchSave(t *testing.T) {
|
||||
result, err := api.FullDiscountBatchSave("6693359", &FullDiscountActInfo{
|
||||
result, err := api.FullDiscountBatchSave(testPoiCode, &FullDiscountActInfo{
|
||||
// ActIDs: "12345678",
|
||||
ActName: "测试活动0402",
|
||||
StartTime: time.Now().Unix(),
|
||||
@@ -33,7 +33,7 @@ func TestFullDiscountBatchSave(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFullDiscountList(t *testing.T) {
|
||||
result, err := api.FullDiscountList("6737142", ActTypeStoreFullDiscount)
|
||||
result, err := api.FullDiscountList(testPoiCode, ActTypeStoreFullDiscount)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -41,7 +41,7 @@ func TestFullDiscountList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFullDiscountFoodsList(t *testing.T) {
|
||||
result, err := api.FullDiscountFoodsList("6737142", "497726932")
|
||||
result, err := api.FullDiscountFoodsList(testPoiCode, "497726932")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -49,14 +49,14 @@ func TestFullDiscountFoodsList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFulllDiscountShippingFeeBatchSave(t *testing.T) {
|
||||
err := api.FulllDiscountShippingFeeBatchSave("6737142", []*ShippingFeeActData{&ShippingFeeActData{}})
|
||||
err := api.FulllDiscountShippingFeeBatchSave(testPoiCode, []*ShippingFeeActData{&ShippingFeeActData{}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFulllDiscountShippingFeeList(t *testing.T) {
|
||||
result, err := api.FulllDiscountShippingFeeList("6737142")
|
||||
result, err := api.FulllDiscountShippingFeeList(testPoiCode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -64,8 +64,8 @@ func TestFulllDiscountShippingFeeList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRetailDiscountBatchSave(t *testing.T) {
|
||||
result, err := api.RetailDiscountBatchSave("6737142", []*RetailActData{&RetailActData{
|
||||
AppFoodCode: "24785",
|
||||
result, err := api.RetailDiscountBatchSave(testPoiCode, []*RetailDiscountActData{&RetailDiscountActData{
|
||||
AppFoodCode: "5246",
|
||||
UserType: UserTypeAll,
|
||||
StartTime: time.Now().Unix(),
|
||||
EndTime: time.Now().Add(24 * time.Hour).Unix(),
|
||||
@@ -81,7 +81,7 @@ func TestRetailDiscountBatchSave(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRetailDiscountList(t *testing.T) {
|
||||
result, err := api.RetailDiscountList("6737142")
|
||||
result, err := api.RetailDiscountList(testPoiCode)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -89,8 +89,16 @@ func TestRetailDiscountList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRetailDiscountDelete(t *testing.T) {
|
||||
err := api.RetailDiscountDelete("6737142", []string{"329187452"})
|
||||
err := api.RetailDiscountDelete(testPoiCode, []string{"329187452"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInStoreCouponList(t *testing.T) {
|
||||
result, err := api.InStoreCouponList(testPoiCode, 1, 100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
@@ -38,10 +38,31 @@ type CallbackResponse struct {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
// !!!特别注意,Data中的数据
|
||||
// 全额退款没有Food, FoodList, Money项
|
||||
type CallbackRefundInfo struct {
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
AppID string `json:"app_id"`
|
||||
Sig string `json:"sig"`
|
||||
|
||||
OrderID int64 `json:"order_id"`
|
||||
NotifyType string `json:"notify_type"`
|
||||
RefundID int64 `json:"refund_id"`
|
||||
Ctime int64 `json:"ctime"`
|
||||
Reason string `json:"reason"`
|
||||
ResType int `json:"res_type"`
|
||||
IsAppeal int `json:"is_appeal"`
|
||||
Pictures string `json:"pictures"`
|
||||
PictureList []string `json:"pictureList"`
|
||||
|
||||
Food string `json:"food"`
|
||||
FoodList []*RefundSkuDetail `json:"foodList"`
|
||||
Money float32 `json:"money"`
|
||||
}
|
||||
|
||||
type CallbackMsg struct {
|
||||
Data url.Values
|
||||
Cmd string
|
||||
Cmd string
|
||||
FormData url.Values
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -77,16 +98,29 @@ func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackR
|
||||
msg = &CallbackMsg{
|
||||
Cmd: cmd,
|
||||
}
|
||||
msg.Data = make(url.Values)
|
||||
msg.FormData = make(url.Values)
|
||||
for k, v := range data {
|
||||
// 美团外卖的用户催单信息的timestamp是毫秒(其它的事件是秒),统一归一化为秒
|
||||
if cmd == MsgTypeUserUrgeOrder && k == "timestamp" {
|
||||
intV := utils.Str2Int64(v.(string))
|
||||
if intV > time.Now().Unix()*2 {
|
||||
v = utils.Int64ToStr(intV / 1000)
|
||||
data[k] = v
|
||||
}
|
||||
}
|
||||
msg.Data.Set(k, v.(string))
|
||||
msg.FormData.Set(k, v.(string))
|
||||
}
|
||||
if msg.Cmd == MsgTypeOrderRefund || msg.Cmd == MsgTypeOrderPartialRefund {
|
||||
var refundData *CallbackRefundInfo
|
||||
if err = utils.Map2StructByJson(data, &refundData, true); err == nil {
|
||||
if refundData.Food != "" {
|
||||
utils.UnmarshalUseNumber([]byte(refundData.Food), &refundData.FoodList)
|
||||
}
|
||||
if refundData.Pictures != "" {
|
||||
utils.UnmarshalUseNumber([]byte(refundData.Pictures), &refundData.PictureList)
|
||||
}
|
||||
msg.Data = refundData
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -98,3 +132,8 @@ func (a *API) GetCallbackMsg(request *http.Request) (msg *CallbackMsg, callbackR
|
||||
}
|
||||
return msg, callbackResponse
|
||||
}
|
||||
|
||||
func (a *API) GetRefundSkuDetailFromMsg(msg *CallbackMsg) (refundSkuDetail []*RefundSkuDetail) {
|
||||
utils.UnmarshalUseNumber([]byte(msg.FormData.Get("food")), &refundSkuDetail)
|
||||
return refundSkuDetail
|
||||
}
|
||||
|
||||
19
platformapi/mtwmapi/callback_test.go
Normal file
19
platformapi/mtwmapi/callback_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestGetRefundSkuDetailFromMsg(t *testing.T) {
|
||||
data, _ := url.ParseQuery(`
|
||||
/mtwm/orderPartialRefund?timestamp=1556595759&reason=%E5%BA%97%E9%93%BA%E5%A4%AA%E5%BF%99%E4%BA%86%21%E5%AE%A2%E5%AE%98%E6%88%91%E6%80%95%E6%82%A8%E7%AD%89%E7%9A%84%E5%A4%AA%E4%B9%85&food=%5B%7B%22app_food_code%22%3A%2231458%22%2C%22box_num%22%3A0%2C%22box_price%22%3A0%2C%22count%22%3A1%2C%22food_name%22%3A%22%E9%B2%9C%E7%AB%B9%E7%AC%8B%EF%BC%88%E9%B8%A1%E5%A9%86%E7%AC%8B%EF%BC%89%5B%E6%9C%AA%E6%B3%A1%E6%B0%B4%5D%E7%BA%A6250g%2F%E4%BB%BD%22%2C%22food_price%22%3A7.97%2C%22origin_food_price%22%3A7.97%2C%22refund_price%22%3A7.97%2C%22sku_id%22%3A%2231458%22%2C%22spec%22%3A%22250g%22%7D%5D&money=7.97&is_appeal=0&pictures=¬ify_type=agree&app_id=589&order_id=67413510345111009&res_type=2&sig=0cef69f37b4a0e924ac4119c3d75117b
|
||||
`)
|
||||
msg := &CallbackMsg{
|
||||
FormData: data,
|
||||
}
|
||||
result := api.GetRefundSkuDetailFromMsg(msg)
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
95
platformapi/mtwmapi/comment.go
Normal file
95
platformapi/mtwmapi/comment.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
CommentReplyStatusAll = -1 //全部
|
||||
CommentReplyStatusNotReplied = 0 // 未回复
|
||||
CommentReplyStatusReplied = 1 // 已回复
|
||||
|
||||
MaxCommentQueryPageSize = 20
|
||||
)
|
||||
|
||||
type OrderComment struct {
|
||||
AddComment string `json:"add_comment"`
|
||||
AddCommentTime string `json:"add_comment_time"`
|
||||
CommentContent string `json:"comment_content"`
|
||||
CommentID int64 `json:"comment_id"`
|
||||
CommentLables string `json:"comment_lables"`
|
||||
CommentLableList []string `json:"comment_lable_list"`
|
||||
CommentPictures string `json:"comment_pictures"`
|
||||
CommentTime string `json:"comment_time"`
|
||||
CriticFoodList string `json:"critic_food_list"`
|
||||
DeliveryCommentScore int `json:"delivery_comment_score"`
|
||||
FoodCommentScore int `json:"food_comment_score"`
|
||||
OrderCommentScore int `json:"order_comment_score"`
|
||||
PackingScore int `json:"packing_score"`
|
||||
PraiseFoodList string `json:"praise_food_list"`
|
||||
ReplyStatus int `json:"reply_status"`
|
||||
Result string `json:"result"`
|
||||
ShipTime int `json:"ship_time"`
|
||||
}
|
||||
|
||||
// 根据门店id批量查询评价信息(新版)
|
||||
// http://developer.waimai.meituan.com/home/docDetail/191
|
||||
func (a *API) CommentQuery(poiCode string, startDateStr, endDateStr string, offset, limit int, replyStatus int) (commentList []*OrderComment, err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"start_time": startDateStr,
|
||||
"end_time": endDateStr,
|
||||
"pageoffset": offset,
|
||||
"pagesize": limit,
|
||||
}
|
||||
if limit <= 0 {
|
||||
limit = math.MaxInt32
|
||||
}
|
||||
originalOffset := offset
|
||||
originalLimit := limit
|
||||
for {
|
||||
if limit <= 0 {
|
||||
break
|
||||
}
|
||||
if limit > MaxCommentQueryPageSize {
|
||||
limit = MaxCommentQueryPageSize
|
||||
}
|
||||
params["pageoffset"] = offset
|
||||
params["pagesize"] = limit
|
||||
result, err := a.AccessAPI("comment/query", true, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var batchCommentList []*OrderComment
|
||||
err = utils.Map2StructByJson(result, &batchCommentList, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, comment := range batchCommentList {
|
||||
if comment.CommentLables != "" {
|
||||
comment.CommentLableList = strings.Split(comment.CommentLables, ",")
|
||||
}
|
||||
}
|
||||
commentList = append(commentList, batchCommentList...)
|
||||
if len(batchCommentList) < limit {
|
||||
break
|
||||
}
|
||||
offset += limit
|
||||
limit = originalLimit + originalOffset - offset
|
||||
}
|
||||
return commentList, nil
|
||||
}
|
||||
|
||||
// 根据评价id添加商家回复
|
||||
// http://developer.waimai.meituan.com/home/docDetail/194
|
||||
func (a *API) CommentAddReply(poiCode string, commentID int64, reply string) (err error) {
|
||||
_, err = a.AccessAPI("poi/comment/add_reply", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"comment_id": commentID,
|
||||
"reply": reply,
|
||||
})
|
||||
return err
|
||||
}
|
||||
15
platformapi/mtwmapi/comment_test.go
Normal file
15
platformapi/mtwmapi/comment_test.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestCommentQuery(t *testing.T) {
|
||||
result, err := api.CommentQuery("6783778", "20190501", "20190515", 0, 0, CommentReplyStatusAll)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
@@ -39,6 +39,12 @@ const (
|
||||
GeneralMaxLimit = 200 // 大多数的API的批处理最大条数
|
||||
)
|
||||
|
||||
const (
|
||||
ErrCodeSysErr = 700 // 系统错误,按美团外卖技术支持的说法,可当成需重试的错误
|
||||
ErrCodeAccessLimited = 711 // 接口调用过于频繁,触发流控,请降低调用频率
|
||||
ErrCodeNoAppFood = 805 // 不存在此菜品
|
||||
)
|
||||
|
||||
type API struct {
|
||||
appID string
|
||||
secret string
|
||||
@@ -47,6 +53,13 @@ type API struct {
|
||||
config *platformapi.APIConfig
|
||||
}
|
||||
|
||||
var (
|
||||
canRetryCodes = map[int]int{
|
||||
ErrCodeSysErr: 1,
|
||||
ErrCodeAccessLimited: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func New(appID, secret, callbackURL string, config ...*platformapi.APIConfig) *API {
|
||||
curConfig := platformapi.DefAPIConfig
|
||||
if len(config) > 0 {
|
||||
@@ -133,11 +146,14 @@ func (a *API) AccessAPI2(cmd string, isGet bool, bizParams map[string]interface{
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
if _, ok := jsonResult1["error"]; ok {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
if errObj, ok := jsonResult1["error"]; ok {
|
||||
baseapi.SugarLogger.Debugf("mtwm AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
|
||||
errorInfo := jsonResult1["error"].(map[string]interface{})
|
||||
errorInfo := errObj.(map[string]interface{})
|
||||
newErr := utils.NewErrorIntCode(errorInfo["msg"].(string), int(utils.MustInterface2Int64(errorInfo["code"])))
|
||||
if canRetryCodes[newErr.IntCode()] == 1 {
|
||||
return platformapi.ErrLevelExceedLimit, newErr
|
||||
}
|
||||
return platformapi.ErrLevelCodeIsNotOK, newErr
|
||||
}
|
||||
retVal = jsonResult1[resultKey]
|
||||
|
||||
@@ -22,6 +22,7 @@ const (
|
||||
|
||||
const (
|
||||
WaybillStatusWait4Delivery = "0" // 配送单发往配送
|
||||
WaybillStatusPending = "5" // 配送压单
|
||||
WaybillStatusAccepted = "10" // 配送单已确认
|
||||
WaybillStatusCourierArrived = "15" // 骑手已到店
|
||||
WaybillStatusPickedup = "20" // 骑手已取餐
|
||||
@@ -29,6 +30,7 @@ const (
|
||||
WaybillStatusCanceled = "100" // 配送单已取消
|
||||
)
|
||||
|
||||
// APP方URL 推送用户或客服取消订单(必接)
|
||||
const (
|
||||
CancelReasonAcceptTimeout = 1001 // 系统取消,超时未确认
|
||||
CancelReasonPayTimeout = 1002 // 系统取消,在线支付订单15分钟未支付
|
||||
@@ -42,6 +44,18 @@ const (
|
||||
CancelReasonOther = 1301 // 其他原因
|
||||
)
|
||||
|
||||
const (
|
||||
ResTypePending = 0 // 未处理
|
||||
ResTypeMerchantRefused = 1 // 商家驳回退款请求
|
||||
ResTypeMerchantAgreed = 2 // 商家同意退款
|
||||
ResTypeCSRefused = 3 // 客服驳回退款请求
|
||||
ResTypeCSAgreed = 4 // 客服帮商家同意退款
|
||||
ResTypeTimeoutAutoAgreed = 5 // 超过3小时自动同意
|
||||
ResTypeAutoAgreed = 6 // 系统自动确认
|
||||
ResTypeUserCancelApply = 7 // 用户取消退款申请
|
||||
ResTypeUserCancelComplain = 8 // 用户取消退款申诉
|
||||
)
|
||||
|
||||
const (
|
||||
NotifyTypeApply = "apply" // 发起全款退款
|
||||
NotifyTypePartyApply = "part" // 发起部分退款
|
||||
@@ -55,12 +69,234 @@ const (
|
||||
UserApplyCancelWaitMinute = 30 // 用户申请退款后,商家未在30分钟内(大连锁商家为3小时内)处理退款请求,系统将自动同意退款
|
||||
)
|
||||
|
||||
const (
|
||||
RefundTypeAll = 1
|
||||
RefundTypePart = 2
|
||||
)
|
||||
|
||||
const (
|
||||
ExtrasPromotionTypeTaoCanZeng = 4 // 套餐赠
|
||||
ExtrasPromotionTypeManZeng = 5 // 满赠
|
||||
|
||||
ExtrasPromotionTypeTeJiaCai = 7 // 特价菜
|
||||
ExtrasPromotionTypeZheKouCai = 17 // 折扣菜
|
||||
ExtrasPromotionTypeSecondHalfPrice = 20 // 第2份半价活动
|
||||
ExtrasPromotionTypeShanGouBaoPin = 56 // 闪购爆品
|
||||
)
|
||||
|
||||
type RefundSku struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
SkuID string `json:"sku_id,omitempty"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type RefundSkuDetail struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
BoxNum float32 `json:"box_num"`
|
||||
BoxPrice float64 `json:"box_price"`
|
||||
Count int `json:"count"`
|
||||
FoodName string `json:"food_name"`
|
||||
FoodPrice float64 `json:"food_price"`
|
||||
OriginFoodPrice float64 `json:"origin_food_price"`
|
||||
RefundPrice float64 `json:"refund_price"`
|
||||
SkuID string `json:"sku_id"`
|
||||
Spec string `json:"spec"`
|
||||
}
|
||||
|
||||
type RefundOrderDetail struct {
|
||||
ApplyReason string `json:"apply_reason"`
|
||||
ApplyType int `json:"apply_type"`
|
||||
CTime int64 `json:"ctime"`
|
||||
Money float64 `json:"money"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
Pictures string `json:"pictures"`
|
||||
PictureList []string `json:"pictureList"`
|
||||
RefundType int `json:"refund_type"`
|
||||
ResReason string `json:"res_reason"`
|
||||
ResType int `json:"res_type"`
|
||||
UTime int64 `json:"utime"`
|
||||
WmAppRetailForOrderPartRefundList []*RefundSkuDetail `json:"wmAppRetailForOrderPartRefundList"`
|
||||
WmOrderIDView int64 `json:"wm_order_id_view"`
|
||||
}
|
||||
|
||||
type OrderExtraInfo struct {
|
||||
ActDetailID int `json:"act_detail_id,omitempty"`
|
||||
MtCharge float64 `json:"mt_charge,omitempty"`
|
||||
PoiCharge float64 `json:"poi_charge,omitempty"`
|
||||
ReduceFee float64 `json:"reduce_fee,omitempty"`
|
||||
Remark string `json:"remark,omitempty"`
|
||||
Type int `json:"type,omitempty"`
|
||||
|
||||
RiderFee float64 `json:"rider_fee,omitempty"`
|
||||
}
|
||||
|
||||
type FoodInfo struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
BoxNum int `json:"box_num"`
|
||||
BoxPrice int `json:"box_price"`
|
||||
CartID int `json:"cart_id"`
|
||||
FoodDiscount int `json:"food_discount"`
|
||||
FoodName string `json:"food_name"`
|
||||
FoodProperty string `json:"food_property"`
|
||||
Price float64 `json:"price"`
|
||||
Quantity int `json:"quantity"`
|
||||
SkuID string `json:"sku_id"`
|
||||
Spec string `json:"spec"`
|
||||
Unit string `json:"unit"`
|
||||
}
|
||||
|
||||
type CanRefundFoodInfo struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
BoxNum float64 `json:"box_num"`
|
||||
BoxPrice float64 `json:"box_price"`
|
||||
Count int `json:"count"`
|
||||
FoodName string `json:"food_name"`
|
||||
FoodPrice float64 `json:"food_price"`
|
||||
IsRefundDifference int `json:"is_refund_difference"`
|
||||
OriginFoodPrice float64 `json:"origin_food_price"`
|
||||
RefundPrice float64 `json:"refund_price"`
|
||||
SkuID string `json:"sku_id"`
|
||||
}
|
||||
|
||||
type WmAppOrderActDetailInfo struct {
|
||||
ActID int64 `json:"act_id"`
|
||||
Count int `json:"count"`
|
||||
MtCharge float64 `json:"mtCharge"`
|
||||
PoiCharge float64 `json:"poiCharge"`
|
||||
Remark string `json:"remark"`
|
||||
Type int `json:"type"`
|
||||
}
|
||||
|
||||
type SkuBenefitDetailInfo struct {
|
||||
ActivityPrice float64 `json:"activityPrice"`
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
BoxNumber float64 `json:"boxNumber"`
|
||||
BoxPrice float64 `json:"boxPrice"`
|
||||
Count int `json:"count"`
|
||||
Name string `json:"name"`
|
||||
OriginPrice float64 `json:"originPrice"`
|
||||
SkuID string `json:"sku_id"`
|
||||
TotalActivityPrice float64 `json:"totalActivityPrice"`
|
||||
TotalBoxPrice float64 `json:"totalBoxPrice"`
|
||||
TotalMtCharge float64 `json:"totalMtCharge"`
|
||||
TotalOriginPrice float64 `json:"totalOriginPrice"`
|
||||
TotalPoiCharge float64 `json:"totalPoiCharge"`
|
||||
TotalReducePrice float64 `json:"totalReducePrice"`
|
||||
WmAppOrderActDetails []*WmAppOrderActDetailInfo `json:"wmAppOrderActDetails"`
|
||||
}
|
||||
|
||||
type ActOrderChargeInfo struct {
|
||||
Comment string `json:"comment"`
|
||||
FeeTypeDesc string `json:"feeTypeDesc"`
|
||||
FeeTypeID int `json:"feeTypeId"`
|
||||
MoneyCent int64 `json:"moneyCent"`
|
||||
}
|
||||
|
||||
type PoiReceiveDetailInfo struct {
|
||||
ActOrderChargeByMt []*ActOrderChargeInfo `json:"actOrderChargeByMt"`
|
||||
ActOrderChargeByPoi []*ActOrderChargeInfo `json:"actOrderChargeByPoi"`
|
||||
FoodShareFeeChargeByPoi int64 `json:"foodShareFeeChargeByPoi"`
|
||||
LogisticsFee int64 `json:"logisticsFee"`
|
||||
OnlinePayment int64 `json:"onlinePayment"`
|
||||
WmPoiReceiveCent int64 `json:"wmPoiReceiveCent"`
|
||||
}
|
||||
|
||||
type OrderInfo struct {
|
||||
AppOrderCode string `json:"app_order_code"`
|
||||
AppPoiCode string `json:"app_poi_code"`
|
||||
AvgSendTime int `json:"avg_send_time"`
|
||||
BackupRecipientPhone string `json:"backup_recipient_phone"`
|
||||
Caution string `json:"caution"`
|
||||
CityID int `json:"city_id"`
|
||||
Ctime int64 `json:"ctime"`
|
||||
DaySeq int `json:"day_seq"`
|
||||
DeliveryTime int `json:"delivery_time"`
|
||||
Detail string `json:"detail"`
|
||||
DetailList []*FoodInfo `json:"detailList"`
|
||||
DinnersNumber int `json:"dinners_number"`
|
||||
ExpectDeliverTime int `json:"expect_deliver_time"`
|
||||
Extras string `json:"extras"`
|
||||
ExtraList []*OrderExtraInfo `json:"extraList"`
|
||||
HasInvoiced int `json:"has_invoiced"`
|
||||
InvoiceTitle string `json:"invoice_title"`
|
||||
IsFavorites bool `json:"is_favorites"`
|
||||
IsPoiFirstOrder bool `json:"is_poi_first_order"`
|
||||
IsPre int `json:"is_pre"`
|
||||
IsThirdShipping int `json:"is_third_shipping"`
|
||||
Latitude float64 `json:"latitude"`
|
||||
LogisticsCode string `json:"logistics_code"`
|
||||
Longitude float64 `json:"longitude"`
|
||||
OrderCompletedTime int `json:"order_completed_time"`
|
||||
OrderConfirmTime int `json:"order_confirm_time"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderSendTime int `json:"order_send_time"`
|
||||
OriginalPrice float64 `json:"original_price"`
|
||||
PackageBagMoney int `json:"package_bag_money"`
|
||||
PayType int `json:"pay_type"`
|
||||
PickType int `json:"pick_type"`
|
||||
PoiReceiveDetail string `json:"poi_receive_detail"`
|
||||
PoiReceiveDetailPtr *PoiReceiveDetailInfo `json:"poi_receive_detail_ptr"`
|
||||
RecipientAddress string `json:"recipient_address"`
|
||||
RecipientName string `json:"recipient_name"`
|
||||
RecipientPhone string `json:"recipient_phone"`
|
||||
Remark string `json:"remark"`
|
||||
Result string `json:"result"`
|
||||
ShipperPhone string `json:"shipper_phone"`
|
||||
ShippingFee float64 `json:"shipping_fee"`
|
||||
ShippingType int `json:"shipping_type"`
|
||||
SkuBenefitDetail string `json:"sku_benefit_detail"`
|
||||
SkuBenefitDetailList []*SkuBenefitDetailInfo `json:"sku_benefit_detail_list"`
|
||||
SourceID int `json:"source_id"`
|
||||
Status int `json:"status"`
|
||||
TaxpayerID string `json:"taxpayer_id"`
|
||||
Total float64 `json:"total"`
|
||||
Utime int64 `json:"utime"`
|
||||
WmOrderIDView int64 `json:"wm_order_id_view"`
|
||||
WmPoiAddress string `json:"wm_poi_address"`
|
||||
WmPoiID int `json:"wm_poi_id"`
|
||||
WmPoiName string `json:"wm_poi_name"`
|
||||
WmPoiPhone string `json:"wm_poi_phone"`
|
||||
}
|
||||
|
||||
type GetOrderActDetailParamAct struct {
|
||||
Type int `json:"type,omitempty"`
|
||||
ActID int64 `json:"act_id,omitempty"`
|
||||
}
|
||||
|
||||
type GetOrderActDetailParam struct {
|
||||
OrderID int64 `json:"order_id_view"`
|
||||
ActParam []*GetOrderActDetailParamAct `json:"act_param,omitempty"`
|
||||
}
|
||||
|
||||
type OrderActInfo struct {
|
||||
OrderID int64 `json:"order_id_view"`
|
||||
ActDetailList []*struct {
|
||||
ActID int64 `json:"act_id"`
|
||||
CouponDetail interface{} `json:"coupon_detail"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
GiftsDetail interface{} `json:"gifts_detail"`
|
||||
PoiDetail interface{} `json:"poi_detail"`
|
||||
ProductDetail struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
CategorySeqence int `json:"category_seqence"`
|
||||
Charge string `json:"charge"`
|
||||
DayLimit int `json:"day_limit"`
|
||||
Name string `json:"name"`
|
||||
OrderLimit int `json:"order_limit"`
|
||||
Period string `json:"period"`
|
||||
Policy string `json:"policy"`
|
||||
SettingType int `json:"setting_type"`
|
||||
UserType int `json:"user_type"`
|
||||
WeeksTime string `json:"weeks_time"`
|
||||
} `json:"product_detail"`
|
||||
Remark string `json:"remark"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
Status int `json:"status"`
|
||||
Type int `json:"type"`
|
||||
TypeName string `json:"type_name"`
|
||||
} `json:"act_detail_list"`
|
||||
}
|
||||
|
||||
func (a *API) OrderReceived(orderID int64) (err error) {
|
||||
_, err = a.AccessAPI("order/poi_received", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
@@ -115,10 +351,10 @@ func (a *API) OrderRefundReject(orderID int64, reason string) (err error) {
|
||||
}
|
||||
|
||||
func (a *API) OrderApplyPartRefund(orderID int64, reason string, removeSkuList []*RefundSku) (err error) {
|
||||
_, err = a.AccessAPI("order/applyPartRefund", true, map[string]interface{}{
|
||||
_, err = a.AccessAPI("order/applyPartRefund", false, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
"reason": reason,
|
||||
"food_data": removeSkuList,
|
||||
"food_data": string(utils.MustMarshal(removeSkuList)),
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -128,7 +364,6 @@ func (a *API) OrderViewStatus(orderID int64) (status int, err error) {
|
||||
KeyOrderID: orderID,
|
||||
})
|
||||
if err == nil {
|
||||
// baseapi.SugarLogger.Debug(result)
|
||||
return int(utils.MustInterface2Int64(result.(map[string]interface{})["status"])), nil
|
||||
}
|
||||
return 0, err
|
||||
@@ -148,6 +383,50 @@ func (a *API) OrderGetOrderDetail(orderID int64, isMTLogistics bool) (orderInfo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) OrderGetOrderDetail2(orderID int64, isMTLogistics bool) (orderInfo *OrderInfo, err error) {
|
||||
orderMap, err := a.OrderGetOrderDetail(orderID, isMTLogistics)
|
||||
if err == nil {
|
||||
if err = utils.Map2StructByJson(orderMap, &orderInfo, false); err == nil {
|
||||
if orderInfo.Detail != "" {
|
||||
err = utils.UnmarshalUseNumber([]byte(orderInfo.Detail), &orderInfo.DetailList)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if orderInfo.Extras != "" {
|
||||
err = utils.UnmarshalUseNumber([]byte(orderInfo.Extras), &orderInfo.ExtraList)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if orderInfo.SkuBenefitDetail != "" {
|
||||
err = utils.UnmarshalUseNumber([]byte(orderInfo.SkuBenefitDetail), &orderInfo.SkuBenefitDetailList)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if orderInfo.PoiReceiveDetail != "" {
|
||||
err = utils.UnmarshalUseNumber([]byte(orderInfo.PoiReceiveDetail), &orderInfo.PoiReceiveDetailPtr)
|
||||
}
|
||||
}
|
||||
}
|
||||
return orderInfo, err
|
||||
}
|
||||
|
||||
func (a *API) OrderGetPartRefundFoods(orderID int64) (canRefundFoodList []*CanRefundFoodInfo, err error) {
|
||||
params := map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
}
|
||||
result, err := a.AccessAPI("order/getPartRefundFoods", true, params)
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &canRefundFoodList, false)
|
||||
}
|
||||
return canRefundFoodList, err
|
||||
}
|
||||
|
||||
func (a *API) OrderLogisticsPush(orderID int64, reason string) (err error) {
|
||||
_, err = a.AccessAPI("order/logistics/push", true, map[string]interface{}{
|
||||
KeyOrderID: orderID,
|
||||
@@ -195,3 +474,37 @@ func (a *API) OrderLogisticsChange2Self(orderID int64) (err error) {
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// refundOrderDetailList不能定义为[]*RefundOrderDetail,否则会有解析错误,原因不明
|
||||
func (a *API) GetOrderRefundDetail(orderID int64, refundType int) (refundOrderDetailList []*RefundOrderDetail, err error) {
|
||||
params := map[string]interface{}{
|
||||
"wm_order_id_view": orderID,
|
||||
}
|
||||
if refundType > 0 {
|
||||
params["refund_type"] = refundType
|
||||
}
|
||||
result, err := a.AccessAPI("ecommerce/order/getOrderRefundDetail", true, params)
|
||||
if err == nil {
|
||||
if err = utils.Map2StructByJson(result, &refundOrderDetailList, false); err == nil {
|
||||
for _, v := range refundOrderDetailList {
|
||||
if v.Pictures != "" {
|
||||
if err = utils.UnmarshalUseNumber([]byte(v.Pictures), &v.PictureList); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return refundOrderDetailList, err
|
||||
}
|
||||
|
||||
func (a *API) GetOrderActDetail(queryData []*GetOrderActDetailParam) (orderActList []*OrderActInfo, err error) {
|
||||
params := map[string]interface{}{
|
||||
"query_data": string(utils.MustMarshal(queryData)),
|
||||
}
|
||||
result, err := a.AccessAPI("ecommerce/order/getOrderActDetail", true, params)
|
||||
if err == nil {
|
||||
err = utils.Map2StructByJson(result, &orderActList, false)
|
||||
}
|
||||
return orderActList, err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package mtwmapi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
func TestOrderViewStatus(t *testing.T) {
|
||||
@@ -13,14 +15,56 @@ func TestOrderViewStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOrderGetOrderDetail(t *testing.T) {
|
||||
result, err := api.OrderGetOrderDetail(33762863658107006, false)
|
||||
result, err := api.OrderGetOrderDetail(69760842061320598, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result) == 0 {
|
||||
t.Fatal("result should have value")
|
||||
}
|
||||
// t.Log(utils.Format4Output(result, false))
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestOrderGetOrderDetail2(t *testing.T) {
|
||||
result, err := api.OrderGetOrderDetail2(69760842061320598, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestOrderGetPartRefundFoods(t *testing.T) {
|
||||
result, err := api.OrderGetPartRefundFoods(25236870562694625)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestOrderReceived(t *testing.T) {
|
||||
err := api.OrderReceived(25236872740350976)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderConfirm(t *testing.T) {
|
||||
err := api.OrderConfirm(25236872740350976)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderApplyPartRefund(t *testing.T) {
|
||||
err := api.OrderApplyPartRefund(25236872740350976, "缺货", []*RefundSku{
|
||||
&RefundSku{
|
||||
AppFoodCode: "30831",
|
||||
Count: 1,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderLogisticsStatus(t *testing.T) {
|
||||
@@ -45,9 +89,27 @@ func TestOrderBatchPullPhoneNumber(t *testing.T) {
|
||||
// t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestOrderConfirm(t *testing.T) {
|
||||
err := api.OrderConfirm(24617230733961993)
|
||||
func TestGetOrderRefundDetail(t *testing.T) {
|
||||
result, err := api.GetOrderRefundDetail(25236870166465610, RefundTypePart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestGetOrderActDetaill(t *testing.T) {
|
||||
result, err := api.GetOrderActDetail([]*GetOrderActDetailParam{
|
||||
&GetOrderActDetailParam{
|
||||
OrderID: 69760842061320598,
|
||||
// ActParam: []*GetOrderActDetailParamAct{
|
||||
// &GetOrderActDetailParamAct{
|
||||
// Type: 1,
|
||||
// },
|
||||
// },
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
@@ -15,6 +15,38 @@ type PoiCategoryInfo struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type PoiInfo struct {
|
||||
Address string `json:"address,omitempty"`
|
||||
AppID int `json:"app_id,omitempt"`
|
||||
AppPoiCode string `json:"app_poi_code,omitempt"`
|
||||
CityID int `json:"city_id,omitempt"`
|
||||
Ctime int64 `json:"ctime,omitempt"`
|
||||
InvoiceDescription string `json:"invoice_description,omitempt"`
|
||||
InvoiceMinPrice int `json:"invoice_min_price,omitempt"`
|
||||
InvoiceSupport int `json:"invoice_support,omitempt"`
|
||||
IsOnline int `json:"is_online,omitempt"`
|
||||
Latitude float64 `json:"latitude,omitempt"`
|
||||
LocationID int `json:"location_id,omitempt"`
|
||||
Longitude float64 `json:"longitude,omitempt"`
|
||||
Name string `json:"name,omitempt"`
|
||||
OpenLevel int `json:"open_level,omitempt"`
|
||||
Phone string `json:"phone,omitempt"`
|
||||
PicURL string `json:"pic_url,omitempt"`
|
||||
PicURLLarge string `json:"pic_url_large,omitempt"`
|
||||
PreBook int `json:"pre_book,omitempt"`
|
||||
PreBookMaxDays int `json:"pre_book_max_days,omitempt"`
|
||||
PreBookMinDays int `json:"pre_book_min_days,omitempt"`
|
||||
PromotionInfo string `json:"promotion_info,omitempt"`
|
||||
Remark string `json:"remark,omitempt"`
|
||||
ShippingFee float64 `json:"shipping_fee,omitempt"`
|
||||
ShippingTime string `json:"shipping_time,omitempt"`
|
||||
StandbyTel string `json:"standby_tel,omitempt"`
|
||||
TagName string `json:"tag_name,omitempt"`
|
||||
ThirdTagName string `json:"third_tag_name,omitempt"`
|
||||
TimeSelect int `json:"time_select,omitempt"`
|
||||
Utime int64 `json:"utime,omitempt"`
|
||||
}
|
||||
|
||||
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))
|
||||
return err
|
||||
@@ -33,17 +65,17 @@ func (a *API) PoiGetIDs() (ids []string, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (a *API) PoiMGet(poiCodes []string) (pois []map[string]interface{}, err error) {
|
||||
func (a *API) PoiMGet(poiCodes []string) (pois []*PoiInfo, err error) {
|
||||
result, err := a.AccessAPI("poi/mget", true, map[string]interface{}{
|
||||
KeyAppPoiCodes: strings.Join(poiCodes, ","),
|
||||
})
|
||||
if err == nil {
|
||||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||||
err = utils.Map2StructByJson(result, &pois, false)
|
||||
}
|
||||
return nil, err
|
||||
return pois, err
|
||||
}
|
||||
|
||||
func (a *API) PoiGet(poiCode string) (poi map[string]interface{}, err error) {
|
||||
func (a *API) PoiGet(poiCode string) (poi *PoiInfo, err error) {
|
||||
result, err := a.PoiMGet([]string{poiCode})
|
||||
if err == nil {
|
||||
if len(result) == 0 {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
testPoiCode = "100077"
|
||||
testPoiCode = "2523687"
|
||||
)
|
||||
|
||||
func TestPoiGetIDs(t *testing.T) {
|
||||
@@ -29,7 +29,7 @@ func TestPoiMGet(t *testing.T) {
|
||||
if len(result) != 1 {
|
||||
t.Fatal("result len is not ok")
|
||||
}
|
||||
if result[0][KeyAppPoiCode] != testPoiCode {
|
||||
if result[0].AppPoiCode != testPoiCode {
|
||||
t.Fatal("test_poi_01 is not equal")
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
@@ -40,7 +40,7 @@ func TestPoiSave(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
poiParams := utils.FilterMapNilMembers(result[0])
|
||||
poiParams := utils.FilterMapNilMembers(utils.Struct2FlatMap(result[0]))
|
||||
poiParams["name"] = "中国"
|
||||
err = api.PoiSave(testPoiCode, poiParams)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,10 @@ import (
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxSkuNameCharCount = 30 // SkuName的最大字符数
|
||||
)
|
||||
|
||||
type RetailCategoryInfo struct {
|
||||
Name string `json:"name"`
|
||||
Sequence int `json:"sequence"`
|
||||
@@ -20,6 +24,68 @@ type RetailTag struct {
|
||||
NamePath string `json:"namePath"`
|
||||
}
|
||||
|
||||
type BareStoreSkuInfo struct {
|
||||
SkuID string `json:"sku_id"`
|
||||
Price string `json:"price,omitempty"`
|
||||
Stock string `json:"stock,omitempty"`
|
||||
}
|
||||
|
||||
type BareStoreFoodInfo struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
Skus []*BareStoreSkuInfo `json:"skus"`
|
||||
}
|
||||
|
||||
type AvailableTimesInfo struct {
|
||||
Friday string `json:"friday"`
|
||||
Monday string `json:"monday"`
|
||||
Saturday string `json:"saturday"`
|
||||
Sunday string `json:"sunday"`
|
||||
Thursday string `json:"thursday"`
|
||||
Tuesday string `json:"tuesday"`
|
||||
Wednesday string `json:"wednesday"`
|
||||
}
|
||||
|
||||
type SkuInfo struct {
|
||||
AvailableTimes *AvailableTimesInfo `json:"available_times"`
|
||||
BoxNum string `json:"box_num"`
|
||||
BoxPrice string `json:"box_price"`
|
||||
LocationCode string `json:"location_code"`
|
||||
Price string `json:"price"`
|
||||
SkuID string `json:"sku_id"`
|
||||
Spec string `json:"spec"`
|
||||
Stock string `json:"stock"`
|
||||
Upc string `json:"upc"`
|
||||
Weight int `json:"weight"`
|
||||
}
|
||||
|
||||
type AppFood struct {
|
||||
AppFoodCode string `json:"app_food_code"`
|
||||
AppPoiCode string `json:"app_poi_code"`
|
||||
BoxNum float64 `json:"box_num"`
|
||||
BoxPrice float64 `json:"box_price"`
|
||||
CategoryCode string `json:"category_code"`
|
||||
CategoryName string `json:"category_name"`
|
||||
Ctime int `json:"ctime"`
|
||||
Description string `json:"description"`
|
||||
IsSp int `json:"isSp"`
|
||||
IsSoldOut int `json:"is_sold_out"`
|
||||
IsSpecialty int `json:"is_specialty"`
|
||||
MinOrderCount int `json:"min_order_count"`
|
||||
Name string `json:"name"`
|
||||
Picture string `json:"picture"`
|
||||
PictureContents string `json:"picture_contents"`
|
||||
Price float64 `json:"price"`
|
||||
SecondaryCategoryCode string `json:"secondary_category_code"`
|
||||
SecondaryCategoryName string `json:"secondary_category_name"`
|
||||
Sequence int `json:"sequence"`
|
||||
Skus string `json:"skus"`
|
||||
SkuList []*SkuInfo `json:"skuList"`
|
||||
TagID int `json:"tag_id"`
|
||||
Unit string `json:"unit"`
|
||||
Utime int `json:"utime"`
|
||||
ZhName string `json:"zh_name"`
|
||||
}
|
||||
|
||||
// 美团分类没有ID,就以名字为唯一标识,不论级别都必须不能重名
|
||||
// name(和originName)的长度不能超过10个字符(字符,不是字节)
|
||||
// 创建一级分类,originName为空,name为新分类名,secondaryName为空
|
||||
@@ -100,48 +166,59 @@ func (a *API) RetailBatchInitData(poiCode string, foodDataList []map[string]inte
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuPrice(poiCode string, foodData []map[string]interface{}) (err error) {
|
||||
func (a *API) RetailSkuPrice(poiCode string, foodData []*BareStoreFoodInfo) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/price", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuStock(poiCode string, foodData []map[string]interface{}) (err error) {
|
||||
func (a *API) RetailSkuStock(poiCode string, foodData []*BareStoreFoodInfo) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/stock", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailGet(poiCode, foodCode string) (food map[string]interface{}, err error) {
|
||||
func (a *API) RetailGet(poiCode, foodCode string) (food *AppFood, err error) {
|
||||
result, err := a.AccessAPI("retail/get", true, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
})
|
||||
if err == nil {
|
||||
return result.(map[string]interface{}), nil
|
||||
if err = utils.Map2StructByJson(result, &food, true); err == nil && food.Skus != "" {
|
||||
err = utils.UnmarshalUseNumber([]byte(food.Skus), &food.SkuList)
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
return food, err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuSave(poiCode, foodCode string, standardSkus, unstandardSkus []map[string]interface{}) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/save", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
KeyAppFoodCode: foodCode,
|
||||
"standard_skus": standardSkus,
|
||||
"unstandard_skus": unstandardSkus,
|
||||
"standard_skus": string(utils.MustMarshal(standardSkus)),
|
||||
"unstandard_skus": string(utils.MustMarshal(unstandardSkus)),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuSellStatus(poiCode string, foodData []map[string]interface{}, status int) (err error) {
|
||||
func (a *API) RetailSkuSellStatus(poiCode string, foodData []map[string]interface{}, sellStatus int) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/sellStatus", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": foodData,
|
||||
"status": status,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
"sell_status": sellStatus,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *API) RetailSkuSellStatus2(poiCode string, foodData []*BareStoreFoodInfo, sellStatus int) (err error) {
|
||||
_, err = a.AccessAPI("retail/sku/sellStatus", false, map[string]interface{}{
|
||||
KeyAppPoiCode: poiCode,
|
||||
"food_data": string(utils.MustMarshal(foodData)),
|
||||
"sell_status": sellStatus,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -47,7 +47,15 @@ func TestRetailList(t *testing.T) {
|
||||
if len(result) == 0 {
|
||||
t.Fatal("should have items")
|
||||
}
|
||||
// t.Log(utils.Format4Output(result, false))
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRetailGet(t *testing.T) {
|
||||
result, err := api.RetailGet(testPoiCode, "5246")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(utils.Format4Output(result, false))
|
||||
}
|
||||
|
||||
func TestRetailGetSpTagIds(t *testing.T) {
|
||||
@@ -69,7 +77,7 @@ func TestRetailCatSkuBatchDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRetailDelete(t *testing.T) {
|
||||
err := api.RetailDelete(testPoiCode, "")
|
||||
err := api.RetailDelete(testPoiCode, "614")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -17,10 +17,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
DefClientTimeout = 10 * time.Second
|
||||
DefClientTimeout = 5 * time.Second
|
||||
DefSleepSecondWhenExceedLimit = 3 * time.Second
|
||||
DefRandSlice = 10
|
||||
DefMaxRecoverableRetryCount = 3
|
||||
DefMaxRecoverableRetryCount = 1
|
||||
DefMaxExceedLimitRetryCount = 25
|
||||
)
|
||||
|
||||
@@ -89,7 +88,7 @@ func getClonedData(requestURL *url.URL, r *bytes.Buffer) string {
|
||||
return retVal
|
||||
}
|
||||
|
||||
func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.Request, config *APIConfig, handleResponse func(bodyMap map[string]interface{}) (string, error)) error {
|
||||
func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.Request, config *APIConfig, handleResponse func(response *http.Response, bodyMap map[string]interface{}) (string, error)) error {
|
||||
exceedLimitRetryCount := 0
|
||||
recoverableErrorRetryCount := 0
|
||||
for {
|
||||
@@ -106,8 +105,8 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
|
||||
if err != nil {
|
||||
baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry:%s client.Get return err:%v", trackID, err)
|
||||
err, ok := err.(net.Error)
|
||||
recoverableErrorRetryCount++
|
||||
if ok /*&& err.Timeout()*/ && recoverableErrorRetryCount <= config.MaxRecoverableRetryCount { // 只要是网络错误都重试
|
||||
recoverableErrorRetryCount++
|
||||
continue
|
||||
} else {
|
||||
baseapi.SugarLogger.Errorf("AccessPlatformAPIWithRetry:%s access api url:%v, request:%v, error:%v", trackID, request.URL, getClonedData(request.URL, savedBuf), err)
|
||||
@@ -155,7 +154,7 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
|
||||
if err != nil {
|
||||
errLevel = ErrLevelRecoverableErr // 读取数据错误,或数据格式错误认为是偶发情况,重试
|
||||
} else {
|
||||
errLevel, err = handleResponse(bodyMap)
|
||||
errLevel, err = handleResponse(response, bodyMap)
|
||||
}
|
||||
if err == nil {
|
||||
return nil
|
||||
|
||||
@@ -32,14 +32,29 @@ type PendingSaveB2CSkuVo struct {
|
||||
|
||||
type PendingSaveSkuVo struct {
|
||||
OuterSkuCode string `json:"outerSkuCode"`
|
||||
ImageURL string `json:"imageUrl"`
|
||||
SalePrice float32 `json:"salePrice"`
|
||||
OriginalPrice float32 `json:"originalPrice"`
|
||||
CostPrice float32 `json:"costPrice"`
|
||||
ImageURL string `json:"imageUrl,omitempty"`
|
||||
SalePrice float64 `json:"salePrice"`
|
||||
OriginalPrice float64 `json:"originalPrice,omitempty"`
|
||||
CostPrice float64 `json:"costPrice"`
|
||||
EditStockNum int `json:"editStockNum"`
|
||||
B2cSku *PendingSaveB2CSkuVo `json:"b2cSku"`
|
||||
}
|
||||
|
||||
type PendingSaveGoodsVo struct {
|
||||
Title string `json:"title"`
|
||||
OuterGoodsCode string `json:"outerGoodsCode,omitempty"`
|
||||
IsMultiSku int `json:"isMultiSku"`
|
||||
GoodsImageURL []string `json:"goodsImageUrl"`
|
||||
GoodsDesc string `json:"goodsDesc"`
|
||||
InitialSales int `json:"initialSales,omitempty"`
|
||||
DeductStockType int `json:"deductStockType"`
|
||||
IsPutAway int `json:"isPutAway"`
|
||||
Sort int `json:"Sort,omitempty"`
|
||||
CategoryID int64 `json:"categoryId"`
|
||||
B2cGoods []*PendingSaveB2CGoodsVo `json:"b2cGoods"`
|
||||
SkuList []*PendingSaveSkuVo `json:"skuList"`
|
||||
}
|
||||
|
||||
type Category struct {
|
||||
CategoryID int64 `json:"categoryId"`
|
||||
Title string `json:"title"`
|
||||
@@ -198,6 +213,16 @@ func (a *API) UpdateClassify(classifyID int64, title string, imageURL string) (e
|
||||
return err
|
||||
}
|
||||
|
||||
func getDataFromCUGoodsResult(result interface{}) (goodsId int64, skuMap map[string]int64, err error) {
|
||||
skuMap = make(map[string]int64)
|
||||
skuList := result.(map[string]interface{})["skuList"].([]interface{})
|
||||
for _, v := range skuList {
|
||||
sku := v.(map[string]interface{})
|
||||
skuMap[utils.Interface2String(sku[KeyOuterSkuCode])] = utils.MustInterface2Int64(sku[KeySkuID])
|
||||
}
|
||||
return utils.MustInterface2Int64(result.(map[string]interface{})["goodsId"]), skuMap, nil
|
||||
}
|
||||
|
||||
func (a *API) AddGoods(outerGoodsCode, title string, isMultiSku bool, goodsImageUrl []string, goodsDesc string, isPutAway bool, sort int, categoryId int64, classifyIdList []int64, b2cGoods *PendingSaveB2CGoodsVo, skuList []map[string]interface{}, addParams map[string]interface{}) (goodsId int64, skuMap map[string]int64, err error) {
|
||||
goodsInfo := map[string]interface{}{
|
||||
"outerGoodsCode": outerGoodsCode,
|
||||
@@ -221,13 +246,20 @@ func (a *API) AddGoods(outerGoodsCode, title string, isMultiSku bool, goodsImage
|
||||
"goods": mergedMap,
|
||||
})
|
||||
if err == nil {
|
||||
skuMap := make(map[string]int64)
|
||||
skuList := result.(map[string]interface{})["skuList"].([]interface{})
|
||||
for _, v := range skuList {
|
||||
sku := v.(map[string]interface{})
|
||||
skuMap[utils.Interface2String(sku[KeyOuterSkuCode])] = utils.MustInterface2Int64(sku[KeySkuID])
|
||||
}
|
||||
return utils.MustInterface2Int64(result.(map[string]interface{})["goodsId"]), skuMap, nil
|
||||
return getDataFromCUGoodsResult(result)
|
||||
}
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
func (a *API) AddGoods2(goodsInfo *PendingSaveGoodsVo) (goodsId int64, skuMap map[string]int64, err error) {
|
||||
if goodsInfo.DeductStockType == 0 {
|
||||
goodsInfo.DeductStockType = DeductStockTypePay
|
||||
}
|
||||
result, err := a.AccessAPI("goods/addGoods", map[string]interface{}{
|
||||
"goods": goodsInfo,
|
||||
})
|
||||
if err == nil {
|
||||
return getDataFromCUGoodsResult(result)
|
||||
}
|
||||
return 0, nil, err
|
||||
}
|
||||
@@ -254,13 +286,20 @@ func (a *API) UpdateGoods(goodsID int64, title string, isMultiSku bool, goodsIma
|
||||
"goods": mergedMap,
|
||||
})
|
||||
if err == nil {
|
||||
skuMap := make(map[string]int64)
|
||||
skuList := result.(map[string]interface{})["skuList"].([]interface{})
|
||||
for _, v := range skuList {
|
||||
sku := v.(map[string]interface{})
|
||||
skuMap[utils.Interface2String(sku[KeyOuterSkuCode])] = utils.MustInterface2Int64(sku[KeySkuID])
|
||||
}
|
||||
return utils.MustInterface2Int64(result.(map[string]interface{})["goodsId"]), skuMap, nil
|
||||
return getDataFromCUGoodsResult(result)
|
||||
}
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
func (a *API) UpdateGoods2(goodsInfo *PendingSaveGoodsVo) (goodsId int64, skuMap map[string]int64, err error) {
|
||||
if goodsInfo.DeductStockType == 0 {
|
||||
goodsInfo.DeductStockType = DeductStockTypePay
|
||||
}
|
||||
result, err := a.AccessAPI("goods/updateGoods", map[string]interface{}{
|
||||
"goods": goodsInfo,
|
||||
})
|
||||
if err == nil {
|
||||
return getDataFromCUGoodsResult(result)
|
||||
}
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ func (a *API) AccessAPI(apiStr string, apiParams map[string]interface{}) (retVal
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
// baseapi.SugarLogger.Debug(utils.Format4Output(jsonResult1, false))
|
||||
code := ResponseCodeSuccess
|
||||
errMsg := ""
|
||||
|
||||
@@ -100,7 +100,7 @@ func (a *API) AccessAPI(action string, params map[string]interface{}, body strin
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (result string, err error) {
|
||||
var errInfo *ErrorInfo
|
||||
// 微信的返回值,在错误与正常情况下,结构是完全不一样的
|
||||
if errCode, ok := jsonResult1["errcode"]; ok {
|
||||
|
||||
@@ -80,7 +80,7 @@ func (a *API) AccessAPI(apiName string, apiParams map[string]interface{}) (retVa
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := int(utils.Interface2Int64WithDefault(jsonResult1["errno"], ResponseCodeSuccess))
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal = jsonResult1
|
||||
|
||||
@@ -91,7 +91,7 @@ func (a *API) AccessAPI(apiName string, apiParams map[string]interface{}) (retVa
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := utils.Interface2String(jsonResult1["error"])
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal, _ = jsonResult1["body"].(map[string]interface{})
|
||||
|
||||
@@ -88,7 +88,7 @@ func (a *API) AccessAPI(apiName string, apiParams map[string]interface{}, isGet
|
||||
return request
|
||||
},
|
||||
a.config,
|
||||
func(jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
func(response *http.Response, jsonResult1 map[string]interface{}) (errLevel string, err error) {
|
||||
code := int(utils.MustInterface2Int64(jsonResult1["errNum"]))
|
||||
if code == ResponseCodeSuccess {
|
||||
retVal, _ = jsonResult1["retData"].(map[string]interface{})
|
||||
|
||||
47
utils/java_date.go
Normal file
47
utils/java_date.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type JavaDate struct {
|
||||
Day time.Weekday `json:"day"` // day of the week
|
||||
|
||||
Hours int `json:"hours"`
|
||||
Minutes int `json:"minutes"`
|
||||
Seconds int `json:"seconds"`
|
||||
Time int64 `json:"time"`
|
||||
TimezoneOffset int `json:"timezoneOffset"`
|
||||
|
||||
Date int `json:"date"`
|
||||
Month time.Month `json:"month"`
|
||||
Year int `json:"year"`
|
||||
}
|
||||
|
||||
func NewJavaDate() *JavaDate {
|
||||
return NewJavaDateFromTime(time.Now())
|
||||
}
|
||||
|
||||
func NewJavaDateFromTime(tm time.Time) (jd *JavaDate) {
|
||||
jd = &JavaDate{
|
||||
Time: tm.UnixNano() / 1000000,
|
||||
Day: tm.Weekday(),
|
||||
Hours: tm.Hour(),
|
||||
Minutes: tm.Minute(),
|
||||
Seconds: tm.Second(),
|
||||
}
|
||||
jd.Year, jd.Month, jd.Date = tm.Date()
|
||||
jd.Year -= 1900
|
||||
jd.Month--
|
||||
_, jd.TimezoneOffset = tm.Zone()
|
||||
jd.TimezoneOffset /= 60
|
||||
jd.TimezoneOffset = -jd.TimezoneOffset
|
||||
return jd
|
||||
}
|
||||
|
||||
func (j *JavaDate) GoTime() time.Time {
|
||||
if j == nil {
|
||||
return DefaultTimeValue
|
||||
}
|
||||
return Timestamp2Time(j.Time / 1000)
|
||||
}
|
||||
38
utils/java_date_test.go
Normal file
38
utils/java_date_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestJavaDate(t *testing.T) {
|
||||
var (
|
||||
date interface{}
|
||||
jd *JavaDate
|
||||
)
|
||||
err := UnmarshalUseNumber([]byte(`
|
||||
{
|
||||
"date":6,
|
||||
"day":1,
|
||||
"hours":9,
|
||||
"minutes":45,
|
||||
"month":4,
|
||||
"seconds":46,
|
||||
"time":1557107146000,
|
||||
"timezoneOffset":-480,
|
||||
"year":119
|
||||
}
|
||||
`), &date)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = Map2StructByJson(date, &jd, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(jd.GoTime())
|
||||
t.Log(Format4Output(jd, false))
|
||||
|
||||
jd = NewJavaDateFromTime(jd.GoTime())
|
||||
t.Log(jd.GoTime())
|
||||
t.Log(Format4Output(jd, false))
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -65,23 +67,27 @@ func taskFun(taskChan chan *TaskParam, index int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pool) callFun(func4Call func(), primaryID string, isAsync bool) chan interface{} {
|
||||
func (p *Pool) callFun(func4Call func(), primaryID string, isAsync bool) (r interface{}) {
|
||||
result := md5.Sum([]byte(primaryID))
|
||||
resultInt64 := int64(binary.LittleEndian.Uint32(result[8:]))
|
||||
chanIndex := int(resultInt64 % int64(p.curRoutineCount))
|
||||
chanParam := &TaskParam{
|
||||
handler: func4Call,
|
||||
}
|
||||
if isAsync {
|
||||
if !isAsync {
|
||||
chanParam.resultChan = make(chan interface{})
|
||||
}
|
||||
p.taskChans[chanIndex] <- chanParam
|
||||
return chanParam.resultChan
|
||||
if !isAsync {
|
||||
r = <-chanParam.resultChan
|
||||
close(chanParam.resultChan)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (p *Pool) CallFun(func4Call func(), primaryID string) {
|
||||
if p.curRoutineCount > 0 {
|
||||
r := <-p.callFun(func4Call, primaryID, true)
|
||||
r := p.callFun(func4Call, primaryID, false)
|
||||
if r != nil {
|
||||
panic(r)
|
||||
}
|
||||
@@ -94,5 +100,7 @@ func (p *Pool) CallFunAsync(func4Call func(), primaryID string) {
|
||||
if p.curRoutineCount == 0 {
|
||||
panic("CallFunAsync can not run when p.curRoutineCount == 0")
|
||||
}
|
||||
p.callFun(func4Call, primaryID, false)
|
||||
utils.CallFuncAsync(func() {
|
||||
p.callFun(func4Call, primaryID, true)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -22,17 +21,6 @@ var (
|
||||
ZeroTimeValue = time.Time{}
|
||||
)
|
||||
|
||||
func GetConcretValue(value reflect.Value) reflect.Value {
|
||||
for {
|
||||
if value.Kind() == reflect.Interface || value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func UnmarshalUseNumber(data []byte, result interface{}) error {
|
||||
err := TryUnmarshalUseNumber(data, result)
|
||||
if err != nil {
|
||||
@@ -184,21 +172,6 @@ func Interface2StringList(data interface{}) []string {
|
||||
return retVal
|
||||
}
|
||||
|
||||
func Interface2Slice(value interface{}) (retVal []interface{}) {
|
||||
typeInfo := reflect.TypeOf(value)
|
||||
if typeInfo.Kind() != reflect.Slice {
|
||||
panic("list must be slice type!")
|
||||
}
|
||||
if value != nil {
|
||||
valueInfo := reflect.ValueOf(value)
|
||||
retVal = make([]interface{}, valueInfo.Len())
|
||||
for i := 0; i < valueInfo.Len(); i++ {
|
||||
retVal[i] = valueInfo.Index(i).Interface()
|
||||
}
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
|
||||
func Slice2MapSlice(data []interface{}) []map[string]interface{} {
|
||||
retVal := make([]map[string]interface{}, len(data))
|
||||
for k, v := range data {
|
||||
@@ -486,6 +459,7 @@ func Struct2FlatMap(obj interface{}) map[string]interface{} {
|
||||
return FlatMap(m)
|
||||
}
|
||||
|
||||
// !!! 此函数好像不支持struct是内嵌结构的
|
||||
func Map2StructByJson(inObj interface{}, outObjAddr interface{}, weaklyTypedInput bool) (err error) {
|
||||
decoder, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||
TagName: "json",
|
||||
|
||||
@@ -14,6 +14,10 @@ import (
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
APIPin = "jxadmin"
|
||||
)
|
||||
|
||||
func DictKeysMan(data interface{}, keysToRemove []string, keysToKeep []string) interface{} {
|
||||
if data == nil || (keysToKeep == nil && keysToRemove == nil) {
|
||||
return data
|
||||
@@ -101,10 +105,11 @@ func GetCurTimestamp() int64 {
|
||||
}
|
||||
|
||||
func GetAPIOperator(userName string) string {
|
||||
retVal := "jxc4-admin"
|
||||
retVal := APIPin
|
||||
if userName != "" {
|
||||
retVal += "-" + userName
|
||||
}
|
||||
retVal = LimitUTF8StringLen(retVal, 50)
|
||||
return retVal
|
||||
}
|
||||
|
||||
@@ -182,14 +187,18 @@ func GenerateGetURL(baseURL, apiStr string, params map[string]interface{}) strin
|
||||
return baseURL + queryString
|
||||
}
|
||||
|
||||
func SendFakeRequest(method, url, body, contentType string) (*http.Response, error) {
|
||||
request, _ := http.NewRequest(method, url, strings.NewReader(body))
|
||||
func BuildRequest(method, url, body, contentType string) (request *http.Request) {
|
||||
request, _ = http.NewRequest(method, url, strings.NewReader(body))
|
||||
if contentType == "" {
|
||||
contentType = "application/x-www-form-urlencoded"
|
||||
}
|
||||
request.Header.Set("Content-Type", contentType)
|
||||
return request
|
||||
}
|
||||
|
||||
func SendFakeRequest(method, url, body, contentType string) (*http.Response, error) {
|
||||
client := &http.Client{}
|
||||
return client.Do(request)
|
||||
return client.Do(BuildRequest(method, url, body, contentType))
|
||||
}
|
||||
|
||||
// 过滤 utf8mb4(比如emoji表情)
|
||||
@@ -238,7 +247,7 @@ func Base64DecodeMultiString(strs ...string) (decodedData [][]byte, err error) {
|
||||
return decodedData, nil
|
||||
}
|
||||
|
||||
// 只适合与纯英文的情况
|
||||
// 限制的是字节数,只适合纯英文的情况,推荐使用LimitMixedStringLen,除非确定是纯英文,且对性能相当敏感
|
||||
func LimitStringLen(str string, maxByteCount int) (limitedStr string) {
|
||||
if maxByteCount > 0 {
|
||||
if strLen := len(str); strLen > maxByteCount {
|
||||
|
||||
85
utils/utils_reflect.go
Normal file
85
utils/utils_reflect.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 得到一个结构体(或指向结构体的指针)中其成员(tag指定,缺省是字段名)的路径(嵌入结构体或指向结构指针会被展开)
|
||||
func GetStructObjNameIndex(obj interface{}, tag string) map[string][]int {
|
||||
objType := reflect.TypeOf(obj)
|
||||
return GetStructNameIndex(objType, tag)
|
||||
}
|
||||
|
||||
func GetStructNameIndex(objType reflect.Type, tag string) (nameIndex map[string][]int) {
|
||||
if objType.Kind() == reflect.Ptr {
|
||||
objType = objType.Elem()
|
||||
}
|
||||
if objType.Kind() != reflect.Struct {
|
||||
panic("obj must be struct obj or pointer to struct of obj!")
|
||||
}
|
||||
nameIndex = make(map[string][]int)
|
||||
for i := 0; i < objType.NumField(); i++ {
|
||||
structField := objType.Field(i)
|
||||
fieldType := structField.Type
|
||||
|
||||
if IndirectType(fieldType).Kind() == reflect.Struct && IsFieldEmbedded(&structField) { // 嵌入
|
||||
subNameIndex := GetStructNameIndex(fieldType, tag)
|
||||
for k, v := range subNameIndex {
|
||||
nameIndex[k] = append([]int{i}, v...)
|
||||
}
|
||||
} else {
|
||||
tagName := structField.Name
|
||||
if tag != "" {
|
||||
tagName2 := strings.Split(structField.Tag.Get(tag), ",")[0]
|
||||
if tagName2 == "-" {
|
||||
tagName = "" // 忽略
|
||||
} else if tagName2 != "" {
|
||||
tagName = tagName2
|
||||
}
|
||||
}
|
||||
if tagName != "" {
|
||||
nameIndex[tagName] = []int{i}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nameIndex
|
||||
}
|
||||
|
||||
// 判断成员是否是嵌入的,依据是成员名与类型名相同
|
||||
func IsFieldEmbedded(structField *reflect.StructField) bool {
|
||||
return structField.Name == IndirectType(structField.Type).Name()
|
||||
}
|
||||
|
||||
func IndirectType(objType reflect.Type) reflect.Type {
|
||||
if objType.Kind() == reflect.Ptr {
|
||||
objType = objType.Elem()
|
||||
}
|
||||
return objType
|
||||
}
|
||||
|
||||
func GetConcretValue(value reflect.Value) reflect.Value {
|
||||
for {
|
||||
if value.Kind() == reflect.Interface || value.Kind() == reflect.Ptr {
|
||||
value = value.Elem()
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func Interface2Slice(value interface{}) (retVal []interface{}) {
|
||||
typeInfo := reflect.TypeOf(value)
|
||||
if typeInfo.Kind() != reflect.Slice {
|
||||
panic("list must be slice type!")
|
||||
}
|
||||
if value != nil {
|
||||
valueInfo := reflect.ValueOf(value)
|
||||
retVal = make([]interface{}, valueInfo.Len())
|
||||
for i := 0; i < valueInfo.Len(); i++ {
|
||||
retVal[i] = valueInfo.Index(i).Interface()
|
||||
}
|
||||
}
|
||||
return retVal
|
||||
}
|
||||
24
utils/utils_reflect_test.go
Normal file
24
utils/utils_reflect_test.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReflect(t *testing.T) {
|
||||
type SubXXXX struct {
|
||||
IntData int
|
||||
StrData string
|
||||
}
|
||||
type XXXX struct {
|
||||
SubXXXX
|
||||
A int
|
||||
B string `json:"b"`
|
||||
}
|
||||
|
||||
x := XXXX{}
|
||||
typeX := reflect.TypeOf(x)
|
||||
field := typeX.Field(0)
|
||||
t.Log(IsFieldEmbedded(&field))
|
||||
t.Log(Format4Output(GetStructObjNameIndex(&x, ""), false))
|
||||
}
|
||||
Reference in New Issue
Block a user