[特殊字符]《京东JOS宙斯迁移实录:jingdong.ware.get → jingdong.ware.read.get 平滑切(2026版)》(附Python源码)
2026/7/18 2:19:48 网站建设 项目流程

🔄《京东JOS宙斯迁移实录:jingdong.ware.getjingdong.ware.read.get平滑切(2026版)》(附Python源码)

京东宙斯(JOS)在2024~2026年间持续推进接口标准化,老接口jingdong.ware.get(及别名360buy.ware.get)已进入维护期,新应用不再支持申请,官方推荐统一迁移至jingdong.ware.read.get(只读商品读取接口,权限更清晰、支持SKU快照字段)。

迁移只需改method + 微调fields,网关/签名/AccessToken完全不变,下面给你一份可直接执行的平滑切换实录。


一、老 vs 新接口对照(一目了然)

维度

老接口(即将下线)

新接口(推荐)

Method

jingdong.ware.get/360buy.ware.get

jingdong.ware.read.get

网关

https://api.jd.com/routerjson

完全相同

签名算法

MD5(AppSecret+KV_ASCII+AppSecret) 秒级timestamp

完全相同(一行不改)

必传参数

wareId,fields

完全相同wareId,fields

返回根节点

jingdong_ware_get_response.ware

jingdong_ware_read_get_response.ware

SKU库存可见

需传seller token

