京东工业面向企业采购场景,和零售商品数据结构差异明显,除基础图文信息外,还包含物料参数、批量阶梯价、最小起订量、交期、资质证书等 B 端专属字段。很多常规示例只做简单返回打印,没有针对工业物料做数据规整,本文聚焦规格扁平化、阶梯报价拆分、异常字段兼容的落地思路,附带可直接调试的代码。 对接前需要在京东工业开放平台完成企业认证,创建应用并申请对应能力权限,拿到 app_key、app_secret 以及 access_token。工业物料的一大难点是多规格嵌套,同一个商品 ID 下会分出不同型号、材质、包装规格,批量价格不是固定单价,需要单独解析;同时部分非标物料会存在参数缺失、交期为空的情况,代码层要做容错兜底,避免整条数据解析失败。 下面是封装后的示例,内置签名生成、结果清洗、阶梯价拆解逻辑: 代码核心不是简单请求,而是把嵌套的规格、阶梯报价抽成平层结构,方便入库给采购系统使用。工业场景里,阶梯价是高频踩坑点:不同采购数量对应不同单价,不能直接取展示价作为结算价。另外,时间戳要和服务端时差控制在 3 分钟内,否则签名校验失败。 落地过程还有几个要点:第一,做好频率控制,B 端能力有 QPS 限制,批量同步时增加随机间隔;第二,区分现货和定制物料,交期字段为空代表非标定制,业务上要标记;第三,参数属性存在多语言、特殊单位,入库前统一单位,避免统计混乱;第四,仅使用已申请权限的能力,遵守平台协议,不做无授权的高频轮询。 这套方案适合企业物料寻源、内部比价系统、库存前置同步场景,相比通用零售商品拉取方案,更贴合工业采购的业务属性,清洗后的数据可以直接对接采购中台,省去二次解析的开发成本。
import requests
import time
import hmac
import hashlib
import json
class JdIndustryDetail:
def __init__(self, app_key, app_secret, token):
self.app_key = app_key
self.app_secret = app_secret
self.token = token
self.url = "https://api.jd.com/routerjson"
def build_sign(self, param_dict):
sorted_keys = sorted([k for k, v in param_dict.items() if v])
raw = "".join([f"{k}{param_dict[k]}" for k in sorted_keys])
raw = self.app_secret + raw + self.app_secret
sign = hmac.new(self.app_secret.encode(), raw.encode(), hashlib.md5).hexdigest().upper()
return sign
def get_detail(self, sku_id):
params = {
"app_key": self.app_key,
"access_token": self.token,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"v": "2.0",
"method": "industry.goods.detail.get",
"skuId": sku_id
}
params["sign"] = self.build_sign(params)
resp = requests.post(self.url, data=params, timeout=10)
res_json = resp.json()
if res_json.get("code") != 0:
return {"status": False, "msg": res_json.get("msg"), "data": None}
raw_data = res_json.get("result", {})
flat_data = {
"skuId": raw_data.get("skuId"),
"title": raw_data.get("title"),
"brand": raw_data.get("brandName"),
"minOrder": raw_data.get("minOrder"),
"deliveryDay": raw_data.get("deliveryDay"),
"specList": raw_data.get("specInfo", []),
"ladderPrice": raw_data.get("ladderPriceList", []),
"attr": raw_data.get("attrInfo", {})
}
return {"status": True, "data": flat_data}
if __name__ == "__main__":
client = JdIndustryDetail("你的key", "你的secret", "你的token")
ret = client.get_detail("100xxxxxx")
print(json.dumps(ret, ensure_ascii=False, indent=2))