package ebaiapi import ( "fmt" "regexp" "strings" "git.rosy.net.cn/baseapi/utils" ) const ( SkuStatusOnline = 1 // 为上架 SkuStatusOffline = 0 // 为下架 SkuStatusDeleted = 2 // 为删除 ) const ( UPCTypeStandard = 1 UPCTypePrivate = 0 ) const ( MaxLeftNum = 99999 ) 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"` } 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) { 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 GetEbaiSkuIDFromError(err error) int64 { if err2, ok := err.(*utils.ErrorWithCode); ok && err2.IntCode() == 1 && strings.Index(err2.ErrMsg(), "shop sku exist") >= 0 { searchResult := skuExistReg.FindStringSubmatch(err2.ErrMsg()) if searchResult != nil && len(searchResult[1]) > 0 { return utils.Str2Int64(searchResult[1]) } } return 0 } 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) 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(`%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 }