Merge branch 'master' into get-store

This commit is contained in:
gazebo
2019-06-24 10:12:27 +08:00
67 changed files with 3112 additions and 729 deletions

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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

View File

@@ -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) {

View File

@@ -0,0 +1,5 @@
package ebaiapi
const (
ErrOrderIsNotPartRefund = 301006 // 该订单非部分退款订单
)

View File

@@ -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))
}

View File

@@ -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)
}
}

View File

@@ -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 {

View File

@@ -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{})

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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))
}