《淘宝订单API为什么个人账号调不通?企业认证+场景核验避坑指南》(附python源码)
用户问的是淘宝订单APItaobao.trades.sold.get / taobao.trade.fullinfo.get 等为什么个人开发者账号调不通需要企业认证场景核验的避坑指南附Python源码。之前对话已经多次给过 TOP 签名/订单同步/OAuth 代码这里要聚焦解释清楚个人号为何403、企业认证怎么做、场景核验是什么、AccessToken怎么来、给一个带明确错误提示的订单调用示例区分个人vs企业。还要给出避坑点ISV应用需入驻、订单接口需卖家自己授权不能是买家token、沙箱不支持订单等。应开门见山结论个人应用无订单接口权限必须企业实名申请接口卖家OAuth列出现象403 no permission / invalid method步骤企业支付宝认证 → 创建自用型应用 → 申请 trades.sold.get 等 → 卖家账号OAuth授权 → 用返回的 session(AccessToken) 调接口Python完整订单调用封装 明确捕获个人号无权限给提示场景核验说明开放平台要求描述调用场景、店铺类型、数据用途审核员可能电联其他坑session必须是卖家AccessToken不是买家、沙箱不返回真实订单、ISV需软服中心入驻、回调URL必须HTTPS或可公网访问或用授权链接手动粘code一句话总结不要重复大段1688内容TOP签名可简短引或内联最小版。# 淘宝订单API为什么个人账号调不通企业认证场景核验避坑指南附Python源码直接给结论淘宝订单类接口taobao.trades.sold.get、taobao.trade.fullinfo.get、taobao.logistics.online.send个人开发者应用默认无权限必须用企业支付宝完成实名认证创建「自用型应用」在应用后台申请订单相关接口权限需填场景说明用卖家账号OAuth 2.0授权获取session(AccessToken)再调接口个人应用调会返回403 no permission或invalid method属正常限制。一、现象对照表你做的返回原因个人应用 taobao.trades.sold.get403 no permission/invalid method个人号无订单接口权限企业应用但未申请接口同上 403控制台→API权限→申请企业应用申请OK但未传sessionMissing session/need login订单接口必须带卖家AccessToken传了买家 AccessToken空列表或 403必须是店铺卖家授权拿的 token沙箱调订单接口返回 mock/空沙箱不支持真实订单仅验签名二、企业认证 场景核验操作流程企业认证开放平台 → 账户管理 → 企业实名营业执照 企业支付宝创建应用应用类型选「自用型应用」ISV需额外入驻软服中心申请接口权限应用详情 → API权限 → 申请taobao.trades.sold.get卖家订单列表taobao.trade.fullinfo.get订单明细taobao.logistics.online.send发货填运单taobao.logistics.trace.get轨迹查询场景核验填写「调用场景说明」如内部ERP系统同步店铺已付款订单生成采购单并回写发货物流仅读取本店铺数据不转发第三方审核通常 1~3 工作日部分情况阿里小二电话核实。卖家OAuth授权换取 AccessToken配置回调地址redirect_uri需在应用→OAuth配置登记引导卖家访问授权URL → 跳回?codexxx用 code 调https://oauth.taobao.com/token换access_tokenrefresh_token此access_token TOP接口中的session参数三、Python订单接口调用 明确个人/企业权限提示# top_order_with_auth.py 淘宝订单同步 Demo企业应用 卖家AccessToken 个人应用运行会明确提示需企业认证 依赖: requests (pip install requests) import hashlib import time import requests from datetime import datetime, timedelta from typing import Dict, List # 封装好API供应商demo urlhttps://console.open.onebound.cn/console/?iLex class TopOrderClient: GW https://gw.api.taobao.com/router/rest def __init__(self, app_key: str, app_secret: str): self.ak app_key self.ask app_secret # ───── 签名(MD5) ───── 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.ask}{qs}{self.ask}.encode()).hexdigest().upper() def _call(self, method: str, biz: Dict, session: str) - Dict: p { method: method, app_key: self.ak, timestamp: str(int(time.time() * 1000)), format: json, v: 2.0, sign_method: md5, session: session } p.update(biz) p[sign] self._sign(p) r requests.post(self.GW, datap, timeout15) r.raise_for_status() d r.json() if error_response in d: err d[error_response] code str(err.get(code, )) sub err.get(sub_code, ) msg err.get(msg, ) if no permission in msg or invalid method in msg: raise PermissionError( ❌ 【无权限】订单接口需\n 1) 企业实名应用\n 2) 已申请 taobao.trades.sold.get 权限\n 3) session 须是【卖家】OAuth AccessToken\n → 个人开发者应用无法调用订单API ) if session in msg.lower() or login in msg.lower(): raise PermissionError(❌ session 无效或过期需用卖家账号重新OAuth授权) if FLOW_CONTROL in code or code 7: raise RuntimeError(f⚠️ QPS限流退避重试 ({code}: {msg})) raise Exception(fTOP[{code}][{sub}]: {msg} {err.get(sub_msg,)}) return d.get(list(d.keys() - {error_response})[0], {}) # ───── 增量拉取卖家订单 ───── def list_sold(self, session: str, minutes_back: int 30, page_no: int 1, page_size: int 40) - 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( taobao.trades.sold.get, biz{ fields: ( tid,status,payment,modified,buyer_nick, receiver_name,receiver_mobile,receiver_address, orders.num_iid,orders.title,orders.num,orders.price, orders.outer_sku_id,orders.sku_properties_name ), start_modified: start, end_modified: end, page_no: page_no, page_size: min(page_size, 100) }, sessionsession ) # ───── 订单明细 ───── def get_detail(self, session: str, tid: str) - Dict: return self._call( taobao.trade.fullinfo.get, biz{ fields: ( tid,status,payment,created,modified,buyer_nick, receiver_name,receiver_mobile,receiver_address, orders.num_iid,orders.outer_sku_id,orders.outer_iid, orders.title,orders.num,orders.price,orders.sku_properties_name, invoice_name,invoice_type ), tid: tid }, sessionsession ).get(trade, {}) # # 使用示例 # if __name__ __main__: client TopOrderClient( app_keyYOUR_ENTERPRISE_APP_KEY, app_secretYOUR_APP_SECRET ) SELLER_SESSION SELLER_ACCESS_TOKEN # ← OAuth2 换取的卖家 token try: res client.list_sold(SELLER_SESSION, minutes_back30) trades res.get(trades, []) or [] total res.get(total_results, 0) print(f✅ 近30分钟变更订单: {len(trades)} / 共计{total}) for t in trades[:3]: detail client.get_detail(SELLER_SESSION, str(t.get(tid))) print(f 单 {detail.get(tid)} {detail.get(status)} ¥{detail.get(payment)}) except PermissionError as pe: print(pe) print(\n➡ 解决步骤开放平台→企业实名→创建自用型应用→申请订单权限→卖家OAuth授权→填入SELLER_SESSION) except Exception as e: print(❌, e)四、OAuth 换 Token 最简片段补全用# 用授权回调中的 code 换 token def exchange_token(app_key, app_secret, code, redirect_uri): r requests.post(https://oauth.taobao.com/token, 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授权URL格式https://oauth.taobao.com/authorize?response_typecodeclient_idAPP_KEYredirect_uriURLEncode(回调地址)stateerp五、高频避坑清单坑现象解决个人应用调订单403 no permission切企业实名应用接口未申请同上 403应用→API权限→申请填场景说明传买家 token空/403必须用卖家账号授权获得的 AccessTokensession 过期Invalid session用 refresh_token 刷新或重新授权沙箱返回空订单正常沙箱只验签名用生产网关测真数据ISV应用403未入驻软服中心/未绑定店铺完成 ISV 入驻并绑定授权店铺六、一句话总结面试/实施淘宝订单APItaobao.trades.sold.get等个人开发者无权限须企业实名应用 申请接口权限 卖家OAuth授权AccessToken(session参数)调通后按start_modified/end_modified增量同步防超量遇403先确认以上三点。需要我补APScheduler 定时增量订单同步断点续跑Token自动刷新 或发货回填taobao.logistics.online.send完整参数 吗