京东商城api

This commit is contained in:
苏尹岚
2020-05-08 16:05:10 +08:00
parent c638575d8b
commit 80d050b1c5
7 changed files with 285 additions and 2 deletions

View File

@@ -181,8 +181,8 @@ type WaybillReceiveParam struct {
// SiteType int `json:"siteType"` //否 无 站点类型
// SiteID int `json:"siteId"` //否 无 站点编码
// SiteName string `json:"siteName"` //否 无 站点名称
// ReceiveTel string `json:"receiveTel"` //否 无 收件人电话
// ReceiveMobile string `json:"receiveMobile"` //否 无 收件人手机号(收件人电话、手机至少有一个不为空)
ReceiveTel string `json:"receiveTel"` //否 无 收件人电话
ReceiveMobile string `json:"receiveMobile"` //否 无 收件人手机号(收件人电话、手机至少有一个不为空)
// Postcode string `json:"postcode"` //否 100000 收件人邮编长度6
PackageCount int `json:"packageCount"` //是 无 包裹数(大于0小于1000)
Weight int `json:"weight"` //是 2.5 重量(单位kg保留小数点后两位)

View File

@@ -0,0 +1,108 @@
package jdshopapi
import (
"crypto/md5"
"fmt"
"net/http"
"sort"
"strings"
"time"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
)
const (
prodURL = "https://api.jd.com/routerjson"
sigKey = "sign"
)
type API struct {
platformapi.APICookie
accessToken string
appKey string
appSecret string
client *http.Client
config *platformapi.APIConfig
}
type UniteResp struct {
Num int `json:"num"`
IsSuccess bool `json:"is_success"`
ErrorCode string `json:"error_code"`
ErrorMsgCn string `json:"error_msg_cn"`
ErrorMsg string `json:"error_msg"`
}
func New(accessToken, appKey, appSecret string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
accessToken: accessToken,
appKey: appKey,
appSecret: appSecret,
client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig,
}
}
func (a *API) signParam(params map[string]interface{}) (sig string) {
var valueList []string
for k, v := range params {
if k != sigKey {
if str := fmt.Sprint(v); str != "" {
valueList = append(valueList, fmt.Sprintf("%s%s", k, str))
}
}
}
sort.Sort(sort.StringSlice(valueList))
valueList = append(valueList, fmt.Sprintf("%s", a.appSecret))
var valueList2 = make([]string, len(valueList)+1)
at := copy(valueList2, valueList[:0])
at += copy(valueList2[at:], []string{a.appSecret})
copy(valueList2[at:], valueList[0:])
sig = strings.Join(valueList2, "")
binSig := md5.Sum([]byte(sig))
sig = fmt.Sprintf("%X", binSig)
return sig
}
func (a *API) AccessAPI(action string, url string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
params := make(map[string]interface{})
params["access_token"] = a.accessToken
params["app_key"] = a.appKey
params["timestamp"] = utils.Time2Str(time.Now())
params["method"] = action
params["v"] = "2.0"
params = utils.MergeMaps(params, bizParams)
signStr := a.signParam(params)
params["sign"] = signStr
fullURL := utils.GenerateGetURL(url, "", nil)
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(params).Encode()))
request.Header.Set("charset", "UTF-8")
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
return request
},
a.config,
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
if jsonResult1 == nil {
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
}
if err == nil {
if jsonResult1["error_response"] != nil {
errLevel = platformapi.ErrLevelGeneralFail
err = utils.NewErrorCode(jsonResult1["error_response"].(map[string]interface{})["zh_desc"].(string), jsonResult1["error_response"].(map[string]interface{})["code"].(string))
baseapi.SugarLogger.Debugf("jdeclp AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
}
retVal = jsonResult1
}
return errLevel, err
})
return retVal, err
}

View File

@@ -0,0 +1,19 @@
package jdshopapi
import (
"git.rosy.net.cn/baseapi"
"go.uber.org/zap"
)
var (
api *API
sugarLogger *zap.SugaredLogger
)
func init() {
logger, _ := zap.NewDevelopment()
sugarLogger = logger.Sugar()
baseapi.Init(sugarLogger)
api = New("da8db492e20149e494afaf5607e1d6654zgi", "E1D746D42474D5F1F1A10CECE75D99F6", "efa7e1d1a22640fa990e6cf164b28608")
api.SetCookie("thor", "80FAF09E9A09B6E618A68057BDFCFCB81C821714A15F3E8682FBAD9605C6284CE3D573A97D5021559891D214CDCCFA4A90F8254643B0A60E168F976FF8C3D2E5ACB0F3DB2ABFBC0A2E4EE6297EC49919CAE5CBBD6A686F1F7370B6ABD7AE8BE70DD216650EC9AAD79928DAC85CFA2D9BC581BA085F0D45C613A99F13F25AA3B24372930D5BB7CEBF685AF34698EBFD92")
}

View File