相同(传seller token可看stockNuminskus_json

权限申请

老入口(已关闭新申请)

应用→接口权限→申请jingdong.ware.read.get(即时生效)

迁移量:代码中只改method 字符串​ +fields 补全skus_json,stock_num,其余(Client/签名/网关/token)一行不动。


二、Python:老接口 vs 新接口调用对比 + 兼容封装

# jd_ware_migration_2026.py """ 京东JOS宙斯迁移实录 old: jingdong.ware.get → new: jingdong.ware.read.get 同一个 JdClient 复用,仅 method + fields 不同 支持 沙箱/生产 切换 """ import hashlib import json import requests import time from typing import Dict, Optional 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex class JdWareClient: """京东JOS商品接口客户端(兼容新旧两套)""" GW_PROD = "https://api.jd.com/routerjson" GW_SANDBOX = "https://api.sandbox.jd.com/routerjson" def __init__(self, app_key: str, app_secret: str, sandbox: bool = False): self.ak = app_key self.ask = app_secret self.gw = self.GW_SANDBOX if sandbox else self.GW_PROD # ───── JOS MD5签名(秒级timestamp,紧凑JSON)───── def _sign(self, params: Dict) -> str: filt = sorted( (k, v) for k, v in params.items() if k != "sign" and v is not None and str(v).strip() != "" ) qs = "".join(f"{k}{v}" for k, v in filt) raw = f"{self.ask}{qs}{self.ask}" return hashlib.md5(raw.encode("utf-8")).hexdigest().upper() def _call(self, method: str, biz: Dict, token: str = None) -> Dict: p = { "app_key": self.ak, "method": method, "timestamp": str(int(time.time())), # ← 秒级!不是毫秒 "format": "json", "v": "2.0", "sign_method": "md5", "360buy_param_json": json.dumps(biz, ensure_ascii=False, separators=(',', ':')) } if token: p["access_token"] = token p["sign"] = self._sign(p) r = requests.post(self.gw, data=p, timeout=15) r.raise_for_status() d = r.json() # 提取响应(兼容新旧method对应的resp_key) resp_key = method.replace(".", "_") + "_response" if resp_key not in d: for k in d: if k.endswith("_response"): resp_key = k break data = d.get(resp_key, d) if "error_response" in str(data): err = d.get(resp_key, {}).get("error_response") or d.get("error_response") if err: code = str(err.get("code", "")) zh = err.get("zh_desc") or err.get("en_desc") sub = err.get("sub_code", "") if "no permission" in zh: raise PermissionError( f"❌ 无权限:确认已申请 {method} 接口,订单类需传卖家AccessToken\n原始: {zh}" ) raise Exception(f"JOS[{code}]: {zh} sub={sub}") raise Exception(f"JOS error: {d}") return data # ─── 老接口(不推荐,仅作对比/过渡期兼容)─── def get_ware_old(self, ware_id: str, fields: str = None, token: str = None) -> Dict: fields = fields or ( "ware_id,title,price,jd_price,stock_num,skus_json,image_path" ) return self._call( "jingdong.ware.get", # ← 老 method {"wareId": ware_id, "fields": fields}, token ).get("ware", {}) # ─── ✅ 新接口(推荐迁移目标)─── def get_ware_new(self, ware_id: str, fields: str = None, token: str = None) -> Dict: fields = fields or ( "ware_id,title,brand_name,cid,category_name," "price,jd_price,market_price,stock_num," "skus_json,image_path,desc,outer_id,approve_status" ) return self._call( "jingdong.ware.read.get", # ← 新 method {"wareId": ware_id, "fields": fields}, token ).get("ware", {}) # ========================================================= # 使用示例:平滑切换 # ========================================================= if __name__ == "__main__": client = JdWareClient( app_key="YOUR_JD_APP_KEY", app_secret="YOUR_JD_APP_SECRET", sandbox=False # 沙箱测试 = True ) WARE_ID = "100012345678" # ← 替换真实 wareId SELLER_TOKEN = None # 查自己店铺SKU库存需传卖家AccessToken try: # ★ 迁移后只用这一行 ★ ware = client.get_ware_new(WARE_ID, token=SELLER_TOKEN) print("✅ [新接口] 商品标题:", ware.get("title")) print(" 京东价:", ware.get("jd_price")) print(" SPU库存:", ware.get("stock_num")) # skus_json 解析(查自己店铺时才有真实库存) import json as _j skus_raw = ware.get("skus_json") or "" if skus_raw: skus = _j.loads(skus_raw) print(f" SKU数: {len(skus)}") for s in skus[:3]: print(f" skuId:{s.get('skuId')} 价:{s.get('jdPrice')} " f"库:{s.get('stockNum')} 商家码:{s.get('outerId','')}") print("\n→ 迁移完成!仅需改 method='jingdong.ware.read.get' + fields补skus_json") except PermissionError as pe: print(pe) except Exception as e: print("❌", e) print("→ 确认: AppKey/Secret正确、接口已申请、wareId有效")

三、迁移 Checklist(照着做,5分钟切完)

  1. 应用后台申请新权限

    → 接口权限 → 勾选jingdong.ware.read.get→ 提交(通常即时生效)

  2. 代码改动(极小)

    - method = "jingdong.ware.get" + method = "jingdong.ware.read.get" - fields = "ware_id,title,price" + fields = "ware_id,title,price,jd_price,stock_num,skus_json,image_path"

    wareId参数名不变(驼峰,同老接口)

  3. 回归测试(5分钟)

    • 沙箱调通签名 ✓

    • 生产比对新旧返回字段一致性(标题/价格/SKU数应一致)

    • 自家店铺查 SKU 库存需传access_token(同旧逻辑)

  4. 下线老调用

    确认所有环境切新 method 后,删除get_ware_old()分支


四、避坑清单

现象

解决

新接口返回 403

未申请jingdong.ware.read.get

应用→接口权限→申请

skus_json

公开查询别人商品 / 未传 token

查自己店铺商品须传卖家 AccessToken

老代码wareId写成ware_id

部分SDK自动映射,推荐用wareId(首字母大写)

与文档保持一致

返回结构 key 变

jingdong_ware_get_responsejingdong_ware_read_get_response

解析用.get("ware")不依赖外层 key

timestamp毫秒

Invalid Timestamp

JOS用秒级int(time.time())

沙箱返回 mock 数据

正常,沙箱只验签不返真数据

切生产验证


五、面试/方案一句话

京东JOS宙斯迁移:老接口jingdong.ware.get→ 新接口jingdong.ware.read.get只改 method 字符串 + fields 补skus_json,stock_num,网关/签名/AccessToken 完全不变;应用需申请新接口权限,返回值结构外层key变但内层ware节点字段一致,解析取.get("ware")即兼容,5分钟平滑切换。

需要我补京东订单增量同步(jingdong.pop.order.search) 或 库存快照定时校正脚本​ 的完整迁移示例吗?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询