当前位置: 首页 > news >正文

[特殊字符]《京东开放平台JOS接入全指南:注册、AppKey、OAuth2.0授权与沙箱调试(2026最新)》(附Python源码)

🟦《京东开放平台JOS接入全指南:注册、AppKey、OAuth2.0授权与沙箱调试(2026最新)》(附Python源码)

京东开放平台(JOS = JD Open Service)是京东POP商家/ISV对接商品、订单、物流、售后、仓储的官方渠道。爬虫不可取,JOS免费额度内零成本,下面按实际接入顺序给你完整说明 + Python签名/授权/沙箱调用代码。


一、接入四步曲(先记这个)

① 注册京东商家/开发者 → 创建JOS应用(自用/ISV) https://jos.jd.com → 获取 AppKey + AppSecret(别名AppPassword) ② 申请接口权限(商品/订单/物流…) ③ OAuth2.0 授权(店铺卖家登录→code→access_token/refresh_token) *只有订单/私有店铺数据需要 token,商品公开查询可不传* ④ 沙箱调通签名 → 切生产网关正式同步

二、创建应用 & 获取 AppKey / AppSecret

  1. 登录 京东开放平台→控制台 → 创建应用

  2. 应用类型:

    • 商家自用应用(推荐,绑定自己店铺)→ 免ISV入驻

    • ISV应用 → 需软服中心入驻、商家授权托管

  3. 应用审核通过后,详情页复制:

    • App Key(也叫app_key/client_id

    • App Secret(也叫app_password/client_secret

  4. 接口管理 → 申请权限:勾选所需(如jingdong.pop.order.searchjingdong.ware.sku.readjingdong.etms.trace.get等)

⚠️ 京东JOS签名用360buy/jd参数名规范,详见下文。


三、JOS 签名算法(必须掌握)

京东JOS使用MD5签名,规则:

  1. 收集所有业务参数 + 公共参数app_key,method,timestamp,v,sign_method,若有access_token也参入)

    • 剔除:signfile字段、值为空(""/None)

  2. 按参数名 ASCII 升序排序

  3. 拼接key1+value1+key2+value2+...(无=&

  4. 首尾拼 AppSecretAppSecret + 拼接串 + AppSecret

  5. MD5 → 大写

待签名 = APP_SECRET + app_keyxxxformatjsonmethodjd.xxxv2.0timestampxxx + APP_SECRET sign = MD5(待签名).upper()

📌 京东参数名多为jd.xxxmethod值如jingdong.pop.order.searchtimestamp秒级(10位),不同于TOP的毫秒!


四、OAuth2.0 卖家授权获取 AccessToken

订单/私有店铺接口需卖家账号授权

① 引导卖家访问: https://auth.jd.com/oauth2/toLogin.action ?response_type=code &client_id=YOUR_APP_KEY &redirect_uri=URLENCODE(你在应用配置的回调地址) &state=erp_jd ② 回调 → redirect_uri?code=xxx&state=erp_jd ③ 换 token: POST https://auth.jd.com/oauth2/accessToken grant_type=authorization_code client_id=APP_KEY client_secret=APP_SECRET code=xxx redirect_uri=同上 → {access_token, refresh_token, expires_in, uid, user_nick}

五、Python完整封装(签名 + OAuth + 沙箱/生产调用)

# jd_jos_client.py """ 京东开放平台(JOS) API Client — 2026版 网关: 生产: https://api.jd.com/routerjson 沙箱: https://api.sandbox.jd.com/routerjson (部分接口支持) 签名: MD5(AppSecret + KV_sorted + AppSecret) → upper timestamp: 秒级(10位) """ import hashlib import time import requests import urllib.parse from typing import Dict, Optional from datetime import datetime, timedelta # 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex class JdJosClient: PROD = "https://api.jd.com/routerjson" SANDBOX = "https://api.sandbox.jd.com/routerjson" def __init__(self, app_key: str, app_secret: str, sandbox: bool = False): self.ak = app_key self.as_ = app_secret self.gw = self.SANDBOX if sandbox else self.PROD # ─────────────── 签名 ─────────────── def _sign(self, params: Dict) -> str: filt = sorted((k, v) for k, v in params.items() if v is not None and str(v).strip() != '' and k != 'sign') qs = ''.join(f"{k}{v}" for k, v in filt) raw = f"{self.as_}{qs}{self.as_}" return hashlib.md5(raw.encode('utf-8')).hexdigest().upper() # ─────────────── 通用调用 ─────────────── def call(self, method: str, biz: Dict, access_token: str = None) -> Dict: """ method: 如 'jingdong.pop.order.search' biz: 业务参数字典(会变成 JSON 串放 '360buy_param_json') """ api_params = { "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) } if access_token: api_params["access_token"] = access_token api_params["sign"] = self._sign(api_params) # JOS推荐 POST x-www-form-urlencoded r = requests.post(self.gw, data=api_params, timeout=15) r.raise_for_status() d = r.json() # JOS返回结构: {method_response: {error_response / xxx_response}} resp_key = method.replace(".", "_") + "_response" if resp_key not in d: # 有些接口直接用 method名作为key 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") if resp_key in d else d.get("error_response") if err: raise Exception(f"JOS Err[{err.get('code')}]: {err.get('zh_desc') or err.get('en_desc')} " f"sub:{err.get('sub_code')}") raise Exception(f"JOS 未知错误: {d}") return data # ─────────────── 示例:商品详情(公开可不传token)──────── def get_sku_detail(self, sku_id: str) -> Dict: return self.call( "jingdong.ware.sku.read.findSkuById", {"skuId": sku_id, "fields": "skuId,wareId,title,price,jdPrice,stockNum"} ).get("skuReadResult", {}).get("skuEntity", {}) # ─────────────── 示例:订单列表(需token)──────── def list_orders(self, access_token: str, start_modified: str, end_modified: str, page=1, page_size=50) -> Dict: return self.call( "jingdong.pop.order.search", { "start_modified": start_modified, "end_modified": end_modified, "order_state": "WAIT_SELLER_STOCK_OUT", # 已付款待发货示例 "page": page, "page_size": min(page_size, 100) }, access_token=access_token ).get("popOrderSearch", {}).get("orderSearch", {}) # ─────────────── 物流轨迹(需token)──────── def get_trace(self, access_token: str, waybill_code: str, customer_code: str = None) -> Dict: biz = {"waybillCode": waybill_code} if customer_code: biz["customerCode"] = customer_code return self.call("jingdong.etms.trace.get", biz, access_token ).get("etmsTraceGetResponse", {}).get("traceApiResult", {}) # ── OAuth 换 token 辅助 ── def jd_oauth_exchange(app_key, app_secret, code, redirect_uri): r = requests.post("https://auth.jd.com/oauth2/accessToken", data={ "grant_type": "authorization_code", "client_id": app_key, "client_secret": app_secret, "code": code, "redirect_uri": redirect_uri, "state": "" }, timeout=15) r.raise_for_status() return r.json() # access_token / refresh_token / expires_in / uid def json_dumps(d: Dict) -> str: import json return json.dumps(d, ensure_ascii=False, separators=(',', ':')) # ========================================================= # 使用示例 # ========================================================= if __name__ == "__main__": client = JdJosClient( app_key="YOUR_JD_APP_KEY", app_secret="YOUR_JD_APP_SECRET", sandbox=True # 生产切 False ) try: # ① 公开商品(沙箱返回mock,生产需真实skuId) sku = client.get_sku_detail("100012345678") print("✅ SKU查询签名通!title=", sku.get("title")) # ② 订单(需卖家AccessToken,沙箱多返回空) # from datetime import datetime,timedelta # now = datetime.now() # start = (now - timedelta(minutes=30)).strftime("%Y-%m-%d %H:%M:%S") # end = now.strftime("%Y-%m-%d %H:%M:%S") # orders = client.list_orders("SELLER_ACCESS_TOKEN", start, end) # print("订单数:", orders.get("orderTotal")) except Exception as e: print("❌", e)

六、沙箱 vs 生产注意点

项目

沙箱

生产

网关

api.sandbox.jd.com/routerjson

api.jd.com/routerjson

数据

Mock(商品ID原样回显/空订单)

真实店铺数据

订单接口

返回空列表正常

需卖家AccessToken + 申请权限

AppKey

同一应用Key

同一应用Key

淘宝客类

不适用

京东无淘宝客API

沙箱能调通签名+JSON结构 = 生产一定通,返回空不报错属预期。


七、高频避坑

现象

解决

timestamp 毫秒

Invalid Timestamp

JOS用秒级int(time.time()),不是毫秒!

360buy_param_json格式错

Missing Required Parameter

值是紧凑JSON字符串(无空格),中文不URL编码但 ensure_ascii=False

订单403

个人应用/未申请

创建商家自用应用​ + 申请jingdong.pop.order.search+ 卖家OAuth

session传买家token

空/403

须是店铺卖家授权换的 access_token

sign mismatch

参入 sign / 空值参入

严格过滤空值+剔除sign再排序

沙箱空订单慌

正常,切生产验证


八、面试/方案一句话

京东JOS接入 = 创建商家自用应用拿AppKey/Secret → MD5签名(参按ASCII升序拼AppSecret+KV+AppSecret,秒级timestamp) →360buy_param_json放业务JSON → 订单类接口需卖家OAuth AccessToken;沙箱验签通后切生产网关取真实数据,基础接口有免费额度。

需要我补京东订单增量同步APScheduler(断点续跑+Token刷新)​ 或京东商品全量SKU翻页同步完整字段解析​ 吗?

http://www.gsyq.cn/news/1628849.html

相关文章:

  • Java SpringBoot+Vue3+MyBatis 物业管理系统系统源码|前后端分离+MySQL数据库
  • Qwen2-7B本地轻量部署:喂饭级一键推理工作流
  • Markdown 语法完全指南:一篇学完全部语法
  • 靠谱的汽车保养排名
  • 心电自监督分类论文分享(1)-read your heart
  • 盘锦门窗窗纱一体防风要看哪里
  • 模型端侧适配技能之ONNX 模型拆分
  • Python+Django构建轻量级企业员工管理系统实战
  • EM3080-W条形码解码器与STM32F303RC的硬件协同设计
  • AI时代,为什么视频号作品数据和评论数据越来越重要?
  • USB3.0总线高速数据采集卡,8通道、16位分辨率、5MHz同步采样,程控增益±10V、±5V、±2V、±1V
  • 项目进度实时监控与资源优化:项目制服务解决方案落地方法论
  • 想提升企业资源管理效能?ERP系统优化是关键!
  • Qwen3vl+Midscene+Playwright自动化AI测试框架搭建流程(win11本地安装)
  • 2026淮北黄金回收白银回收铂金回收旧料回收怎么选?五家高实价铂金白银线下门店测评清单 + 联系方式
  • 用GPT-5.5重构遗留项目:一套可复用的迁移脚本分享(附避坑指南与教程)
  • GPT高效落地实战:日常工作与学习任务优化全流程方法论
  • LENA-R8与PIC18LF45K22的全球连接与低功耗定位方案
  • 好用的平衡机创新机构
  • HoRain云--Java多线程编程:6种实战技巧与避坑指南
  • 你用AI写分析文,总觉得像拼凑的?问题不在AI,在流程
  • 互联网大厂 Java 求职面试:从 Java SE 8 到微服务技术的深入探讨
  • VSCode集成GPT-5.5教程:如何选择插件与我的效率配置盘点清单
  • 基于51/STM32单片机空气质量监测系统/环境气体检测/WiFi传输/APP21(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_
  • 打破NVIDIA垄断:如何在非NVIDIA GPU上无缝运行CUDA程序的终极方案
  • Linux 系统编程 08:System V IPC
  • WandEnhancer开源增强工具:解锁游戏修改新体验的完整指南
  • QuickLookVideo:彻底解决Mac视频预览难题的高效实用解决方案
  • 汽车电子智能散热方案:DRV8213与PIC18F87J10温控设计
  • 【第三部分:线性回归(Linear Regression)】