@@ -0,0 +1,52 @@
package jdshopapi
import (
"fmt"
"git.rosy.net.cn/baseapi/utils"
)
type FindShopCategoriesResult struct {
CID int64 `json:"cid"` //123456 分类编号
VenderID int `json:"vender_id"` //123456 商家编号
ShopID int `json:"shop_id"` // 123456 店铺编号
ParentCID int64 `json:"parent_cid"` //123456 父分类编号
OrderNo int `json:"order_no"` //1 分类排序
Name string `json:"name"` //分类1 分类名称
IsOpen bool `json:"is_open"` //false 是否展开子分类false不展开true展开
IsHomeShow bool `json:"is_home_show"` //false 是否在首页展示分类false前台不展示true前台展示
Status int `json:"status"` // 1 状态(1删除 1正常)
CreateTime int64 `json:"create_time"` //1394089643000 创建时间
ModifyTime int64 `json:"modify_time"` // 修改时间。每修改一次此值都会发生变化。
}
//查询商家所有的店内分类
//https://open.jd.com/home/home#/doc/api?apiCateId=88&apiId=2801&apiName=jingdong.vender.shopcategory.findShopCategoriesByVenderId
func (a *API) FindShopCategories() (findShopCategoriesResult []*FindShopCategoriesResult, err error) {
result, err := a.AccessAPI("jingdong.vender.shopcategory.findShopCategoriesByVenderId", prodURL, nil)
if err == nil {
utils.Map2StructByJson(result["jingdong_vender_shopcategory_findShopCategoriesByVenderId_responce"].(map[string]interface{})["shopCategoryResult"].(map[string]interface{})["shop_category_list"], &findShopCategoriesResult, false)
}
return findShopCategoriesResult, err
}
//删除店内分类
//https://open.jd.com/home/home#/doc/api?apiCateId=88&apiId=3031&apiName=jingdong.vender.shopcategory.deleteShopCategoryByVenderIdAndCid
func (a *API) DeleteShopCategory(cid int64) (uniteResp *UniteResp, err error) {
result, err := a.AccessAPI("jingdong.vender.shopcategory.deleteShopCategoryByVenderIdAndCid", prodURL, map[string]interface{}{
"cid": cid,
})
if err == nil {
utils.Map2StructByJson(result["jingdong_vender_shopcategory_deleteShopCategoryByVenderIdAndCid_responce"].(map[string]interface{})["shopCategoryResult"], &uniteResp, false)
if !uniteResp.IsSuccess {
return nil, fmt.Errorf(uniteResp.ErrorMsgCn)
}
}
return uniteResp, err
}
//京东商城发布商品(创建商品?)
//https://open.jd.com/home/home#/doc/api?apiCateId=48&apiId=1379&apiName=jingdong.ware.write.add
func (a *API) CreateSkuName() (err error) {
return err
}

View File

@@ -0,0 +1,23 @@
package jdshopapi
import (
"testing"
"git.rosy.net.cn/baseapi/utils"
)
func TestFindShopCategories(t *testing.T) {
result, err := api.FindShopCategories()
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}
func TestDeleteShopCategory(t *testing.T) {
result, err := api.DeleteShopCategory(14439186)
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}

View File

@@ -0,0 +1,61 @@
package jdshopapi
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
)
func (a *API) AccessStorePage(fullURL string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
if a.GetCookieCount() == 0 {
return nil, fmt.Errorf("需要设置Store Cookie才能使用此方法")
}
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodPost, fullURL, strings.NewReader(utils.Map2URLValues(bizParams).Encode()))
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
a.FillRequestCookies(request)
return request
},
a.config,
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
if jsonResult1 == nil {
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
}
if err == nil {
if jsonResult1["error_response"] != nil {
errLevel = platformapi.ErrLevelGeneralFail
err = utils.NewErrorCode(jsonResult1["error_response"].(map[string]interface{})["zh_desc"].(string), jsonResult1["error_response"].(map[string]interface{})["code"].(string))
baseapi.SugarLogger.Debugf("jdeclp AccessAPI failed, jsonResult1:%s", utils.Format4Output(jsonResult1, true))
}
retVal = jsonResult1
}
return errLevel, err
})
return retVal, err
}
type CreateShopCategoryParam struct {
HomeShow int `json:"homeShow"`
ID int `json:"id"`
Open string `json:"open"`
OrderNo int `json:"orderNo"`
ParentID string `json:"parentId"`
Title string `json:"title"`
Type int `json:"type"`
}
//京东商城创建或修改店内分类
//https://seller.shop.jd.com/vendershop/vendershop_shopCategory.action#
func (a *API) CreateShopCategory(createShopCategoryParam []*CreateShopCategoryParam) (err error) {
result, _ := json.MarshalIndent(createShopCategoryParam, "", "")
_, err = a.AccessStorePage("https://seller.shop.jd.com/vendershop/vendershop_doShopCategory.action", map[string]interface{}{
"categoryJson": string(result),
})
return err
}

View File

@@ -0,0 +1,20 @@
package jdshopapi
import (
"testing"
)
func TestCreateShopCategory(t *testing.T) {
var CreateShopCategoryParams = []*CreateShopCategoryParam{
&CreateShopCategoryParam{
HomeShow: 0,
ID: 0,
Open: "",
OrderNo: 0,
ParentID: "",
Title: "测试1",
Type: 3,
},
}
api.CreateShopCategory(CreateShopCategoryParams)
}