一、接口体系概览
表格
| 接口类型 | 核心接口 | 数据覆盖 | 适用场景 | 权限要求 |
|---|---|---|---|---|
| 淘宝联盟-商品详情 | taobao.tbk.item.info.get | 原价、券后价(zk_final_price)、优惠券信息、佣金 | 推广者获取优惠后价格 | 淘宝联盟开发者账号 |
| 淘宝联盟-优惠券 | taobao.tbk.item.coupon.get | 优惠券面额、使用门槛、有效期 | 单独查询优惠券详情 | 联盟权限 |
| 淘宝客-万能转链 | taobao.tbk.link.parse | 解析淘口令/链接中的券后价 | 链接还原、物料解析 | 工具服务商权限 |
| 第三方聚合API | item_get / taobao.item_get | 整合后的完整价格信息 | 快速接入、批量查询 | 第三方平台密钥 |
核心计算公式 :
plain
券后价 = 原价(zk_final_price或price) - 优惠券面额(coupon_amount)注意:需先判断原价是否满足优惠券使用门槛(coupon_start_fee),否则优惠券不可用。
二、官方API:taobao.tbk.item.info.get(推荐)
1. 接入准备
- 注册开发者账号:完成企业/个人实名认证
- 创建应用:获取 App Key 和 App Secret
- 申请联盟权限:在淘宝联盟开发者平台申请
taobao.tbk.item.info.get接口权限 - 创建推广位:获取 PID(格式如
mm_123456789_00000000) - 获取Session(部分接口需要):通过OAuth授权获取用户会话密钥
2. 核心请求参数
表格
| 参数名 | 类型 | 必选 | 说明 | 示例值 |
|---|---|---|---|---|
app_key | String | 是 | 应用唯一标识 | 12345678 |
method | String | 是 | 接口方法名 | taobao.tbk.item.info.get |
timestamp | String | 是 | 时间戳(yyyy-MM-dd HH:mm:ss) | 2026-04-07 17:15:00 |
format | String | 是 | 响应格式 | json |
v | String | 是 | API版本 | 2.0 |
sign_method | String | 是 | 签名算法 | md5 |
sign | String | 是 | MD5签名 | E4F2G3H4... |
session | String | 否 | 用户授权令牌(部分接口需要) | 6100a8b8... |
num_iids | String | 是 | 商品ID列表(逗号分隔,最多40个) | 123456,789012 |
fields | String | 是 | 返回字段 | num_iid,title,price,zk_final_price,coupon_info,coupon_amount,coupon_start_fee |
3. 核心返回字段(券后价相关)
JSON
{
"tbk_item_info_get_response": {
"results": {
"n_tbk_item": [
{
"num_iid": "567890123",
"title": "时尚纯棉男士短袖T恤",
"price": "99.90", // 原价(划线价)
"zk_final_price": "39.90", // 券后价(优惠后价格)⭐核心字段
"coupon_info": "满50减10", // 优惠券信息描述
"coupon_amount": "10.00", // 优惠券面额
"coupon_start_fee": "50.00", // 优惠券使用门槛
"coupon_start_time": "2025-03-01 00:00:00",
"coupon_end_time": "2025-03-31 23:59:59",
"commission_rate": "20.00", // 佣金比例
"commission": "7.98", // 佣金金额
"volume": 500, // 30天销量
"pict_url": "https://example.com/tshirt.jpg"
}
]
}
}}关键字段说明 :
表格
| 字段名 | 含义 | 计算逻辑 |
|---|---|---|
price | 商品原价/划线价 | 商品标价 |
zk_final_price | 券后价(核心) | 优惠叠加后的实际到手价 |
coupon_amount | 优惠券面额 | 可抵扣金额 |
coupon_start_fee | 使用门槛 | 满X元可用 |
coupon_info | 优惠券描述 | 如"满50减10" |
三、签名生成算法(核心难点)
淘宝API使用MD5签名,这是新手最容易出错的环节。
签名生成步骤:
- 参数排序:按参数名ASCII升序排列(不含
sign) - 拼接字符串:格式为
key1value1key2value2...(注意:值需URL编码) - 首尾加Secret:字符串首尾各拼接一次
App Secret - MD5加密:结果转大写
Python签名实现:
Python
import hashlibimport urllib.parseimport timefrom typing import Dictdef generate_taobao_sign(params: Dict[str, str], app_secret: str) -> str:
"""
生成淘宝API签名(MD5)
"""
# 1. 过滤sign参数,按ASCII排序
sorted_params = sorted(
[(k, v) for k, v in params.items() if k != "sign" and v is not None],
key=lambda x: x[0]
)
# 2. 拼接为 key1value1key2value2 格式(值需URL编码)
sign_str = "".join([
f"{k}{urllib.parse.quote_plus(str(v))}"
for k, v in sorted_params ])
# 3. 首尾拼接app_secret
sign_str = f"{app_secret}{sign_str}{app_secret}"
# 4. MD5加密并转大写
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()# 使用示例params = {
"app_key": "your_app_key",
"method": "taobao.tbk.item.info.get",
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"format": "json",
"v": "2.0",
"sign_method": "md5",
"num_iids": "123456789",
"fields": "num_iid,title,price,zk_final_price,coupon_info"}sign = generate_taobao_sign(params, "your_app_secret")print(f"生成的签名: {sign}")四、完整实战代码(Python)
以下是一个生产级的淘宝券后价获取类,包含错误处理、批量查询和智能计算:
Python
import requestsimport timeimport jsonimport hashlibimport urllib.parseimport loggingfrom typing import Dict, List, Optional, Unionfrom dataclasses import dataclassfrom requests.adapters import HTTPAdapterfrom urllib3.util.retry import Retry
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')logger = logging.getLogger(__name__)@dataclassclass CouponPriceInfo:
"""券后价信息数据类"""
num_iid: str
title: str
original_price: float # 原价
final_price: float # 券后价(zk_final_price)
coupon_amount: float # 优惠券面额
coupon_start_fee: float # 使用门槛
coupon_info: str # 优惠券描述
commission_rate: float # 佣金比例
commission_amount: float # 佣金金额
coupon_start_time: Optional[str] = None
coupon_end_time: Optional[str] = None
is_coupon_valid: bool = True # 优惠券是否有效
volume: int = 0 # 销量
pict_url: str = ""
def calculate_real_savings(self) -> Dict:
"""计算真实优惠力度"""
# 判断优惠券是否可用(当前价是否满足门槛)
can_use_coupon = self.original_price >= self.coupon_start_fee
# 实际支付价(如果优惠券不可用,则按原价)
real_pay_price = self.final_price if can_use_coupon else self.original_price
# 实际优惠金额
real_savings = self.original_price - real_pay_price
# 折扣率
discount_rate = (real_pay_price / self.original_price) * 10 if self.original_price > 0 else 0
return {
"can_use_coupon": can_use_coupon,
"real_pay_price": round(real_pay_price, 2),
"real_savings": round(real_savings, 2),
"discount_rate": round(discount_rate, 1), # 如8.5折
"savings_percentage": round((real_savings / self.original_price) * 100, 1) if self.original_price > 0 else 0
}class TaobaoCouponAPI:
"""
淘宝券后价API客户端
支持淘宝联盟官方API和第三方聚合API
"""
def __init__(self,
app_key: Optional[str] = None,
app_secret: Optional[str] = None,
session: Optional[str] = None,
third_party_key: Optional[str] = None,
use_official: bool = True):
self.app_key = app_key
self.app_secret = app_secret
self.session = session
self.third_party_key = third_party_key
self.use_official = use_official
# 官方API端点
self.official_url = "https://eco.taobao.com/router/rest"
# 备用官方域名
self.backup_url = "https://gw.api.taobao.com/router/rest"
# 第三方API端点(示例)
self.third_party_urls = {
"aliprice": "https://www.aliprice.com/items/itemDetail",
"o0b": "https://o0b.cn/ibrad/taobao/item_get/",
"vv_tool": "http://api.vv-tool.com/tool/erps/taobaoget"
}
# 配置会话和重试
self.session_req = requests.Session()
retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[429, 500, 502, 503])
self.session_req.mount('https://', HTTPAdapter(max_retries=retry))
# 请求频率控制(官方API默认QPS=10)
self.last_request_time = 0
self.min_interval = 0.1 # 100ms间隔
def _rate_limit(self):
"""请求频率限制"""
current_time = time.time()
elapsed = current_time - self.last_request_time if elapsed < self.min_interval:
time.sleep(self.min_interval - elapsed)
self.last_request_time = time.time()
def _generate_sign(self, params: Dict) -> str:
"""生成淘宝官方API签名"""
sorted_params = sorted(
[(k, v) for k, v in params.items() if k != "sign" and v is not None],
key=lambda x: x[0]
)
sign_str = "".join([
f"{k}{urllib.parse.quote_plus(str(v))}"
for k, v in sorted_params ])
sign_str = f"{self.app_secret}{sign_str}{self.app_secret}"
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
def _call_official_api(self, method: str, biz_params: Dict) -> Optional[Dict]:
"""调用淘宝官方API"""
self._rate_limit()
# 构建公共参数
params = {
"app_key": self.app_key,
"method": method,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"format": "json",
"v": "2.0",
"sign_method": "md5"
}
# 添加业务参数
params.update(biz_params)
# 添加session(如需要)
if self.session:
params["session"] = self.session
# 生成签名
params["sign"] = self._generate_sign(params)
try:
response = self.session_req.get(
self.official_url,
params=params,
timeout=15
)
response.raise_for_status()
result = response.json()
# 处理错误
if "error_response" in result:
error = result["error_response"]
logger.error(f"API错误: {error.get('msg')} (代码: {error.get('code')})")
return None
# 返回业务数据
response_key = f"{method.replace('.', '_')}_response"
return result.get(response_key)
except requests.exceptions.RequestException as e:
logger.error(f"请求异常: {e}")
return None
except json.JSONDecodeError:
logger.error("JSON解析失败")
return None
def get_coupon_price_single(self, num_iid: str) -> Optional[CouponPriceInfo]:
"""
获取单个商品的券后价详情
"""
if self.use_official and self.app_key:
# 使用官方API
method = "taobao.tbk.item.info.get"
fields = (
"num_iid,title,pict_url,price,zk_final_price,"
"coupon_info,coupon_amount,coupon_start_fee,"
"coupon_start_time,coupon_end_time,"
"commission_rate,commission,volume"
)
biz_params = {
"num_iids": num_iid,
"fields": fields }
result = self._call_official_api(method, biz_params)
if not result:
return None
items = result.get("results", {}).get("n_tbk_item", [])
if not items:
logger.warning(f"商品 {num_iid} 无返回数据")
return None
item = items[0]
# 解析价格字段
original_price = float(item.get("price", 0))
final_price = float(item.get("zk_final_price", 0))
coupon_amount = float(item.get("coupon_amount", 0) or 0)
coupon_start_fee = float(item.get("coupon_start_fee", 0) or 0)
# 判断优惠券是否有效(当前时间是否在有效期内)
# 简化处理,实际应解析时间字符串对比
is_valid = True
return CouponPriceInfo(
num_iid=str(item.get("num_iid")),
title=item.get("title", ""),
original_price=original_price,
final_price=final_price,
coupon_amount=coupon_amount,
coupon_start_fee=coupon_start_fee,
coupon_info=item.get("coupon_info", ""),
commission_rate=float(item.get("commission_rate", 0) or 0),
commission_amount=float(item.get("commission", 0) or 0),
coupon_start_time=item.get("coupon_start_time"),
coupon_end_time=item.get("coupon_end_time"),
is_coupon_valid=is_valid,
volume=int(item.get("volume", 0)),
pict_url=item.get("pict_url", "")
)
else:
# 使用第三方API(简化示例)
return self._get_third_party_price(num_iid)
def get_coupon_price_batch(self, num_iids: List[str]) -> List[CouponPriceInfo]:
"""
批量获取券后价(官方API支持一次查询40个商品)
"""
if not num_iids:
return []
# 分批处理(每批最多40个)
batch_size = 40
results = []
for i in range(0, len(num_iids), batch_size):
batch = num_iids[i:i+batch_size]
batch_str = ",".join(batch)
method = "taobao.tbk.item.info.get"
fields = (
"num_iid,title,pict_url,price,zk_final_price,"
"coupon_info,coupon_amount,coupon_start_fee,"
"commission_rate,volume"
)
biz_params = {
"num_iids": batch_str,
"fields": fields }
result = self._call_official_api(method, biz_params)
if result:
items = result.get("results", {}).get("n_tbk_item", [])
for item in items:
try:
info = CouponPriceInfo(
num_iid=str(item.get("num_iid")),
title=item.get("title", ""),
original_price=float(item.get("price", 0)),
final_price=float(item.get("zk_final_price", 0)),
coupon_amount=float(item.get("coupon_amount", 0) or 0),
coupon_start_fee=float(item.get("coupon_start_fee", 0) or 0),
coupon_info=item.get("coupon_info", ""),
commission_rate=float(item.get("commission_rate", 0) or 0),
commission_amount=float(item.get("commission", 0) or 0),
volume=int(item.get("volume", 0)),
pict_url=item.get("pict_url", "")
)
results.append(info)
except Exception as e:
logger.error(f"解析商品数据失败: {e}")
return results
def _get_third_party_price(self, num_iid: str) -> Optional[CouponPriceInfo]:
"""第三方API调用示例(需根据实际平台调整)"""
try:
# 示例:使用订单侠等第三方API
url = f"https://o0b.cn/ibrad/taobao/item_get/"
params = {
"key": self.third_party_key,
"num_iid": num_iid }
response = self.session_req.get(url, params=params, timeout=10)
data = response.json()
item = data.get("item", {})
# 解析第三方返回结构...
# 实际字段需根据第三方文档调整
return CouponPriceInfo(
num_iid=num_iid,
title=item.get("title", ""),
original_price=float(item.get("original_price", 0)),
final_price=float(item.get("final_price", 0)),
coupon_amount=float(item.get("coupon_amount", 0)),
coupon_start_fee=float(item.get("coupon_start_fee", 0)),
coupon_info=item.get("coupon_info", ""),
commission_rate=float(item.get("commission_rate", 0)),
volume=int(item.get("volume", 0)),
pict_url=item.get("pic_url", "")
)
except Exception as e:
logger.error(f"第三方API调用失败: {e}")
return None
def parse_taobao_link(self, url: str) -> Optional[Dict]:
"""
解析淘宝链接/淘口令,获取商品ID和券后价
需要 taobao.tbk.link.parse 权限
"""
if not self.use_official:
logger.warning("解析功能仅支持官方API")
return None
method = "taobao.tbk.link.parse"
biz_params = {
"url": url,
"fields": "num_iid,title,zk_final_price,coupon_info"
}
return self._call_official_api(method, biz_params)# ==================== 使用示例 ====================if __name__ == "__main__":
# 初始化(使用官方API)
api = TaobaoCouponAPI(
app_key="your_app_key",
app_secret="your_app_secret",
session="your_session", # 可选
use_official=True
)
# 示例1:获取单个商品券后价
print("=" * 50)
print("示例1:单个商品查询")
print("=" * 50)
result = api.get_coupon_price_single("6543217890")
if result:
print(f"商品标题: {result.title}")
print(f"原价: ¥{result.original_price}")
print(f"券后价: ¥{result.final_price}")
print(f"优惠券: {result.coupon_info} (面额¥{result.coupon_amount})")
print(f"佣金比例: {result.commission_rate}%")
print(f"30天销量: {result.volume}")
# 计算真实优惠
savings = result.calculate_real_savings()
print(f"\n💰 优惠分析:")
print(f" 是否可用券: {'是' if savings['can_use_coupon'] else '否'}")
print(f" 实际支付: ¥{savings['real_pay_price']}")
print(f" 实际优惠: ¥{savings['real_savings']}")
print(f" 折扣力度: {savings['discount_rate']}折")
print(f" 节省比例: {savings['savings_percentage']}%")
else:
print("获取失败")
# 示例2:批量查询
print("\n" + "=" * 50)
print("示例2:批量商品查询")
print("=" * 50)
item_ids = ["123456", "789012", "345678"]
batch_results = api.get_coupon_price_batch(item_ids)
for item in batch_results:
print(f"\n{item.title[:20]}...")
print(f" 券后价: ¥{item.final_price} (省¥{item.coupon_amount})")五、第三方聚合API方案
对于快速接入或缺乏联盟权限的开发者,第三方API是更简单的选择:
表格
| 平台 | 接口地址 | 特点 | 价格 |
|---|---|---|---|
| 订单侠 | o0b.cn/ibrad/taobao/item_get/ | 字段完整,含券后价、佣金、销量 | 0.003元/次 |
| AliPrice | aliprice.com/items/itemDetail | 支持淘口令解析、历史价格 | 包年包月 |
| VV-Tool | api.vv-tool.com/tool/erps/taobaoget | ERP工具集成,支持批量 | 包年包月 |
第三方API典型返回结构:
JSON
{
"item": {
"num_iid": "123456",
"title": "商品标题",
"original_price": "199.00",
"final_price": "89.00", // 券后价
"coupon_amount": "110.00", // 优惠券面额
"coupon_start_fee": "100.00", // 使用门槛
"commission_rate": "30.00", // 佣金比例
"volume": 10000, // 销量
"pic_url": "https://..."
}}六、券后价计算逻辑详解
复杂场景处理
Python
def calculate_final_price(
original_price: float,
zk_final_price: float,
coupon_amount: float,
coupon_start_fee: float,
shop_discount: float = 0, // 店铺满减
platform_discount: float = 0, // 平台券
is_tmall: bool = False) -> Dict:
"""
计算最终到手价(考虑多重优惠叠加)
"""
# 1. 判断优惠券是否可用
can_use_coupon = original_price >= coupon_start_fee
# 2. 计算优惠顺序(通常:店铺券 > 平台券 > 跨店满减)
price_after_shop = original_price - shop_discount
price_after_coupon = price_after_shop - (coupon_amount if can_use_coupon else 0)
final_price = price_after_coupon - platform_discount
# 3. 确保价格不为负(淘宝不允许负价)
final_price = max(final_price, 0.01)
# 4. 校验与zk_final_price的一致性(误差应<0.1元)
is_consistent = abs(final_price - zk_final_price) < 0.1
return {
"original_price": original_price,
"shop_discount": shop_discount,
"coupon_discount": coupon_amount if can_use_coupon else 0,
"platform_discount": platform_discount,
"final_price": round(final_price, 2),
"total_savings": round(original_price - final_price, 2),
"savings_rate": round((original_price - final_price) / original_price * 100, 1),
"is_coupon_used": can_use_coupon,
"is_price_consistent": is_consistent }七、常见问题与解决方案
表格
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
zk_final_price为null或0 | 商品下架、无推广权限、或API未返回 | 检查商品状态,确认有推广权限 |
coupon_amount返回0 | 该商品当前无优惠券 | 查询coupon_info字段确认,或调用taobao.tbk.coupon.get |
签名错误 (sign invalid) | 参数排序错误、未URL编码、时间戳格式不对 | 严格按ASCII排序,使用urllib.parse.quote_plus编码 |
Insufficient isv permissions | 缺少接口权限 | 在淘宝联盟后台申请taobao.tbk.item.info.get权限 |
| 券后价与实际不符 | 存在多重优惠(店铺券+平台券) | 解析所有优惠字段,手动计算叠加 |
| QPS超限(错误码7) | 请求频率超过限制(默认10次/秒) | 添加请求间隔(100ms),或申请提升额度 |
coupon_info格式不统一 | 不同活动类型描述不同 | 使用正则提取:满(\d+)减(\d+) |
八、合规与风控要点(2026年更新)
根据淘宝开放平台最新规则:
- 数据使用限制:获取的价格数据不可用于竞价排名、恶意比价,仅限自身业务使用
- 缓存策略:券后价实时变动,建议缓存时间不超过5分钟
- 隐私保护:用户手机号、地址等敏感信息需加密存储
- 反爬虫:禁止通过"多账号轮调"突破频率限制,违者封号
- 淘口令解析:需申请
taobao.tbk.link.parse权限,且仅限工具服务商使用
九、扩展应用场景
基于券后价API可构建以下应用:
- 智能导购机器人:自动查询券后价,生成"省XX元"的推广文案
- 价格监控预警:追踪商品券后价波动,降价时推送通知
- 比价搜索引擎:对比淘宝、京东、拼多多券后价,推荐最优渠道
- 返利计算器:结合佣金比例,计算用户实际返现金额
- 选品分析工具:筛选高佣金、高优惠、高销量的"三高"商品
如遇任何疑问或有进一步的需求,请随时与我私信或者评论联系。