Files
baseapi/platformapi/elmapi/product.go
2025-11-21 09:09:09 +08:00

456 lines
17 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}