package elmapi import ( "git.rosy.net.cn/baseapi/utils" ) const ( CategoryTypeNormal = "NORMAL" CategoryTypeRequired = "REQUIRED" CategoryTypeIndependent = "INDEPENDENT" ) const ( MaxPageSize = 300 ) // 这个类型商家店内分类与饿了么分类共用, type CategoryInfo struct { Id int64 `json:"id"` Name string `json:"name"` Description string `json:"description"` // 店内分类独有 IsValid bool `json:"isValid"` // 店内分类独有 ParentId int64 `json:"parentId"` CategoryType string `json:"categoryType"` // 店内分类独有 Level int `json:"level"` // 饿了么分类独有 IsLeaf bool `json:"isLeaf"` // 饿了么分类独有 Children []*CategoryInfo `json:"children"` } type CategorySortInfo struct { ParentId int64 `json:"parentId"` ChildrenIDs []int `json:"childrenIds"` } type OItemIdWithSpecIds struct { ItemId int64 `json:"itemId"` ItemSpecIds []int64 `json:"itemSpecIds"` } type OBatchModifiedFailure struct { Id int64 `json:"id"` Code string `json:"code"` Description string `json:"description"` } const ( IdTypeItem = "ITEM_ID" IdTypeSpec = "SPEC_ID" IdTypeCategory = "CATEGORY_ID" ) type OBatchModifiedResult struct { Type string `json:"type"` Modifications []int64 `json:"modifications"` Failures []*OBatchModifiedFailure `json:"failures"` } type OItemIdWithSpecPrice struct { ItemId int64 `json:"itemId"` PriceMap map[string]float64 `json:"priceMap"` } // 查询店铺商品分类,包含二级分类 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-getShopCategoriesWithChildren func (a *API) GetShopCategoriesWithChildren(shopId int) ([]*CategoryInfo, error) { result, err := a.AccessAPI("eleme.product.category.getShopCategoriesWithChildren", utils.Params2Map(KeyShopID, shopId)) if err == nil { return interface2CatList(result.Result, 1, nil), nil } return nil, err } // 查询商品分类详情,包含二级分类 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-getCategoryWithChildren func (a *API) GetCategoryWithChildren(categoryId int64) (*CategoryInfo, error) { result, err := a.AccessAPI("eleme.product.category.getCategoryWithChildren", utils.Params2Map("categoryId", categoryId)) if err == nil { return interface2Cat(result.Result, 1), nil } return nil, err } // 添加商品分类,支持二级分类 // parentID小于0表示忽略? // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-createCategoryWithChildren func (a *API) CreateCategoryWithChildren(shopId int, parentId int64, name, description string) (*CategoryInfo, error) { params := map[string]interface{}{ KeyShopID: shopId, "name": name, } if parentId >= 0 { params["parentId"] = parentId } if description != "" { params["description"] = description } result, err := a.AccessAPI("eleme.product.category.createCategoryWithChildren", params) if err == nil { return interface2Cat(result.Result, 1), nil } return nil, err } // 更新商品分类,包含二级分类 // parentID小于0表示忽略? // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-updateCategoryWithChildren func (a *API) UpdateCategory(shopId int, parentId int64, name, description string) (*CategoryInfo, error) { params := map[string]interface{}{ KeyShopID: shopId, "name": name, } if parentId >= 0 { params["parentId"] = parentId } if description != "" { params["description"] = description } result, err := a.AccessAPI("eleme.product.category.updateCategory", params) if err == nil { return interface2Cat(result.Result, 1), nil } return nil, err } // 删除商品分类(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-invalidCategory func (a *API) InvalidCategory(categoryId int64) error { _, err := a.AccessAPI("eleme.product.category.invalidCategory", utils.Params2Map("categoryId", categoryId)) return err } // 设置二级分类排序 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-setCategoryPositionsWithChildren func (a *API) setCategoryPositionsWithChildren(shopId int, categoryWithChildrenIds []*CategorySortInfo) error { _, err := a.AccessAPI("eleme.product.category.setCategoryPositionsWithChildren", utils.Params2Map(KeyShopID, shopId, "categoryWithChildrenIds", categoryWithChildrenIds)) return err } // 设置分类排序(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-setCategorySequence func (a *API) setCategorySequence(shopId int, categoryIds []int64) error { _, err := a.AccessAPI("eleme.product.category.setCategorySequence", utils.Params2Map(KeyShopID, shopId, "categoryIds", categoryIds)) return err } // 查询商品后台类目 // 注意,这个是饿了么的商品分类,不是商家商品分类 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-getBackCategory func (a *API) GetBackCategory(shopId int) ([]*CategoryInfo, error) { result, err := a.AccessAPI("eleme.product.category.getBackCategory", utils.Params2Map(KeyShopID, shopId)) if err == nil { return interface2CatList(result.Result, 1, func(data interface{}, level int) (cat *CategoryInfo) { mapData, ok := data.(map[string]interface{}) if ok { cat = &CategoryInfo{ Id: utils.MustInterface2Int64(mapData["id"]), Name: utils.Interface2String(mapData["name"]), ParentId: utils.MustInterface2Int64(mapData["parentId"]), Level: int(utils.MustInterface2Int64(mapData["lev"])), IsLeaf: mapData["leaf"].(bool), } } return cat }), nil } return nil, err } // 设置分类类型 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-category-setCategoryType func (a *API) setCategoryType(shopId int, categoryId int64, categoryType string) error { params := map[string]interface{}{ KeyShopID: shopId, "categoryId": categoryId, "categoryType": categoryType, } _, err := a.AccessAPI("eleme.product.category.setCategoryType", params) return err } // 获取一个分类下的所有商品 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-getItemsByCategoryId func (a *API) GetItemsByCategoryId(categoryId int64) ([]map[string]interface{}, error) { result, err := a.AccessAPI("eleme.product.item.getItemsByCategoryId", utils.Params2Map("categoryId", categoryId)) if err == nil { return utils.MapKV2List(result.Result.(map[string]interface{})), nil } return nil, err } // 查询商品详情 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-getItem func (a *API) GetItem(itemId int64) (map[string]interface{}, error) { result, err := a.AccessAPI("eleme.product.item.getItem", utils.Params2Map("itemId", itemId)) if err == nil { return result.Result.(map[string]interface{}), nil } return nil, err } // 批量查询商品详情 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchGetItems func (a *API) BatchGetItems(itemIds []int64) ([]map[string]interface{}, error) { result, err := a.AccessAPI("eleme.product.item.batchGetItems", utils.Params2Map("itemIds", itemIds)) if err == nil { return utils.MapKV2List(result.Result.(map[string]interface{})), nil } return nil, err } // 添加商品 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-createItem func (a *API) CreateItem(categoryId int64, properties map[string]interface{}) (map[string]interface{}, error) { result, err := a.AccessAPI("eleme.product.item.createItem", utils.Params2Map("categoryId", categoryId, "properties", properties)) if err == nil { return result.Result.(map[string]interface{}), nil } return nil, err } // 批量添加商品 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchCreateItems func (a *API) BatchCreateItems(categoryId int64, items []map[string]interface{}) ([]map[string]interface{}, error) { result, err := a.AccessAPI("eleme.product.item.batchCreateItems", utils.Params2Map("categoryId", categoryId, "items", items)) if err == nil { return utils.Slice2MapSlice(result.Result.([]interface{})), nil } return nil, err } // 更新商品 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-updateItem func (a *API) UpdateItem(itemId, categoryId int64, properties map[string]interface{}) (map[string]interface{}, error) { result, err := a.AccessAPI("eleme.product.item.updateItem", utils.Params2Map("itemId", itemId, "categoryId", categoryId, "properties", properties)) if err == nil { return result.Result.(map[string]interface{}), nil } return nil, err } // 批量置满库存 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchFillStock func (a *API) BatchFillStock(specIds []*OItemIdWithSpecIds) error { _, err := a.AccessAPI("eleme.product.item.batchFillStock", utils.Params2Map("specIds", specIds)) return err } // 批量沽清库存 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchClearStock func (a *API) BatchClearStock(specIds []*OItemIdWithSpecIds) error { _, err := a.AccessAPI("eleme.product.item.batchClearStock", utils.Params2Map("specIds", specIds)) return err } // 批量上架商品(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchListItems func (a *API) BatchListItems(itemIds []int64) (retVal *OBatchModifiedResult, err error) { result, err := a.AccessAPI("eleme.product.item.batchListItems", utils.Params2Map("itemIds", itemIds)) if err == nil { return interface2OBatchModifiedResult(result.Result), nil } return nil, err } // 批量下架商品(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchDelistItems func (a *API) BatchDelistItems(itemIds []int64) (retVal *OBatchModifiedResult, err error) { result, err := a.AccessAPI("eleme.product.item.batchDelistItems", utils.Params2Map("itemIds", itemIds)) if err == nil { return interface2OBatchModifiedResult(result.Result), nil } return nil, err } // 删除商品(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-invalidItem func (a *API) InvalidItem(itemId int64) error { _, err := a.AccessAPI("eleme.product.item.invalidItem", utils.Params2Map("itemId", itemId)) return err } // 批量删除商品 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchRemoveItems func (a *API) BatchRemoveItems(itemIds []int64) (retVal []map[string]interface{}, err error) { result, err := a.AccessAPI("eleme.product.item.batchRemoveItems", utils.Params2Map("itemIds", itemIds)) if err == nil { return utils.MapKV2List(result.Result.(map[string]interface{})), nil } return nil, err } // 批量更新商品库存(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchUpdateStock func (a *API) BatchUpdateStock(itemIds []int64) (retVal *OBatchModifiedResult, err error) { result, err := a.AccessAPI("eleme.product.item.batchUpdateStock", utils.Params2Map("itemIds", itemIds)) if err == nil { return interface2OBatchModifiedResult(result.Result), nil } return nil, err } // 设置商品排序 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-setItemPositions func (a *API) SetItemPositions(categoryId int64, itemIds []int64) error { _, err := a.AccessAPI("eleme.product.item.setItemPositions", utils.Params2Map("categoryId", categoryId, "itemIds", itemIds)) return err } // 根据商品扩展码获取商品 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-getItemByShopIdAndExtendCode func (a *API) GetItemByShopIdAndExtendCode(shopId int, extendCode string) (retVal map[string]interface{}, err error) { result, err := a.AccessAPI("eleme.product.item.getItemByShopIdAndExtendCode", utils.Params2Map("shopId", shopId, "extendCode", extendCode)) if err == nil { return result.Result.(map[string]interface{}), nil } return nil, err } // 批量修改商品价格 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-batchUpdatePrices func (a *API) BatchUpdatePrices(shopId int, specPrices []*OItemIdWithSpecPrice) error { _, err := a.AccessAPI("eleme.product.item.batchUpdatePrices", utils.Params2Map("shopId", shopId, "specPrices", specPrices)) return err } // 查询店铺活动商品(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-getShopSalesItems func (a *API) GetShopSalesItems(shopId int) (retVal []int64, err error) { result, err := a.AccessAPI("eleme.product.item.getShopSalesItems", utils.Params2Map("shopId", shopId)) if err == nil { ls := result.Result.([]interface{}) retVal := make([]int64, len(ls)) for index, v := range ls { retVal[index] = utils.MustInterface2Int64(v) } return retVal, nil } return nil, err } // 分页获取店铺下的商品 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-product-item-queryItemByPage func (a *API) QueryItemByPage(shopId, offset, limit int) (retVal []map[string]interface{}, err error) { if offset < 0 { offset = 0 } if limit > MaxPageSize { limit = MaxPageSize } result, err := a.AccessAPI("eleme.product.item.queryItemByPage", utils.Params2Map("queryPage", map[string]interface{}{ "shopId": shopId, "offset": offset, "limit": limit, })) if err == nil { return utils.Slice2MapSlice(result.Result.([]interface{})), nil } return nil, err } // 上传图片,返回图片的hash值 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-file-uploadImage func (a *API) UploadImage(base64Content string) (hashCode string, err error) { result, err := a.AccessAPI("eleme.file.uploadImage", utils.Params2Map("image", base64Content)) if err == nil { return result.Result.(string), nil } return "", err } // 通过远程URL上传图片,返回图片的hash值 // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-file-uploadImageWithRemoteUrl func (a *API) UploadImageWithRemoteUrl(imgURL string) (hashCode string, err error) { result, err := a.AccessAPI("eleme.file.uploadImageWithRemoteUrl", utils.Params2Map("url", imgURL)) if err == nil { return result.Result.(string), nil } return "", err } // 获取上传图片的url地址(新版) // https://open.shop.ele.me/openapi/apilist/eleme-product/eleme-file-getImageUrl func (a *API) GetImageUrl(hashCode string) (imgURL string, err error) { result, err := a.AccessAPI("eleme.file.getImageUrl", utils.Params2Map("hash", hashCode)) if err == nil { return result.Result.(string), nil } return "", err } /////////////////////////// // 私有辅助函数 func interface2Cat(data interface{}, level int) (cat *CategoryInfo) { mapData, ok := data.(map[string]interface{}) if ok { cat = &CategoryInfo{ Id: utils.MustInterface2Int64(mapData["id"]), Name: utils.Interface2String(mapData["name"]), Description: utils.Interface2String(mapData["description"]), ParentId: utils.MustInterface2Int64(mapData["parentId"]), CategoryType: utils.Interface2String(mapData["categoryType"]), Level: level, IsLeaf: false, } if utils.MustInterface2Int64(mapData["isValid"]) != 0 { cat.IsValid = true } else { cat.IsValid = false } cat.Children = interface2CatList(mapData["children"], level+1, interface2Cat) if len(cat.Children) == 0 { cat.IsLeaf = true } } return cat } func interface2CatList(data interface{}, level int, interface2CatHandler func(data interface{}, level int) (cat *CategoryInfo)) (cats []*CategoryInfo) { if interface2CatHandler == nil { interface2CatHandler = interface2Cat } maps, ok := data.([]interface{}) if ok { cats = make([]*CategoryInfo, len(maps)) for index, v := range maps { cats[index] = interface2CatHandler(v, level) } } return cats } func interface2OBatchModifiedResult(data interface{}) (retVal *OBatchModifiedResult) { mapData := data.(map[string]interface{}) retVal = &OBatchModifiedResult{ Type: utils.Interface2String(mapData["type"]), } if modifications, ok := mapData["modifications"].([]interface{}); ok { retVal.Modifications = make([]int64, len(modifications)) for index, v := range modifications { retVal.Modifications[index] = utils.MustInterface2Int64(v) } } if failures, ok := mapData["failures"].([]interface{}); ok { retVal.Failures = make([]*OBatchModifiedFailure, len(failures)) for index, v := range failures { mp := v.(map[string]interface{}) retVal.Failures[index] = &OBatchModifiedFailure{ Id: utils.MustInterface2Int64(mp["id"]), Code: utils.Interface2String(mp["code"]), Description: utils.Interface2String(mp["description"]), } } } return retVal }