Files
baseapi/platformapi/tiktok_shop/tiktok_api/sku.go
邹宗楠 b2edd80ed4 1
2022-12-30 15:00:44 +08:00

556 lines
19 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 tiktok_api
import (
"errors"
brand_list_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/brand_list/request"
order_batchDecrypt_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/order_batchDecrypt/request"
order_batchSensitive_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/order_batchSensitive/request"
product_GetRecommendCategory_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_GetRecommendCategory/request"
product_addV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_addV2/request"
product_addV2_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_addV2/response"
product_auditList_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_auditList/request"
product_auditList_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_auditList/response"
product_del_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_del/request"
product_detail_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_detail/request"
product_detail_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_detail/response"
product_detail_request_out "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_detail_out_productId/request"
product_editV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_editV2/request"
product_editV2_commit_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_editV2_commit/request"
product_getCatePropertyV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_getCatePropertyV2/request"
product_getCatePropertyV2_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_getCatePropertyV2/response"
product_getProductUpdateRule_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_getProductUpdateRule/request"
product_listV2_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_listV2/request"
product_listV2_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_listV2/response"
product_setOffline_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/product_setOffline/request"
shop_getShopCategory_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/shop_getShopCategory/request"
sku_editPrice_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/sku_editPrice/request"
sku_syncStock_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/sku_syncStock/request"
sku_syncStockBatch_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/sku_syncStockBatch/request"
superm_product_batchApplyStoreProductPrice_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/superm_product_batchApplyStoreProductPrice/request"
superm_product_batchRedistributeStoreProduct_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/superm_product_batchRedistributeStoreProduct/request"
superm_product_createSubProduct_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/superm_product_createSubProduct/request"
superm_product_launchProduct_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/superm_product_launchProduct/request"
"git.rosy.net.cn/jx-callback/globals"
"strings"
)
// UpdateSkuStock
// 1、支持修改普通库存,区域库存,阶梯库存
// 2、支持增量更新当incremental=true时idempotent_id字段参数必传。例原商品库存是10个接口传入5个执行成功商品库存是15个。
// 3、支持全量更新。例原商品库存是10个接口传入5个执行成功商品库存是5个。
// 4、可以设置库存为0
// 5、超市小时达店铺类型更新库存out_warehouse_id= store_id门店id表示更新门店商品库存。
func (a *API) UpdateSkuStock(param *sku_syncStock_request.SkuSyncStockParam) error {
request := sku_syncStock_request.New()
request.Param = param
resp, err := request.Execute(a.accessTokenObj)
if err != nil {
return err
}
if resp.Code != RequestSuccessCode {
return errors.New(resp.Msg)
}
return nil
}
// GetShopCategory 获取商品类目
// 请一定使用最小层级类目id发布商品或更新商品。
// 接口使用注意点:
// 1、第一次请求cid=0获取所有一级类目
// 2、先判断enable=true如果enable=false表示该类目已经失效请勿使用。
// 3、循环获取最小层级类目id方式再判断is_leaf=true或false。is_leaf=true表示是叶子节点最小层级类目id。is_leaf=false表示不是子节点请求参数cid=上一次响应参数id直到获取最小层级类目id。
func (a *API) GetShopCategory(cid int64) ([]*RetailCategoryInfo, error) {
// 如果cid为0,则获取所有的分类,如果cid不为0,则获取该分类下面的所有子分类
request := shop_getShopCategory_request.New()
param := request.GetParams()
param.Cid = cid
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return nil, err
}
if result.Code != RequestSuccessCode {
return nil, errors.New(result.SubMsg)
}
categoryAll := make([]*RetailCategoryInfo, 0, 0)
for i := 0; i < len(result.Data); i++ {
if result.Data[i].Enable != true { // 失效了
continue
}
if result.Data[i].IsLeaf == false {
categoryAll = append(categoryAll, &RetailCategoryInfo{
DataItem: result.Data[i],
Children: make([]*RetailCategoryInfo, 0, 0),
})
parentNode, _ := a.GetShopCategory(result.Data[i].Id)
categoryAll[i].Children = append(categoryAll[i].Children, parentNode...)
} else {
node := RetailCategoryInfo{
DataItem: result.Data[i],
Children: nil,
}
categoryAll = append(categoryAll, &node)
}
}
return categoryAll, nil
}
// GetCatePropertyV2 根据商品分类获取对应的属性列表
// 参数为最终的子节点id下面再无子节点
func (a *API) GetCatePropertyV2(categoryLeftId int64) (*product_getCatePropertyV2_response.ProductGetCatePropertyV2Response, error) {
request := product_getCatePropertyV2_request.New()
param := request.GetParams()
param.CategoryLeafId = categoryLeftId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return nil, err
}
if result.Code != RequestSuccessCode {
return nil, errors.New(result.SubMsg)
}
return result, nil
}
// CreateStoreCommodity (新增总部商品)
func (a *API) CreateStoreCommodity(skuParam *product_addV2_request.ProductAddV2Param) (*product_addV2_response.ProductAddV2Data, error) {
request := product_addV2_request.New()
request.Param = skuParam
result, err := request.Execute(a.accessTokenObj)
if err != nil {
globals.SugarLogger.Debugf("======CreateStoreCommodity logid: %s,%d,%d", result.LogId, skuParam.MainProductId, err.Error())
return nil, err
}
if result.Code != RequestSuccessCode {
return nil, errors.New(result.SubMsg)
}
return result.Data, nil
}
// SyncStockBatch 库存批量同步
func (a *API) SyncStockBatch(param *sku_syncStockBatch_request.SkuSyncStockBatchParam) error {
request := sku_syncStockBatch_request.New()
request.Param = param
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return err
}
if result.Code != RequestSuccessCode {
return errors.New(result.SubMsg)
}
return nil
}
// EditStoreCommodity 编辑商品
func (a *API) EditStoreCommodity(sku *product_editV2_request.ProductEditV2Param) error {
request := product_editV2_request.New()
request.Param = sku
result, err := request.Execute(a.accessTokenObj)
if err != nil {
globals.SugarLogger.Debugf("LogId %s ,err %s", result.LogId, err.Error())
return err
}
if result.Code != RequestSuccessCode {
return errors.New(result.SubMsg)
}
return nil
}
// EditStoreCommodityCommit 上架商品
func (a *API) EditStoreCommodityCommit(sku *product_editV2_commit_request.ProductEditV2Param2) error {
request := product_editV2_commit_request.New()
request.Param = sku
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return err
}
if result.Code != RequestSuccessCode {
return errors.New(result.SubMsg)
}
return nil
}
// DeleteStoreCommodity 删除商品
func (a *API) DeleteStoreCommodity(productId int64) error {
request := product_del_request.New()
param := request.GetParams()
param.ProductId = productId
param.DeleteForever = true
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return err
}
if result.Code != RequestSuccessCode {
return errors.New(result.SubMsg)
}
return nil
}
// ProductSetOffline 商品上下架
func (a *API) ProductSetOffline(productId int64) error {
request := product_setOffline_request.New()
param := request.GetParams()
param.ProductId = productId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return err
}
if result.Code != RequestSuccessCode {
return errors.New(result.SubMsg)
}
return nil
}
// GetSkuDetail 查询单个商品详情(这个只有抖店平台商品id有效)
func (a *API) GetSkuDetail(productId, outProductId string) (*product_detail_response.ProductDetailData, error) {
request := product_detail_request.New()
param := request.GetParams()
if productId != "" {
param.ProductId = productId
}
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return nil, err
}
if strings.Contains(result.SubMsg, "未找到或商品已删除") {
return nil, nil
}
if result.Code != RequestSuccessCode {
return nil, errors.New(result.SubMsg)
}
if result.Data.Status == 2 {
return nil, nil
}
return result.Data, nil
}
// GetSkuDetailLocalID 查询单个商品详情(这个只有京西平台商品id有效,查询到的商品可能为子商品也可能为主商品,主商品删除时,子商品和主商品状态不一致)
func (a *API) GetSkuDetailLocalID(productId, outProductId string) (*product_detail_response.ProductDetailData, error) {
request := product_detail_request_out.New()
param := request.GetParams()
if outProductId != "" {
param.OutProductId = outProductId
}
result, err := request.Execute(a.accessTokenObj)
if strings.Contains(result.SubMsg, "未找到或商品已删除") {
return nil, nil
}
if err != nil {
return nil, err
}
if result.Code != RequestSuccessCode {
return nil, errors.New(result.SubMsg)
}
if result.Data.Status == 2 {
return nil, nil
}
return result.Data, nil
}
// GetSkuDetailList 批量获取商品列表
func (a *API) GetSkuDetailList(param *product_listV2_request.ProductListV2Param) (*product_listV2_response.ProductListV2Data, error) {
request := product_listV2_request.New()
request.Param = param
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return nil, err
}
if result.Code != RequestSuccessCode {
return nil, errors.New(result.SubMsg)
}
return result.Data, nil
}
// EditPrice 编辑商品价格
func (a *API) EditPrice(skuPrice *sku_editPrice_request.SkuEditPriceParam) error {
request := sku_editPrice_request.New()
request.Param = skuPrice
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return err
}
if result.Code != RequestSuccessCode {
return errors.New(result.SubMsg)
}
return nil
}
// GetSkuBrand 获取商品所属品牌
func (a *API) GetSkuBrand(categoryId int64) (int64, error) {
request := brand_list_request.New()
request.Param.CategoryId = categoryId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return 0, err
}
if result.Code != RequestSuccessCode {
return 0, errors.New(result.SubMsg)
}
if result.Data == nil || len(result.Data.AuthBrandList) == 0 {
return 596120136, nil // 无品牌默认值
}
return result.Data.AuthBrandList[0].BrandId, nil
}
// OrderUserInfoDecrypt 用户信息解密
func (a *API) OrderUserInfoDecrypt(orderId, name, tel, address string) (string, string, string, error) {
request := order_batchDecrypt_request.New()
cipherInfos := make([]order_batchDecrypt_request.CipherInfosItem, 0, 0)
for i := 1; i <= 3; i++ {
cipher := order_batchDecrypt_request.CipherInfosItem{}
cipher.AuthId = orderId
switch i {
case 1: // 姓名
cipher.CipherText = name
cipherInfos = append(cipherInfos, cipher)
case 2: // 手机号
cipher.CipherText = tel
cipherInfos = append(cipherInfos, cipher)
case 3: // 地址
cipher.CipherText = address
cipherInfos = append(cipherInfos, cipher)
}
}
request.Param.CipherInfos = cipherInfos
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return "", "", "", err
}
if result.Code != RequestSuccessCode {
return "", "", "", errors.New(result.SubCode)
}
var (
userName, userTel, userAddress = "", "", ""
)
for _, v := range result.Data.DecryptInfos {
if v.CipherText != "" && v.CipherText == name {
userName = v.DecryptText
}
if v.CipherText != "" && v.CipherText == tel {
userTel = v.DecryptText
}
if v.CipherText != "" && v.CipherText == address {
userAddress = v.DecryptText
}
}
return userName, userTel, userAddress, err
}
// OrderUserInfoSensitive 用户信息脱敏
func (a *API) OrderUserInfoSensitive(orderId, name, tel, address string) {
request := order_batchSensitive_request.New()
paramItems := make([]order_batchSensitive_request.CipherInfosItem, 0, 0)
for i := 0; i < 3; i++ {
cipher := order_batchSensitive_request.CipherInfosItem{}
cipher.AuthId = orderId
switch i {
case 1: // 姓名
cipher.CipherText = name
paramItems = append(paramItems, cipher)
case 2: // 手机号
cipher.CipherText = tel
paramItems = append(paramItems, cipher)
case 3: // 地址
cipher.CipherText = address
paramItems = append(paramItems, cipher)
}
}
request.Param.CipherInfos = paramItems
request.Execute(a.accessTokenObj)
}
// GetProductUpdateRule 查询分类是否支持七天无理由退货
func (a *API) GetProductUpdateRule(categoryId int64) bool {
request := product_getProductUpdateRule_request.New()
param := request.GetParams()
param.CategoryId = categoryId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return false
}
if result.Code != RequestSuccessCode {
return false
}
return result.Data.AfterSaleRule.SupplyDayReturnRule.Enable
}
// GetProductUpdateRule2 查询分类是否支持七天无理由退货
func (a *API) GetProductUpdateRule2(categoryId int64) bool {
request := product_getProductUpdateRule_request.New()
param := request.GetParams()
param.CategoryId = categoryId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return false
}
if result.Code != RequestSuccessCode {
return false
}
return result.Data.AfterSaleRule.SupplyDayReturnRule.Enable
}
// GetProductAuditList 获取商品的审核记录
func (a *API) GetProductAuditList(page, pageSize, status int64) ([]product_auditList_response.RecordsItem, int64, error) {
request := product_auditList_request.New()
request.Param.PublishStatus = status
request.Param.Page = page
request.Param.Size = pageSize
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return nil, 0, err
}
if result.Code != RequestSuccessCode {
return nil, 0, errors.New(result.SubMsg)
}
return result.Data.Records, result.Data.Total, nil
}
// GetRecommendCategory 根据图片预测商品类目,优先四级>三级>二级>1级
func (a *API) GetRecommendCategory(picParams []string) (int64, error) {
if len(picParams) == 0 {
return 0, errors.New("抖音根据图片预测分类,图片不能为空")
}
request := product_GetRecommendCategory_request.New()
request.Param.Scene = "smart_publish" // 根据图片获取分类属性
picList := make([]product_GetRecommendCategory_request.PicItem, 0, 0)
for _, v := range picParams {
picList = append(picList, product_GetRecommendCategory_request.PicItem{Url: v})
}
request.Param.Pic = picList
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return 0, err
}
if result.Code != RequestSuccessCode {
return 0, errors.New(result.SubMsg)
}
if len(result.Data.CategoryDetails) == 0 {
return 0, errors.New("抖音根据图片获取分类,返回值为0")
}
var firstCid int64
var secondCid int64
var thirdCid int64
var fourthCid int64
if result.Data.CategoryDetails[0].CategoryDetail.FirstCid != 0 {
firstCid = result.Data.CategoryDetails[0].CategoryDetail.FirstCid
}
if result.Data.CategoryDetails[0].CategoryDetail.SecondCid != 0 {
secondCid = result.Data.CategoryDetails[0].CategoryDetail.SecondCid
}
if result.Data.CategoryDetails[0].CategoryDetail.ThirdCid != 0 {
thirdCid = result.Data.CategoryDetails[0].CategoryDetail.ThirdCid
}
if result.Data.CategoryDetails[0].CategoryDetail.FourthCid != 0 {
fourthCid = result.Data.CategoryDetails[0].CategoryDetail.FourthCid
}
if fourthCid != 0 {
return fourthCid, nil
}
if thirdCid != 0 {
return thirdCid, nil
}
if secondCid != 0 {
return secondCid, nil
}
if firstCid != 0 {
return firstCid, nil
}
return 0, errors.New("抖音获取推荐分类异常")
}
/*--------------------------------方案二 将住上铺平铺到所有门店店中,不在使用子商品------------------------------------------------------------------------------------*/
// CreateSubProduct 基于店铺主品创建门店子品 (同步创建)
func (a *API) CreateSubProduct(mainProductId int64, storeId int64) (int64, error) {
request := superm_product_createSubProduct_request.New()
request.Param.MainProductId = mainProductId
request.Param.StoreId = storeId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return 0, err
}
if result.Code != RequestSuccessCode {
return 0, errors.New(result.SubMsg)
}
return result.Data.SubProductId, nil
}
// BatchRedistributeStoreProduct 重新分配店铺主品对应的门店子品 (异步执行)
func (a *API) BatchRedistributeStoreProduct(param *superm_product_batchRedistributeStoreProduct_request.TaskParams) (int64, error) {
request := superm_product_batchRedistributeStoreProduct_request.New()
request.Param.TaskParams = param
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return 0, err
}
if result.Code != RequestSuccessCode {
return 0, err
}
return result.Data.RootTaskId, nil
}
// BatchApplyStoreProductPrice 同步主商品价格到子商品
func (a *API) BatchApplyStoreProductPrice(mainProductId int64) (int64, error) {
request := superm_product_batchApplyStoreProductPrice_request.New()
request.Param.TaskParams.MainProductId = mainProductId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return 0, err
}
if result.Code != RequestSuccessCode {
return 0, errors.New(result.SubMsg)
}
return result.Data.RootTaskId, nil
}
// LaunchProduct 上架商品 ,支持主商品和子商品上架
func (a *API) LaunchProduct(productId int64) error {
request := superm_product_launchProduct_request.New()
request.Param.ProductId = productId
result, err := request.Execute(a.accessTokenObj)
if err != nil {
return err
}
if result.Code != RequestSuccessCode {
return errors.New(result.SubMsg)
}
return nil
}