摘要:本文聚焦 VVIC 跨境 B2B 平台商品详情接口(item.detail.get),区别于网上通用教程,从批发场景特性、标准签名机制、异常处理与数据结构化解析四大维度展开,提供可直接运行的 Python 代码与避坑指南,适配 CSDN 审核规范,帮助开发者高效、合规接入。 VVIC(搜款网)作为服装 B2B 批发平台,其商品接口与淘宝 / 京东等零售接口设计逻辑完全不同: 核心字段:档口信息、混批价 / 打包价、阶梯价、起批量、多 SKU 联动库存 鉴权:AppKey + 时间戳 + MD5 签名(非简单 Token) 限流:基础 30 次 / 分钟、高级 100 次 / 分钟,IP + 账号双重管控 适用场景:选品分析、价格监控、货源同步、跨境铺货 开放平台注册应用,获取: 开通item.detail.get接口权限 依赖安装: bash 网上常见代码多为简化版,本文采用官方标准签名流程(ASCII 排序 + 拼接 + MD5 大写): 所有非空参数(含 拼接为 末尾追加 MD5-32 位加密→转大写 python 签名必坑 必须13 位毫秒时间戳(10 位秒会报错) 空值参数必须剔除,否则签名不匹配 严格ASCII 排序,不能自定义顺序 批发场景重点 价格:优先取 库存:SKU 级库存独立,需循环解析 档口: 异常处理 HTTP 4xx:鉴权 / 参数错误 HTTP 5xx:服务器异常,建议重试 + 降级 限流:返回一、接口核心背景与场景差异
二、接入准备(必填)
app_key:应用标识app_secret:签名密钥(严格保密)
运行
pip install requests hashlib三、标准签名机制(关键)
app_key/item_id/timestamp)按key 升序排序key1=value1&key2=value2app_secret
点击获取key和secret
四、完整可运行代码(原创实现)
运行import requests
import hashlib
import time
from typing import Dict, Optional
class VVICItemDetailClient:
"""VVIC商品详情接口标准化客户端(适配批发场景)"""
def __init__(self, app_key: str, app_secret: str):
self.app_key = app_key
self.app_secret = app_secret
self.base_url = "https://api.vvic.com/rest/item/detail"
self.timeout = 10
def _generate_sign(self, params: Dict[str, str]) -> str:
"""标准签名生成(官方规范)"""
# 1. 过滤空值并按key升序
sorted_items = sorted(
[(k, v) for k, v in params.items() if v is not None and v != ""],
key=lambda x: x[0]
)
# 2. 拼接参数
param_str = "&".join([f"{k}={v}" for k, v in sorted_items])
# 3. 追加密钥
sign_raw = f"{param_str}{self.app_secret}"
# 4. MD5大写
sign = hashlib.md5(sign_raw.encode("utf-8")).hexdigest().upper()
return sign
def get_item_detail(self, item_id: str) -> Optional[Dict]:
"""获取商品详情(含批发价/SKU/档口)"""
# 构造请求参数
timestamp = str(int(time.time() * 1000)) # 13位毫秒
params = {
"app_key": self.app_key,
"item_id": item_id,
"timestamp": timestamp,
"version": "1.0"
}
# 生成签名
params["sign"] = self._generate_sign(params)
try:
# 发送请求(POST+JSON)
resp = requests.post(
self.base_url,
json=params,
headers={"Content-Type": "application/json"},
timeout=self.timeout
)
resp.raise_for_status()
result = resp.json()
# 业务状态判断
if result.get("code") == 200:
return self._parse_wholesale_data(result["data"])
else:
print(f"API错误:{result.get('msg', '未知错误')}")
return None
except requests.exceptions.RequestException as e:
print(f"请求异常:{str(e)}")
return None
def _parse_wholesale_data(self, data: Dict) -> Dict:
"""批发场景专属解析(提取核心字段)"""
parsed = {
"item_id": data.get("itemId"),
"title": data.get("title"),
"category": data.get("categoryPath", []),
# 批发价格(区别于零售)
"wholesale_price": {
"mix_price": data.get("mixPrice"), # 混批价
"package_price": data.get("packagePrice"), # 打包价
"min_buy": data.get("minBuy") # 起批量
},
# SKU规格+库存(服装多尺码/颜色)
"skus": [{
"sku_id": sku.get("skuId"),
"specs": sku.get("specs", {}),
"price": sku.get("price"),
"stock": sku.get("stock")
} for sku in data.get("skus", [])],
# 档口信息(B2B核心)
"shop": {
"shop_name": data.get("shopName"),
"market": data.get("marketName"), # 如十三行、四季青
"score": data.get("shopScore")
},
"images": data.get("mainImages", [])
}
return parsed
# ———— 调用示例 ————
if __name__ == "__main__":
# 替换为你的密钥
APP_KEY = "your_app_key"
APP_SECRET = "your_app_secret"
ITEM_ID = "12345678" # 商品ID
client = VVICItemDetailClient(APP_KEY, APP_SECRET)
detail = client.get_item_detail(ITEM_ID)
if detail:
import json
print(json.dumps(detail, ensure_ascii=False, indent=2))五、关键解析与避坑(原创)
mixPrice/packagePrice,非单一级别零售价marketName(市场名)是 B2B 核心决策字段code=429时,需休眠后重试