[特殊字符]《京东订单API(jd.order.detail.get)对接ERP:企业认证+OAuth授权避坑指南》(附Python源码)

发布时间:2026/7/4 1:36:19

[特殊字符]《京东订单API(jd.order.detail.get)对接ERP:企业认证+OAuth授权避坑指南》(附Python源码) 《京东订单APIjd.order.detail.get对接ERP企业认证OAuth授权避坑指南》附Python源码直接说结论先京东订单类接口jingdong.pop.order.search/jd.order.detail.get/jingdong.etms.waybill.send个人开发者应用无权限必须企业支付宝/企业对公认证​ 创建「商家自用型应用」申请订单相关接口权限需填场景说明用店铺卖家账号OAuth 2.0授权获取access_tokensession参数个人应用调会返回403 no permission / invalid method属正常限制。一、现象对照表你做的返回原因个人应用 jd.order.detail.get403 no permission/invalid method个人号无订单接口权限企业应用未申请接口同上 403控制台→API权限→申请jingdong.pop.order.search/jd.order.detail.get传了买家​ AccessToken空/403必须是店铺卖家​ OAuth 换的 token沙箱调订单返回 mock/空沙箱不支持真实订单仅验签名session 过期Invalid access_token用refresh_token刷新二、企业认证 OAuth授权流程关键企业认证​JOS控制台 → 账户管理 → 企业实名营业执照 企业对公/企业支付宝创建应用​应用类型选「商家自用型应用」ISV需额外软服中心入驻申请接口权限​应用→接口权限→申请jingdong.pop.order.search订单列表jd.order.detail.get订单明细jingdong.etms.waybill.send发货回填运单jingdong.etms.trace.get物流轨迹 场景说明示例ERP系统同步本店铺已付款订单生成内部销售单并回写发货物流仅访问授权店铺数据卖家OAuth授权换取 AccessToken① 引导卖家访问 https://auth.jd.com/oauth2/toLogin.action ?response_typecode client_idYOUR_APP_KEY redirect_uriURLENCODE(你在应用配置的回调地址) stateerp_jd ② 回调 → redirect_uri?codexxx ③ POST https://auth.jd.com/oauth2/accessToken grant_typeauthorization_code client_idAPP_KEY client_secretAPP_SECRET codexxx redirect_uri同上 → {access_token, refresh_token, expires_in, user_nick}此access_token JOS接口中的access_token(session) 参数三、Python订单列表 明细调用封装含权限提示# jd_order_sync.py 京东订单同步 Demo企业应用 卖家AccessToken jingdong.pop.order.search → jd.order.detail.get 依赖: requests (pip install requests) import hashlib import json import requests import time from datetime import datetime, timedelta from typing import Dict, List # 封装好API供应商demo urlhttps://console.open.onebound.cn/console/?iLex class JdOrderClient: GW https://api.jd.com/routerjson def __init__(self, app_key: str, app_secret: str): self.ak app_key self.as_ app_secret # ─── JOS MD5签名秒级timestamp─── def _sign(self, p: Dict) - str: filt sorted((k, v) for k, v in p.items() if v is not None and str(v).strip() ! and k ! sign) qs .join(f{k}{v} for k, v in filt) return hashlib.md5(f{self.as_}{qs}{self.as_}.encode() ).hexdigest().upper() def _call(self, method: str, biz: Dict, access_token: str): api_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_asciiFalse, separators(,, :)), access_token: access_token } api_p[sign] self._sign(api_p) r requests.post(self.GW, dataapi_p, timeout15) r.raise_for_status() d r.json() 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 isinstance(data, dict): err data.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) if no permission in zh or invalid method in zh: raise PermissionError( ❌ 【无权限】订单接口需\n 1) 企业实名商家应用\n 2) 已申请 jingdong.pop.order.search / jd.order.detail.get\n 3) access_token 须是【卖家】OAuth授权所得非买家token\n f 原始: [{code}] {zh} ) raise Exception(fJOS [{code}]: {zh} sub:{err.get(sub_code)}) return data # ─── 增量拉取订单列表 ─── def list_orders(self, access_token: str, minutes_back: int 30, order_state: str WAIT_SELLER_STOCK_OUT, page: int 1, page_size: int 50) - Dict: now datetime.now() start (now - timedelta(minutesminutes_back)).strftime(%Y-%m-%d %H:%M:%S) end now.strftime(%Y-%m-%d %H:%M:%S) return self._call( jingdong.pop.order.search, { start_modified: start, end_modified: end, order_state: order_state, # WAIT_SELLER_STOCK_OUT已付待发 page: page, page_size: min(page_size, 100) }, access_token ).get(popOrderSearch, {}).get(orderSearch, {}) # ─── 订单明细 ─── def get_detail(self, access_token: str, order_id: str) - Dict: return self._call( jd.order.detail.get, {orderId: order_id}, access_token ).get(orderDetail, {}).get(orderInfo, {}) # # 使用示例 # if __name__ __main__: client JdOrderClient( app_keyYOUR_JD_ENTERPRISE_APP_KEY, app_secretYOUR_JD_APP_SECRET ) SELLER_TOKEN SELLER_ACCESS_TOKEN # ← OAuth2 换取的卖家 token try: result client.list_orders(SELLER_TOKEN, minutes_back30) orders result.get(orderInfoList, []) or [] total result.get(orderTotal, 0) print(f✅ 近30分钟变更订单: {len(orders)} / 共计{total}) for o in orders[:3]: detail client.get_detail(SELLER_TOKEN, str(o.get(orderId))) print(f 单 {detail.get(orderId)} {detail.get(orderState)} f¥{detail.get(orderPrice)}) except PermissionError as pe: print(pe) print(\n➡ 解决企业实名→创建自用型应用→申请订单权限→卖家OAuth授权→填入SELLER_TOKEN) except Exception as e: print(❌, e)四、OAuth Token 交换最简片段补全用def jd_exchange_token(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 }, timeout15) r.raise_for_status() return r.json() # access_token / refresh_token / expires_in / user_nick五、避坑清单京东订单对接必看坑现象解决个人应用调订单403 no permission切企业实名商家自用应用​接口未申请同上 403应用→API权限→申请订单接口传买家 token空/403必须用店铺卖家​ OAuth 换的 AccessTokentoken 过期Invalid access_tokenrefresh_token提前刷新建议过期前7天沙箱返回空订单正常沙箱只验签用生产网关ISV应用403未入驻软服/未绑定店铺完成 ISV 入驻并绑定授权店铺timestamp 毫秒Invalid TimestampJOS用秒级​int(time.time())六、面试/方案一句话京东订单APIjingdong.pop.order.search/jd.order.detail.get须企业实名商家应用 申请订单权限 卖家OAuth AccessToken(session参数)增量按start_modified/end_modified时间窗拉取防超量遇403先确认以上三点沙箱仅验签名不返回真实订单。需要我补APScheduler 定时增量订单同步断点续跑Token自动刷新​ 或京东发货回填jingdong.etms.waybill.send完整参数​ 吗

相关新闻