402 lines
13 KiB
Go
402 lines
13 KiB
Go
package ebaiapi
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
)
|
||
|
||
const (
|
||
SkuStatusOnline = 1 // 为上架
|
||
SkuStatusOffline = 0 // 为下架
|
||
SkuStatusDeleted = 2 // 为删除
|
||
)
|
||
|
||
const (
|
||
UPCTypeStandard = 1
|
||
UPCTypePrivate = 0
|
||
)
|
||
const (
|
||
MaxLeftNum = 99999
|
||
MaxSkuNameByteCount = 100 // skuname的最大字节数,注意不是字符数,超长饿百会报错:{"data":"","errno":20200,"error":"invalid param:[name]...
|
||
|
||
MaxStoreSkuBatchSize = 100 // sku.offline, sku.online, sku.price.update.batch和sku.stock.update.batch这些批量操作的最大值
|
||
)
|
||
|
||
type CategoryInfo struct {
|
||
CategoryID int64 `json:"category_id"`
|
||
Name string `json:"name"`
|
||
Rank int `json:"rank"` // 店内分类独有
|
||
Children []*CategoryInfo `json:"children"`
|
||
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 `json:"Total"`
|
||
Page int `json:"Page"`
|
||
Pages int `json:"Pages"`
|
||
List []*SkuInfo `json:"List"`
|
||
}
|
||
|
||
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) {
|
||
result, err := a.AccessAPI("sku.shop.category.create", map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
"parent_category_id": parentID,
|
||
"name": name,
|
||
"rank": rank,
|
||
})
|
||
if err == nil {
|
||
return utils.Str2Int64(utils.Interface2String(result.Data.(map[string]interface{})["category_id"])), nil
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
func (a *API) ShopCategoryGet(shopID string) (cats []*CategoryInfo, err error) {
|
||
result, err := a.AccessAPI("sku.shop.category.get", utils.Params2Map(KeyShopID, shopID))
|
||
if err == nil {
|
||
if inMap, ok := result.Data.(map[string]interface{}); ok { // fuck it
|
||
cats := interface2CatList(inMap["categorys"], 1)
|
||
return cats, nil
|
||
}
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
func (a *API) ShopCategoryUpdate(shopID string, categoryID int64, name string, rank int) (err error) {
|
||
_, err = a.AccessAPI("sku.shop.category.update", map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
"category_id": categoryID,
|
||
"name": name,
|
||
"rank": rank,
|
||
})
|
||
if errWithCode, ok := err.(*utils.ErrorWithCode); ok {
|
||
if errWithCode.Level() == 0 && errWithCode.IntCode() == 1 { //忽略同名错误
|
||
err = nil
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func (a *API) ShopCategoryDelete(shopID string, categoryID int64) (err error) {
|
||
_, err = a.AccessAPI("sku.shop.category.delete", map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
"category_id": categoryID,
|
||
})
|
||
return err
|
||
}
|
||
|
||
func (a *API) SkuGetItemsByCategoryId(shopID string, categoryID int64) (skus []map[string]interface{}, err error) {
|
||
result, err := a.AccessAPI("sku.getItemsByCategoryId", map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
"category_id": categoryID,
|
||
})
|
||
if err == nil {
|
||
return utils.Slice2MapSlice(result.Data.([]interface{})), nil
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
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 {
|
||
err = utils.Map2StructByJson(result.Data, &skuInfo, true)
|
||
}
|
||
return skuInfo, err
|
||
}
|
||
|
||
// 饿百商品名可以相同,不会报错
|
||
func (a *API) SkuCreate(shopID string, customSkuID int, params map[string]interface{}) (skuID int64, err error) {
|
||
defParams := map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
KeyCustomSkuID: customSkuID,
|
||
}
|
||
if params["upc"] == nil {
|
||
defParams["upc_type"] = UPCTypePrivate
|
||
defParams["upc"] = "upc-" + utils.Int2Str(customSkuID)
|
||
}
|
||
if params["brand_id"] == nil {
|
||
defParams["brand_id"] = 0
|
||
}
|
||
if params["brand_name"] == nil {
|
||
defParams["brand_name"] = "无" // 很狗血的是,你还必须填个无才行。。。
|
||
}
|
||
params = utils.MergeMaps(params, defParams)
|
||
// baseapi.SugarLogger.Debugf(utils.Format4Output(params, false))
|
||
result, err := a.AccessAPI("sku.create", params)
|
||
if err == nil {
|
||
return utils.Str2Int64(utils.Interface2String(result.Data.(map[string]interface{})[KeySkuID])), nil
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
func (a *API) SkuUpdate(shopID string, ebaiSkuID int64, params map[string]interface{}) (skuID int64, err error) {
|
||
defParams := map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
KeySkuID: ebaiSkuID,
|
||
}
|
||
result, err := a.AccessAPI("sku.update", utils.MergeMaps(params, defParams))
|
||
if err == nil {
|
||
return utils.Str2Int64(utils.Interface2String(result.Data.(map[string]interface{})[KeySkuID])), nil
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
func (a *API) SkuDelete(shopID, skuIDsStr string) (err error) {
|
||
params := map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
KeySkuID: skuIDsStr,
|
||
}
|
||
_, err = a.AccessAPI("sku.delete", params)
|
||
return err
|
||
}
|
||
|
||
func (a *API) SkuDeleteByCustomIDs(shopID, customSkuIDsStr string) (err error) {
|
||
params := map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
KeyCustomSkuID: customSkuIDsStr,
|
||
}
|
||
_, err = a.AccessAPI("sku.delete", params)
|
||
return err
|
||
}
|
||
|
||
func (a *API) SkuOnline(shopID, skuIDsStr string) (err error) {
|
||
params := map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
KeySkuID: skuIDsStr,
|
||
}
|
||
_, err = a.AccessAPI("sku.online", params)
|
||
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
|
||
}
|
||
|
||
func (a *API) SkuOffline(shopID, skuIDsStr string) (err error) {
|
||
params := map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
KeySkuID: skuIDsStr,
|
||
}
|
||
_, err = a.AccessAPI("sku.offline", params)
|
||
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
|
||
}
|
||
|
||
func (a *API) SkuStockUpdateBatch(shopID, skuStockStr, customSkuStockStr, upcStockStr string) (err error) {
|
||
params := genSkuPriceParams(skuStockStr, customSkuStockStr, upcStockStr)
|
||
params[KeyShopID] = shopID
|
||
_, err = a.AccessAPI("sku.stock.update.batch", params)
|
||
return err
|
||
}
|
||
|
||
func (a *API) SkuStockUpdateOne(shopID, skuStockStr, customSkuStockStr, upcStockStr string) (err error) {
|
||
params := genSkuPriceParams(skuStockStr, customSkuStockStr, upcStockStr)
|
||
params[KeyShopID] = shopID
|
||
_, err = a.AccessAPI("sku.stock.update.one", params)
|
||
return err
|
||
}
|
||
|
||
func (a *API) SkuShopCategoryMap(shopID string, skuID int64, categoryIDsStr string) (err error) {
|
||
params := map[string]interface{}{
|
||
KeyShopID: shopID,
|
||
KeySkuID: skuID,
|
||
"category_id": categoryIDsStr,
|
||
}
|
||
_, err = a.AccessAPI("sku.shop.category.map", params)
|
||
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{})
|
||
if ok {
|
||
cats = make([]*CategoryInfo, len(maps))
|
||
for index, v := range maps {
|
||
cats[index] = interface2Cat(v, level)
|
||
}
|
||
}
|
||
return cats
|
||
}
|
||
|
||
func interface2Cat(data interface{}, level int) (cat *CategoryInfo) {
|
||
catMap := data.(map[string]interface{})
|
||
cat = &CategoryInfo{
|
||
CategoryID: utils.MustInterface2Int64(catMap["category_id"]),
|
||
Name: utils.Interface2String(catMap["name"]),
|
||
Rank: int(utils.MustInterface2Int64(catMap["rank"])),
|
||
Children: interface2CatList(catMap["children"], level+1),
|
||
Level: level,
|
||
}
|
||
return cat
|
||
}
|
||
|
||
func IsErrCategoryExist(err error) (isExist bool) {
|
||
return utils.IsErrMatch(err, "1", []string{"商户已存在该自定义分类"})
|
||
}
|
||
|
||
func IsErrCategoryNotExist(err error) (isExist bool) {
|
||
return utils.IsErrMatch(err, "", []string{"不存在该自定义分类ID", "商户不存在该自定义分类"})
|
||
}
|
||
|
||
func IsErrSkuExist(err error) (isExist bool) {
|
||
return utils.IsErrMatch(err, "1", []string{"商品已存在", "shop sku exist"})
|
||
}
|
||
|
||
func IsErrSkuNotExist(err error) (isExist bool) {
|
||
return utils.IsErrMatch(err, "1", []string{"sku_id与shop_id不匹配", "SKU不存在或者已经被删除"})
|
||
}
|
||
|
||
func (a *API) GetEbaiSkuIDFromCustomID(shopID, customSkuID string) (ebaiSkuID int64) {
|
||
if skuInfo, err2 := a.SkuList(shopID, &SkuListParams{
|
||
CustomSkuID: customSkuID,
|
||
}); err2 == nil && skuInfo != nil && len(skuInfo.List) > 0 {
|
||
ebaiSkuID = skuInfo.List[0].SkuID
|
||
}
|
||
return ebaiSkuID
|
||
}
|
||
|
||
func (a *API) GetEbaiCatIDFromName(shopID, catName string) (ebaiCatID int64) {
|
||
if catList, err2 := a.ShopCategoryGet(shopID); err2 == nil {
|
||
for _, v := range catList {
|
||
if v.Name == catName {
|
||
ebaiCatID = v.CategoryID
|
||
break
|
||
}
|
||
}
|
||
}
|
||
return ebaiCatID
|
||
}
|