796 lines
29 KiB
Go
796 lines
29 KiB
Go
package jdapi
|
||
|
||
import (
|
||
"fmt"
|
||
"regexp"
|
||
"strings"
|
||
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
)
|
||
|
||
const (
|
||
KeyBrandId = "brandId"
|
||
KeyBrandName = "brandName"
|
||
KeyBrandStatus = "brandStatus"
|
||
KeyCategoryId = "categoryId"
|
||
KeyChildIds = "childIds"
|
||
KeyFields = "fields"
|
||
KeyFixedStatus = "fixedStatus"
|
||
KeyHandleStatus = "handleStatus"
|
||
KeyHeight = "height"
|
||
KeyID = "id"
|
||
KeyImages = "images"
|
||
KeyImgType = "imgType"
|
||
KeyIfViewDesc = "ifViewDesc"
|
||
KeyIsFilterDel = "isFilterDel"
|
||
KeyIsSale = "isSale"
|
||
KeyKeyValue = "keyValue"
|
||
KeyLength = "length"
|
||
KeyLiquidStatue = "liquidStatue"
|
||
KeyOutSkuId = "outSkuId"
|
||
KeyOutSpuId = "outSuperId"
|
||
KeySpuName = "superName"
|
||
KeySkuMainInfo = "skuMainInfo"
|
||
KeyPID = "pid"
|
||
KeyProductDesc = "productDesc"
|
||
KeyPageNo = "pageNo"
|
||
KeyPageSize = "pageSize"
|
||
KeyPrefixKey = "prefixKey"
|
||
KeyPrefixKeyId = "prefixKeyId"
|
||
KeyPreKeyEndTime = "preKeyEndTime"
|
||
KeyPreKeyStartTime = "preKeyStartTime"
|
||
KeyPrescripition = "prescripition"
|
||
KeyShopCategoryLevel = "shopCategoryLevel"
|
||
KeyShopCategoryName = "shopCategoryName"
|
||
KeyShopCategories = "shopCategories"
|
||
KeySellCities = "sellCities"
|
||
KeySlogan = "slogan"
|
||
KeySloganEndTime = "sloganEndTime"
|
||
KeySloganStartTime = "sloganStartTime"
|
||
KeySort = "sort"
|
||
KeySkuId = "skuId"
|
||
KeySkuName = "skuName"
|
||
KeySkuPrice = "skuPrice"
|
||
KeyStoreId = "storeId"
|
||
KeySystemFixedStatus = "systemFixedStatus"
|
||
KeyTransportAttribute = "transportAttribute"
|
||
KeyUpcCode = "upcCode"
|
||
KeyWeight = "weight"
|
||
)
|
||
|
||
const (
|
||
FakeKeySpecAttr = "specAttr"
|
||
)
|
||
|
||
const (
|
||
MaxBatchSize4BatchUpdateOutSkuId = 50
|
||
MaxPageSize4QuerySku = 50
|
||
MaxSkuIDsCount4QueryListBySkuIds = 25
|
||
|
||
ErrMustUPC = "处方药商品请根据商品UPC码批量新增商品接口创建"
|
||
)
|
||
|
||
const (
|
||
SkuFixedStatusOnline = 1 // 上架
|
||
SkuFixedStatusOffline = 2 // 下架
|
||
SkuFixedStatusDeleted = 4 // 删除
|
||
)
|
||
|
||
const (
|
||
CreateSpuResultSuccess = 1
|
||
CreateSpuResultInProgress = 2
|
||
CreateSpuResultFailed = 3
|
||
)
|
||
|
||
const (
|
||
IsFilterDelTrue = "0" // 0代表不查已删除商品
|
||
)
|
||
|
||
const (
|
||
MaxSkuNameCharCount = 45 // skuname最长字符数
|
||
SaleAttrIDBase = 1001
|
||
SaleAttrValueIDBase = 10
|
||
)
|
||
|
||
const (
|
||
ImgTypeMain = 1 // 商品图片
|
||
ImgTypeDetail = 2 // 详情图片
|
||
)
|
||
|
||
type SkuIDPair struct {
|
||
SkuId int64 `json:"skuId"`
|
||
OutSkuId string `json:"outSkuId"`
|
||
}
|
||
|
||
type BatchUpdateOutSkuIdFailedItem struct {
|
||
Detail string `json:"detail"`
|
||
SkuInfo *SkuIDPair `json:"skuInfo"`
|
||
}
|
||
|
||
type BrandInfo struct {
|
||
ID int `json:"id"`
|
||
BrandName string `json:"brandName"`
|
||
BrandStatus int `json:"brandStatus"`
|
||
}
|
||
|
||
type IDKeyValuePair struct {
|
||
ID string `json:"_id"`
|
||
KeyValue string `json:"keyValue"`
|
||
}
|
||
|
||
type ProductStatus struct {
|
||
Synchronized bool `json:"synchronized"`
|
||
EsEntity map[string]interface{} `json:"esEntity"`
|
||
ProductEntity map[string]interface{} `json:"productEntity"`
|
||
}
|
||
|
||
// 这个类型商家店内分类与到家分类共用,
|
||
type CategoryInfo struct {
|
||
Id int64 `json:"id"`
|
||
ParentId int64 `json:"pid"`
|
||
Name string `json:"categoryName"`
|
||
Level int `json:"categoryLevel"`
|
||
Sort int `json:"sort"` // 店内分类独有
|
||
Status int `json:"status"` // 到家分类独有
|
||
FullPath string `json:"fullPath"` // 到家分类独有
|
||
}
|
||
|
||
type CreateByUpcParam struct {
|
||
UniqueUpc string `json:"uniqueCode"` // 商品UPC码
|
||
OutSku string `json:"outSku"` // 商家商品编码,商家系统中唯一编码,限1-35字符,与到家商品编码一对一对应
|
||
JdPrice string `json:"jdPrice"` // 商家商品价格(单位:元),用于初始商品门店价格,所有的商品门店价格都会初始化成该值。后续修改商品门店价格需要通过价格类接口修改。
|
||
ShopCategoryID int64 `json:"shopCategoryId"` // 商家店内分类编码,店内分类编码通过查询商家店内分类信息接口获取
|
||
IsSale bool `json:"isSale"` // 门店商品可售状态,true为可售,false为不可售,默认为可售。
|
||
}
|
||
|
||
type CreateByUpcParam2 struct {
|
||
Upc string `json:"upc"` // 商品UPC码
|
||
OutSkuId string `json:"outSkuId"` // 商家商品编码,商家系统中唯一编码,限1-35字符,与到家商品编码一对一对应
|
||
JdPrice string `json:"jdPrice"` // 商家商品价格(单位:元),用于初始商品门店价格,所有的商品门店价格都会初始化成该值。后续修改商品门店价格需要通过价格类接口修改。
|
||
ShopCategoryID int64 `json:"shopCategoryId"` // 商家店内分类编码,店内分类编码通过查询商家店内分类信息接口获取
|
||
IsSale bool `json:"isSale"` // 门店商品可售状态,true为可售,false为不可售,默认为可售。
|
||
}
|
||
|
||
type CreateByUpcPair struct {
|
||
Upc string
|
||
SkuId int64
|
||
}
|
||
|
||
type QuerySkuParam struct {
|
||
SkuName string `json:"skuName,omitempty"`
|
||
UpcCode string `json:"upcCode,omitempty"`
|
||
SkuID int64 `json:"skuId,omitempty"`
|
||
IsFilterDel string `json:"isFilterDel,omitempty"` // 是否查询出已删除的上传商品(0代表不查已删除商品,不填则查出全部商品)
|
||
PageNo int `json:"pageNo,omitempty"`
|
||
PageSize int `json:"pageSize,omitempty"`
|
||
}
|
||
|
||
type SkuMain struct {
|
||
SuperID int64 `json:"superId"`
|
||
SkuID int64 `json:"skuId"`
|
||
OutSkuID string `json:"outSkuId"`
|
||
CategoryID int64 `json:"categoryId"`
|
||
BrandID int64 `json:"brandId"`
|
||
ShopCategories []int64 `json:"shopCategories"`
|
||
SkuName string `json:"skuName"`
|
||
Slogan string `json:"slogan"`
|
||
FixedStatus int `json:"fixedStatus"` // 商家商品上下架状态(1:上架;2:下架;4:删除;)
|
||
FixedUpTime string `json:"fixedUpTime"`
|
||
OrgCode int `json:"orgCode"`
|
||
SellCities []int64 `json:"sellCities"`
|
||
SkuPrice int `json:"skuPrice"`
|
||
Weight float64 `json:"weight"`
|
||
}
|
||
|
||
const (
|
||
IsSaleYes = 1
|
||
IsSaleNo = -1
|
||
)
|
||
|
||
type OpSkuParam struct {
|
||
TraceID string `json:"traceId"`
|
||
OutSkuID string `json:"outSkuId"`
|
||
ShopCategories []int64 `json:"shopCategories,omitempty"`
|
||
CategoryID int64 `json:"categoryId,omitempty"`
|
||
BrandID int64 `json:"brandId,omitempty"`
|
||
SkuName string `json:"skuName,omitempty"`
|
||
SkuPrice int `json:"skuPrice,omitempty"`
|
||
Weight float64 `json:"weight,omitempty"`
|
||
FixedStatus int `json:"fixedStatus,omitempty"` // 商家商品上下架状态(1:上架;2:下架;4:删除;)
|
||
IsSale int `json:"-"` // 创建:0,1可售,-1不可售,更新:0忽略,1可售,-1不可售
|
||
DontUseThisFieldDirectlyIsSale bool `json:"isSale"` // 门店商品可售状态(true/false);新建商品时,如果为true,门店商品可售状态初始为可售,如果为false, 门店商品可售状态初始为不可售。后续修改各个门店商品可售状态时,请使用根据京东到家商品编码批量修改门店商品可售状态接口。
|
||
|
||
Upc string `json:"upcCode,omitempty"` // TODO 老版与新版接口参数不一致,UPC编码(商品条码),限1-35个字符,包装类的商品要求UPC编码必填,且要符合条码编写的校验,否则商品会不予通过,接口返回错误状态码code为10059。
|
||
Images []string `json:"images,omitempty"`
|
||
ProductDesc string `json:"productDesc,omitempty"`
|
||
IfViewDesc int `json:"ifViewDesc"`
|
||
Slogan string `json:"slogan,omitempty"`
|
||
SloganStartTime string `json:"sloganStartTime,omitempty"`
|
||
SloganEndTime string `json:"sloganEndTime,omitempty"`
|
||
SellCities []int64 `json:"sellCities,omitempty"`
|
||
}
|
||
|
||
type QueryListBySkuIdsParam struct {
|
||
SkuIDs []int64 `json:"skuIds"`
|
||
ImgType int `json:"imgType,omitempty"`
|
||
HandleStatus []int `json:"handleStatus,omitempty"`
|
||
}
|
||
|
||
type ImgHandleQueryResult struct {
|
||
ID string `json:"id"`
|
||
SkuID int64 `json:"skuId"`
|
||
IsMain int `json:"isMain"`
|
||
ImgType int `json:"imgType"`
|
||
SourceImgURL string `json:"sourceImgUrl"`
|
||
SkuImgSort int `json:"skuImgSort"`
|
||
HandleStatus int `json:"handleStatus"`
|
||
HandleStatusStr string `json:"handleStatusStr"`
|
||
HandleRemark string `json:"handleRemark"`
|
||
HandleErrLog string `json:"handleErrLog"`
|
||
}
|
||
|
||
var (
|
||
skuExistReg = regexp.MustCompile(`商家skuId已存在:(\d+)`)
|
||
)
|
||
|
||
// 分页查询商品品牌信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=1ca07a3e767649a7a44fc6ea7e9ed8dd
|
||
func (a *API) QueryPageBrandInfo(pageNo, pageSize int, brandId int64, brandName string) (brandList []*BrandInfo, totalCount int, err error) {
|
||
if pageNo <= 0 {
|
||
pageNo = 1
|
||
}
|
||
if pageSize == 0 {
|
||
pageSize = 50
|
||
}
|
||
params := map[string]interface{}{
|
||
KeyPageNo: pageNo, // pageNo好像必须要有值,否则一直不返回
|
||
KeyPageSize: pageSize,
|
||
KeyFields: []string{
|
||
"BRAND_ID",
|
||
"BRAND_NAME",
|
||
"BRAND_STATUS",
|
||
},
|
||
}
|
||
if brandId != 0 {
|
||
params[KeyBrandId] = brandId
|
||
}
|
||
if brandName != "" {
|
||
params[KeyBrandName] = brandName
|
||
}
|
||
|
||
result, totalCount, err := a.AccessAPIHavePage("pms/queryPageBrandInfo", params, nil, nil, nil)
|
||
if err == nil {
|
||
brandList = make([]*BrandInfo, len(result))
|
||
for index, v := range result {
|
||
mapData := v.(map[string]interface{})
|
||
brandList[index] = &BrandInfo{
|
||
ID: int(utils.MustInterface2Int64(mapData[KeyID])),
|
||
BrandName: utils.Interface2String(mapData[KeyBrandName]),
|
||
BrandStatus: int(utils.MustInterface2Int64(mapData[KeyBrandStatus])),
|
||
}
|
||
}
|
||
return brandList, totalCount, nil
|
||
}
|
||
return nil, 0, err
|
||
}
|
||
|
||
// 获取京东到家类目信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=d287d326124d42c090cff03c16385706
|
||
func (a *API) QueryChildCategoriesForOP(pid int64) (catList []*CategoryInfo, err error) {
|
||
result, err := a.AccessAPINoPage("api/queryChildCategoriesForOP", utils.Params2Map("fields", []string{
|
||
"ID",
|
||
"PID",
|
||
"CATEGORY_NAME",
|
||
"CATEGORY_LEVEL",
|
||
"CATEGORY_STATUS",
|
||
"FULLPATH",
|
||
}, "id", pid), nil, nil, nil)
|
||
if err == nil {
|
||
return interface2CatList(result, 1, func(data interface{}, level int) (cat *CategoryInfo) {
|
||
mapData, ok := data.(map[string]interface{})
|
||
if ok {
|
||
cat = &CategoryInfo{
|
||
Id: utils.MustInterface2Int64(mapData["id"]),
|
||
ParentId: utils.MustInterface2Int64(mapData["pid"]),
|
||
Name: utils.Interface2String(mapData["categoryName"]),
|
||
Level: int(utils.MustInterface2Int64(mapData["categoryLevel"])),
|
||
Status: int(utils.MustInterface2Int64(mapData["categoryStatus"])),
|
||
FullPath: utils.Interface2String(mapData["fullPath"]),
|
||
}
|
||
}
|
||
return cat
|
||
}), nil
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=de26f24a62aa47a49e5ab7579d638cb3
|
||
func (a *API) AddShopCategory(pid int64, shopCategoryName string, shopCategoryLevel, sort int, userName string) (catId string, err error) {
|
||
params := map[string]interface{}{
|
||
KeyPID: pid,
|
||
KeyShopCategoryName: shopCategoryName,
|
||
}
|
||
if shopCategoryLevel > 0 {
|
||
params[KeyShopCategoryLevel] = shopCategoryLevel
|
||
}
|
||
if sort >= 0 {
|
||
params[KeySort] = sort
|
||
}
|
||
if userName != "" {
|
||
params["createPin"] = utils.GetAPIOperator(userName)
|
||
}
|
||
result, err := a.AccessAPINoPage("pms/addShopCategory", params, nil, nil, nil)
|
||
if err == nil {
|
||
return (result.(map[string]interface{}))["id"].(string), nil
|
||
}
|
||
return "", err
|
||
}
|
||
|
||
// 查询商家店内分类信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=964f2d248a7e42b196be2ab35b4e93b4
|
||
func (a *API) QueryCategoriesByOrgCode() (catList []*CategoryInfo, err error) {
|
||
result, err := a.AccessAPINoPage("pms/queryCategoriesByOrgCode", utils.Params2Map("fields", []string{
|
||
"ID",
|
||
"PID",
|
||
"SHOP_CATEGORY_NAME",
|
||
"SHOP_CATEGORY_LEVEL",
|
||
"SORT",
|
||
}), nil, nil, nil)
|
||
if err == nil {
|
||
return interface2CatList(result, 1, nil), nil
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
// 修改商家店内分类信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=1de278c670b64da492f676ab78d62f73
|
||
func (a *API) UpdateShopCategory(id int64, shopCategoryName string) error {
|
||
params := map[string]interface{}{
|
||
KeyID: id,
|
||
KeyShopCategoryName: shopCategoryName,
|
||
}
|
||
_, err := a.AccessAPINoPage("pms/updateShopCategory", params, nil, nil, nullResultParser)
|
||
if IsErrIgnorable(err) {
|
||
err = nil
|
||
}
|
||
return err
|
||
}
|
||
|
||
func IsErrIgnorable(err error) bool {
|
||
return err == nil || utils.IsErrMatch(err, "-3", []string{"店内分类名称未修改,无需操作"})
|
||
}
|
||
|
||
// 修改商家店内分类顺序接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=2a8267602e814be9828f0c7ce307b872
|
||
func (a *API) ChangeShopCategoryOrder(pid int64, childIds []int64) error {
|
||
params := map[string]interface{}{
|
||
KeyPID: pid,
|
||
KeyChildIds: childIds,
|
||
}
|
||
_, err := a.AccessAPINoPage("pms/changeShopCategoryOrder", params, nil, nil, nullResultParser)
|
||
return err
|
||
}
|
||
|
||
// 删除商家店内分类接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=c17b96e9fe254b2a8574f6d1bc0c1667
|
||
// 删除一个不存在的分类,好像不会报错
|
||
func (a *API) DelShopCategory(id int64) error {
|
||
_, err := a.AccessAPINoPage("pms/delShopCategory", utils.Params2Map(KeyID, id), nil, nil, nullResultParser)
|
||
return err
|
||
}
|
||
|
||
// 新增商品信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=dfe6a5ca73fa421da1c9f969b848113e
|
||
func (a *API) AddSku(outSkuId string, cagtegoryId int, shopCategories []int64, brandId int, skuName string, skuPrice int, weight float32, images []string, fixedStatus int, isSale bool, addParams map[string]interface{}) (skuId string, err error) {
|
||
fixedParams := map[string]interface{}{
|
||
KeyOutSkuId: outSkuId,
|
||
KeyCategoryId: cagtegoryId,
|
||
KeyShopCategories: shopCategories,
|
||
KeyBrandId: brandId,
|
||
KeySkuName: skuName,
|
||
KeySkuPrice: skuPrice,
|
||
KeyWeight: weight,
|
||
KeyImages: images,
|
||
KeyFixedStatus: fixedStatus,
|
||
KeyIsSale: isSale,
|
||
}
|
||
result, err := a.AccessAPINoPage("pms/sku/addSku", utils.MergeMaps(fixedParams, addParams), nil, nil, nil)
|
||
if err == nil {
|
||
return (result.(map[string]interface{}))["skuId"].(string), nil
|
||
}
|
||
return "", err
|
||
}
|
||
|
||
func translateIsSale(isSale int) bool {
|
||
return isSale == 0 || isSale == IsSaleYes
|
||
}
|
||
|
||
func (a *API) AddSku2(param *OpSkuParam) (skuID string, err error) {
|
||
param.DontUseThisFieldDirectlyIsSale = translateIsSale(param.IsSale)
|
||
mapData := utils.Struct2MapByJson(param)
|
||
result, err := a.AccessAPINoPage("pms/sku/addSku", mapData, nil, nil, nil)
|
||
if err == nil {
|
||
return (result.(map[string]interface{}))["skuId"].(string), nil
|
||
}
|
||
return "", err
|
||
}
|
||
|
||
// 根据商家商品编码修改商品信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=290bdb0ea8a44e10b86b05591254ad68
|
||
func (a *API) UpdateSku(outSkuId string, params map[string]interface{}) (skuId string, err error) {
|
||
result, err := a.AccessAPINoPage("pms/sku/updateSku", utils.MergeMaps(params, utils.Params2Map("outSkuId", outSkuId)), nil, nil, nil)
|
||
if err == nil {
|
||
return (result.(map[string]interface{}))["skuId"].(string), nil
|
||
}
|
||
return "", err
|
||
}
|
||
|
||
func (a *API) UpdateSku2(param *OpSkuParam) (skuID string, err error) {
|
||
param.DontUseThisFieldDirectlyIsSale = translateIsSale(param.IsSale)
|
||
mapData := utils.Struct2MapByJson(param)
|
||
result, err := a.AccessAPINoPage("pms/sku/updateSku", mapData, nil, nil, nil)
|
||
if err == nil {
|
||
return (result.(map[string]interface{}))["skuId"].(string), nil
|
||
}
|
||
return "", err
|
||
}
|
||
|
||
// 根据到家商品编码批量更新商家商品编码接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=4155d29bbdf649b69c67473b705ce7e7
|
||
func (a *API) BatchUpdateOutSkuId(skuInfoList []*SkuIDPair) (failedList []*BatchUpdateOutSkuIdFailedItem, err error) {
|
||
result, err := a.AccessAPINoPage("pms/sku/batchUpdateOutSkuId", utils.Params2Map("skuInfoList", skuInfoList), nil, nil, nil)
|
||
err2 := utils.Map2StructByJson(result, &failedList, false)
|
||
if err == nil {
|
||
err = err2
|
||
}
|
||
return failedList, err
|
||
}
|
||
|
||
// 查询商家已上传商品信息列表接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=e433b95f74524dab91718432c0358977
|
||
// pageNo 从1开始
|
||
func (a *API) QuerySkuInfos(queryParam *QuerySkuParam) (skuList []*SkuMain, totalCount int, err error) {
|
||
if queryParam.PageNo <= 0 {
|
||
queryParam.PageNo = 1
|
||
}
|
||
if queryParam.PageSize == 0 {
|
||
queryParam.PageSize = MaxPageSize4QuerySku
|
||
}
|
||
result, totalCount, err := a.AccessAPIHavePage("pms/querySkuInfos", utils.Struct2MapByJson(queryParam), nil, nil, nil)
|
||
if err == nil {
|
||
err = JdMap2StructByJson(result, &skuList, false)
|
||
}
|
||
return skuList, totalCount, err
|
||
}
|
||
|
||
// 查询商品图片处理结果接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=17506653e03542f9a49023711780c30d
|
||
func (a *API) QueryListBySkuIds(queryParam *QueryListBySkuIdsParam) (imgList []*ImgHandleQueryResult, err error) {
|
||
result, err := a.AccessAPINoPage("order/queryListBySkuIds", utils.Struct2MapByJson(queryParam), nil, nil, nil)
|
||
if err == nil {
|
||
err = JdMap2StructByJson(result, &imgList, false)
|
||
}
|
||
return imgList, err
|
||
}
|
||
|
||
// 分页查询京东到家商品前缀库接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=2195b87baf0c4783bb1a4fda35aea7d1
|
||
func (a *API) QueryKeyWordDicInfo(pageNo, pageSize int, keyValue string) (values []*IDKeyValuePair, totalCount int, err error) {
|
||
if pageNo <= 0 {
|
||
pageNo = 1
|
||
}
|
||
if pageSize == 0 {
|
||
pageSize = 50
|
||
}
|
||
params := map[string]interface{}{
|
||
KeyPageNo: pageNo, // pageNo好像必须要有值,否则一直不返回
|
||
KeyPageSize: pageSize,
|
||
KeyFields: []string{
|
||
"ID",
|
||
"KEYVALUE",
|
||
},
|
||
}
|
||
if keyValue != "" {
|
||
params[KeyKeyValue] = keyValue
|
||
}
|
||
|
||
result, totalCount, err := a.AccessAPIHavePage("pms/queryKeyWordDicInfo", params, nil, nil, nil)
|
||
if err == nil {
|
||
values = make([]*IDKeyValuePair, len(result))
|
||
for index, v := range result {
|
||
mapData := v.(map[string]interface{})
|
||
values[index] = &IDKeyValuePair{
|
||
ID: utils.Interface2String(mapData["_id"]),
|
||
KeyValue: utils.Interface2String(mapData[KeyKeyValue]),
|
||
}
|
||
}
|
||
return values, totalCount, nil
|
||
}
|
||
return nil, 0, err
|
||
}
|
||
|
||
// 商家商品状态同步接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=5e29d6c9317847e58b8cbcc70702fd52
|
||
func (a *API) SyncProduct(storeId, skuId string) (retVal bool, err error) {
|
||
result, err := a.AccessAPINoPage("search/syncProduct", utils.Params2Map(KeyStoreId, storeId, KeySkuId, skuId), nil, nil, genNoPageResultParser("status", "message", "synchronized", "200"))
|
||
if err == nil {
|
||
return result.(bool), nil
|
||
}
|
||
return false, err
|
||
}
|
||
|
||
// 商家商品状态检查接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=a348122182ef459982cae1280407ff17
|
||
func (a *API) GetProductStatus(storeId, skuId string) (retVal *ProductStatus, err error) {
|
||
result, err := a.AccessAPINoPage("search/getProductStatus", utils.Params2Map(KeyStoreId, storeId, KeySkuId, skuId), nil, nil, func(data map[string]interface{}) (interface{}, error) {
|
||
status := utils.MustInterface2Int64(data["status"])
|
||
if status == 200 {
|
||
return &ProductStatus{
|
||
Synchronized: data["synchronized"].(bool),
|
||
EsEntity: data["esEntity"].(map[string]interface{}),
|
||
ProductEntity: data["productEntity"].(map[string]interface{}),
|
||
}, nil
|
||
}
|
||
return nil, utils.NewErrorIntCode(data["message"].(string), int(status))
|
||
})
|
||
if err == nil {
|
||
return result.(*ProductStatus), nil
|
||
}
|
||
return nil, err
|
||
|
||
}
|
||
|
||
// 新增SPU信息接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=e30936da75294e55bcfdabb92c3815bc
|
||
func (a *API) AddSpu(outSpuId string, cagtegoryId int, shopCategories []int64, brandId int, spuName string, images []string, fixedStatus int, addParams map[string]interface{}, skus []map[string]interface{}) (spuId int64, skuPairs []*SkuIDPair, err error) {
|
||
attrList := []string{}
|
||
for k, v := range skus {
|
||
attr := v[FakeKeySpecAttr].(string) //getSkuAttr(v[KeyWeight].(float32))
|
||
attrList = append(attrList, attr)
|
||
skus[k] = utils.MergeMaps(map[string]interface{}{
|
||
"saleAttrValues": genAttrMapList(attr),
|
||
}, v)
|
||
delete(skus[k], FakeKeySpecAttr)
|
||
}
|
||
fixedParams := map[string]interface{}{
|
||
KeyOutSpuId: outSpuId,
|
||
KeyCategoryId: cagtegoryId,
|
||
KeyShopCategories: shopCategories,
|
||
KeyBrandId: brandId,
|
||
KeySpuName: spuName,
|
||
KeyImages: images,
|
||
KeyFixedStatus: fixedStatus,
|
||
KeySkuMainInfo: skus,
|
||
KeyProductDesc: spuName, // todo
|
||
"saleAttrRelationInfoList": []map[string]interface{}{
|
||
map[string]interface{}{
|
||
"saleAttrName": "规格",
|
||
"saleAttrValueNameList": attrList,
|
||
},
|
||
},
|
||
}
|
||
result, err := a.AccessAPINoPage("pms/addSpu", utils.MergeMaps(fixedParams, addParams), nil, nil, nil)
|
||
if err == nil {
|
||
resultMap := result.(map[string]interface{})
|
||
skuMainParterResponseList := resultMap["skuMainParterResponseList"].([]interface{})
|
||
skuPairs = make([]*SkuIDPair, len(skuMainParterResponseList))
|
||
for k, v := range skuMainParterResponseList {
|
||
v2 := v.(map[string]interface{})
|
||
skuPairs[k] = &SkuIDPair{
|
||
OutSkuId: v2["outSkuId"].(string),
|
||
SkuId: utils.Str2Int64(v2["skuId"].(string)),
|
||
}
|
||
}
|
||
return utils.MustInterface2Int64(resultMap["superId"]), skuPairs, nil
|
||
}
|
||
return 0, nil, err
|
||
}
|
||
|
||
// 追加新的SKU到指定的SPU接口
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=cffb839b06f042b28d6397b6bd4f2676
|
||
func (a *API) AppendSku(outSpuId string, outSkuId string, skuName string, skuPrice int, weight float32, images []string, fixedStatus int, isSale bool, specAttr string, addParams map[string]interface{}) (skuID int64, err error) {
|
||
attr := specAttr //getSkuAttr(weight)
|
||
if err = a.AppendSpuSaleAttr(outSpuId, utils.Int2Str(SaleAttrIDBase), attr); err != nil {
|
||
return 0, err
|
||
}
|
||
|
||
fixedParams := map[string]interface{}{
|
||
KeyOutSpuId: outSpuId,
|
||
KeyOutSkuId: outSkuId,
|
||
KeySkuName: skuName,
|
||
KeySkuPrice: skuPrice,
|
||
KeyWeight: weight,
|
||
KeyImages: images,
|
||
KeyFixedStatus: fixedStatus,
|
||
KeyIsSale: isSale,
|
||
"saleAttrValues": genAttrMapList(attr),
|
||
}
|
||
result, err := a.AccessAPINoPage("pms/appendSku", utils.MergeMaps(fixedParams, addParams), nil, nil, nil)
|
||
if err == nil {
|
||
resultMap := result.(map[string]interface{})
|
||
skuMainParterResponseList := resultMap["skuMainParterResponseList"].([]interface{})
|
||
return utils.Str2Int64(skuMainParterResponseList[0].(map[string]interface{})["skuId"].(string)), nil
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
// 更新SPU基础信息,不可以更新销售属性
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=3816c5eadc5d4f268f760cac14483ec0
|
||
func (a *API) UpdateSpu(outSpuId string, params map[string]interface{}) (err error) {
|
||
_, err = a.AccessAPINoPage("pms/updateSpu", utils.MergeMaps(params, utils.Params2Map(KeyOutSpuId, outSpuId)), nil, nil, nil)
|
||
return err
|
||
}
|
||
|
||
// 更新SPU下指定SKU的基础信息
|
||
// https://opendj.jd.com/staticnew/widgets/resources.html?groupid=180&apiid=8be2b5d153044179a13089e7f19e24e6
|
||
func (a *API) UpdateSkuBaseInfo(outSpuId, outSkuId string, params map[string]interface{}) (err error) {
|
||
_, err = a.AccessAPINoPage("pms/updateSkuBaseInfo", utils.MergeMaps(params, utils.Params2Map(KeyOutSpuId, outSpuId, KeyOutSkuId, outSkuId)), nil, nil, nil)
|
||
return err
|
||
}
|
||
|
||
func (a *API) GetSkuSaleAttrName() (saleAttrNameList []string, err error) {
|
||
result, err := a.AccessAPINoPage("pms/getSkuSaleAttrName", nil, nil, nil, nil)
|
||
if err == nil {
|
||
return utils.Slice2StringSlice(result.([]interface{})), nil
|
||
}
|
||
return nil, err
|
||
|
||
}
|
||
|
||
func (a *API) AppendSpuSaleAttr(outSpuId, attrName, attrNewValue string) (err error) {
|
||
_, err = a.AccessAPINoPage("pms/appendSpuSaleAttr", map[string]interface{}{
|
||
KeyOutSpuId: outSpuId,
|
||
"saleAttrId": attrName,
|
||
"saleAttrValueName": attrNewValue,
|
||
}, nil, nil, nil)
|
||
return err
|
||
}
|
||
|
||
func (a *API) GetSpuSaleAttr(outSpuId string) (attrList []map[string]interface{}, err error) {
|
||
result, err := a.AccessAPINoPage("pms/getSpuSaleAttr", map[string]interface{}{
|
||
KeyOutSpuId: outSpuId,
|
||
}, nil, nil, nil)
|
||
if err == nil {
|
||
return utils.Slice2MapSlice(result.([]interface{})), nil
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
func (a *API) BatchAddSku(batchSkuRequestList []*CreateByUpcParam) (pairs []*CreateByUpcPair, err error) {
|
||
result, err := a.AccessAPINoPage("PmsSkuMainService/batchAddSku", map[string]interface{}{
|
||
"batchSkuRequestList": batchSkuRequestList,
|
||
}, nil, nil, genNoPageResultParser("code", "result", "detail", "0"))
|
||
if err == nil {
|
||
// todo 这个API在找不到UPC创建失败时,code也是0,底层不能判断失败
|
||
if result2, ok := result.([]interface{}); ok && len(result2) > 0 {
|
||
detail := utils.Slice2MapSlice(result2)
|
||
pairs = make([]*CreateByUpcPair, len(detail))
|
||
for k, v := range detail {
|
||
pairs[k] = &CreateByUpcPair{
|
||
Upc: utils.Interface2String(v["uniqueCode"]),
|
||
SkuId: utils.MustInterface2Int64(v["skuId"]),
|
||
}
|
||
}
|
||
return pairs, nil
|
||
} else {
|
||
return nil, utils.NewErrorIntCode("BatchAddSku失败", -1)
|
||
}
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
type BatchAddSkuByUPCResult struct {
|
||
FailedDetail string `json:"failedDetail"`
|
||
OrgCode string `json:"orgCode"`
|
||
OutSkuID string `json:"outSkuId"`
|
||
ResultCode string `json:"resultCode"`
|
||
ResultMsg string `json:"resultMsg"`
|
||
SkuID string `json:"skuId"`
|
||
UpcCode string `json:"upcCode"`
|
||
}
|
||
|
||
func (a *API) BatchAddSkuByUPC(batchSkuRequestList []*CreateByUpcParam2) (batchAddSkuByUPCResult *BatchAddSkuByUPCResult, err error) {
|
||
result, err := a.AccessAPINoPage("pms/batchAddSku", map[string]interface{}{
|
||
"traceId": utils.GetUUID(),
|
||
"openBatchAddSkuRequests": batchSkuRequestList,
|
||
}, nil, nil, nil)
|
||
if err == nil {
|
||
utils.Map2StructByJson(result.([]interface{})[0].(map[string]interface{}), &batchAddSkuByUPCResult, false)
|
||
if batchAddSkuByUPCResult.SkuID == "" && batchAddSkuByUPCResult.FailedDetail != "" {
|
||
return nil, fmt.Errorf(batchAddSkuByUPCResult.FailedDetail)
|
||
}
|
||
}
|
||
return batchAddSkuByUPCResult, err
|
||
}
|
||
|
||
func (a *API) GetSpuStatus(outSpuId string) (resultStatus int, err error) {
|
||
result, err := a.AccessAPINoPage("pms/getSpuStatus", map[string]interface{}{
|
||
"outSuperId": outSpuId,
|
||
}, nil, nil, nil)
|
||
if err == nil {
|
||
return int(utils.MustInterface2Int64(result.(map[string]interface{})["status"])), nil
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
func (a *API) GetSkuStatus(outSkuId string) (resultStatus int, err error) {
|
||
result, err := a.AccessAPINoPage("pms/getSkuStatus", map[string]interface{}{
|
||
"outSkuId": outSkuId,
|
||
"traceId": utils.GetUUID(),
|
||
}, nil, nil, nil)
|
||
if err == nil {
|
||
return int(utils.MustInterface2Int64(result.(map[string]interface{})["resultMsg"])), nil
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
func (a *API) UpdateSpuSaleAttr(outSpuId, saleAttrId, saleAttrName, saleAttrValueId, saleAttrValueName string) (err error) {
|
||
apiParams := map[string]interface{}{
|
||
"outSuperId": outSpuId,
|
||
"saleAttrId": saleAttrId,
|
||
"saleAttrValueId": saleAttrValueId,
|
||
}
|
||
if saleAttrName != "" {
|
||
apiParams["saleAttrName"] = saleAttrName
|
||
}
|
||
if saleAttrValueName != "" {
|
||
apiParams["saleAttrValueName"] = saleAttrValueName
|
||
}
|
||
_, err = a.AccessAPINoPage("pms/updateSpuSaleAttr", apiParams, nil, nil, 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"]),
|
||
ParentId: utils.MustInterface2Int64(mapData["pid"]),
|
||
Name: utils.Interface2String(mapData["shopCategoryName"]),
|
||
Level: int(utils.Interface2Int64WithDefault(mapData["shopCategoryLevel"], 0)),
|
||
Sort: int(utils.MustInterface2Int64(mapData["sort"])),
|
||
}
|
||
}
|
||
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 getSkuAttr(weight float32) (attr string) {
|
||
// attr = fmt.Sprintf("约%dg", int(math.Round(float64(weight*1000))))
|
||
// return attr
|
||
// }
|
||
|
||
func genAttrMapList(kgAttr string) (attrList []map[string]interface{}) {
|
||
return []map[string]interface{}{
|
||
map[string]interface{}{
|
||
"saleAttrName": "规格",
|
||
"saleAttrValueName": kgAttr,
|
||
},
|
||
}
|
||
}
|
||
|
||
func GetJdSkuIDFromError(err error) int64 {
|
||
if err2, ok := err.(*utils.ErrorWithCode); ok && err2.IntCode() == 11001 && strings.Index(err2.ErrMsg(), "商家skuId已存在") >= 0 {
|
||
searchResult := skuExistReg.FindStringSubmatch(err2.ErrMsg())
|
||
if searchResult != nil && len(searchResult[1]) > 0 {
|
||
return utils.Str2Int64(searchResult[1])
|
||
}
|
||
}
|
||
return 0
|
||
}
|