
做 B2B 电商数据的都懂,1688 商品详情接口(核心接口名alibaba.offer.get)比 C 端平台难搞太多 —— 既要处理多接口协同,又要扛住签名加密,还得兼容批发价、起订量这些 B 端特色字段。我前前后后对接过 30 多个 1688 项目,光签名错误就踩过 7 种坑,今天把压箱底的技术干货掏出来,从参数到代码全拆解,新手照做能直接避坑。

1688 作为 B2B 平台,接口设计完全服务于供应链场景,这 3 个特性是坑点根源:
字段名 | 来源接口 | 技术用途 | 避坑提醒 |
|---|---|---|---|
offerId | 所有接口必填 | 商品唯一标识 | 短链转长链才能提取,纯数字 10-16 位 |
priceRange | alibaba.offer.price.get | 批发价区间 | 需拆分为最低价 / 最高价字段存储 |
moq | alibaba.offer.price.get | 最小起订量 | 部分商品返回 “10+”,需截取数字 |
specList | alibaba.offer.spec.get | SKU 规格列表 | 嵌套 3 层 JSON,需递归解析 |
creditLevel | alibaba.member.get | 供应商信用等级 | 对应 “AAA”“AA” 等标签,需映射转换 |
签名是 1688 接口的第一道坎,我见过最多的错误就是 “25 签名错误”,直接上实战代码和避坑要点。
import hashlib
import time
import sortedcontainers
def generate_1688_sign(params: dict, app_secret: str) -> str:
"""
生成1688标准签名(踩过5次坑后总结的正确版本)
:param params: 待签名参数字典(不含sign)
:param app_secret: 应用密钥
:return: 32位大写签名字符串
"""
# 坑点1:必须用SortedDict保证ASCII升序,普通dict会乱序
sorted_params = sortedcontainers.SortedDict(params)
# 坑点2:拼接格式是"keyvalue"无分隔符,首尾必须加app_secret
sign_str = app_secret
for key, value in sorted_params.items():
# 坑点3:参数值必须转字符串,数字类型会导致加密偏差
sign_str += f"{key}{str(value)}"
sign_str += app_secret
# 加密并转大写(小写会报错)
return hashlib.md5(sign_str.encode("utf-8")).hexdigest().upper()
# 测试示例(替换成自己的app_key和secret)
if __name__ == "__main__":
base_params = {
"method": "alibaba.offer.get",
"app_key": "你的app_key",
"timestamp": str(int(time.time() * 1000)), # 毫秒级时间戳
"format": "json",
"v": "2.0",
"signMethod": "md5",
"offerId": "12345678901234"
}
sign = generate_1688_sign(base_params, "你的app_secret")
print(f"正确签名:{sign}")1688 的商品数据像 “散装零件”,得把 4 个接口的数据拼起来才能用,这是 B 端对接的核心技术点。
import requests
from dataclasses import dataclass
from typing import List, Optional
# 用数据类存结构化结果(比字典清晰10倍)
@dataclass
class ProductDetail:
offer_id: str
title: str
min_price: float # 最低价
max_price: float # 最高价
moq: int # 最小起订量
spec_list: List[dict] # SKU规格
supplier_name: str
credit_level: str
class Ali1688Client:
def __init__(self, app_key: str, app_secret: str):
self.app_key = app_key
self.app_secret = app_secret
self.base_url = "1688开放平台接口地址" # 按官方文档配置
def _get_base_params(self, method: str, offer_id: str) -> dict:
"""生成基础参数字典(复用率90%)"""
params = {
"method": method,
"app_key": self.app_key,
"timestamp": str(int(time.time() * 1000)),
"format": "json",
"v": "2.0",
"signMethod": "md5",
"offerId": offer_id
}
params["sign"] = generate_1688_sign(params, self.app_secret)
return params
def get_product_detail(self, offer_id: str) -> Optional[ProductDetail]:
"""
多接口协同获取完整商品详情
顺序:基础信息→价格库存→规格→供应商信息
"""
try:
# 1. 拉取基础信息(标题、主图)
base_params = self._get_base_params("alibaba.offer.get", offer_id)
base_res = requests.get(self.base_url, params=base_params, timeout=10).json()
if base_res.get("error_code") != 0:
print(f"基础接口报错:{base_res['error_msg']}")
return None
base_data = base_res["result"]["offer"]
# 2. 拉取价格与起订量
price_params = self._get_base_params("alibaba.offer.price.get", offer_id)
price_res = requests.get(self.base_url, params=price_params, timeout=10).json()
price_data = price_res["result"]["priceInfo"]
# 解析价格区间(坑点:部分返回"10.00-15.00",需拆分)
price_range = price_data["priceRange"].split("-")
min_price = float(price_range[0])
max_price = float(price_range[1]) if len(price_range) > 1 else min_price
# 解析起订量(坑点:处理"10+"这类格式)
moq = int(price_data["moq"].replace("+", ""))
# 3. 拉取SKU规格
spec_params = self._get_base_params("alibaba.offer.spec.get", offer_id)
spec_res = requests.get(self.base_url, params=spec_params, timeout=10).json()
spec_list = spec_res["result"]["specList"]
# 4. 拉取供应商信息
supplier_id = base_data["memberId"]
supplier_params = self._get_base_params("alibaba.member.get", offer_id)
supplier_params["memberId"] = supplier_id # 补充供应商ID参数
supplier_params["sign"] = generate_1688_sign(supplier_params, self.app_secret) # 重新签名
supplier_res = requests.get(self.base_url, params=supplier_params, timeout=10).json()
supplier_data = supplier_res["result"]["member"]
# 5. 组装结构化数据
return ProductDetail(
offer_id=offer_id,
title=base_data["title"],
min_price=min_price,
max_price=max_price,
moq=moq,
spec_list=spec_list,
supplier_name=supplier_data["companyName"],
credit_level=supplier_data["creditLevel"]
)
except requests.exceptions.Timeout:
print("接口超时(1688高峰在9-11点,建议加重试机制)")
return None
except KeyError as e:
print(f"字段缺失:{str(e)}(部分商品无规格,需做兼容)")
return None错误码 | 典型场景 | 解决方案(亲测有效) |
|---|---|---|
25 | 签名错误 | 按 “排序→转字符串→首尾加 secret” 三步重写签名逻辑 |
401 | 未授权访问 | 检查 app_key 是否绑定应用,token 是否过期 |
429 | 请求过于频繁 | 加动态延迟(成功→20 秒,失败→60 秒),用代理池轮换 IP |
1001 | 商品不存在 | 验证 offerId 是否正确,商品是否下架 |
40005 | 规格不匹配 | 重新调用alibaba.offer.spec.get获取最新 specId |
1688 接口对接最磨人的是 “权限申请” 和 “限流”,分享两个实战技巧:
对了,需要稳定 KEY 和更高配额的朋友,找小编就能解决,省得自己跟平台磨权限 —— 我们做电商数据接口多年,适配过 1688 全量接口,稳定性比自己申请的靠谱多。
要是对接时卡在签名报错、字段解析乱码,或者想知道多接口并发调度的技巧,直接评论区留言。我每天都翻技术论坛,有问必答,毕竟 1688 这坑,能帮一个是一个~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。