1688 开放平台的item_search接口(对应官方标准接口portals.open.api.item.search)是按关键字搜索商品的核心工具,专为 B2B 批发场景设计,广泛应用于采购系统、供应链选品、竞品分析等业务。本文将从接口基础、对接流程、代码实现到高级优化,全面讲解如何高效对接该接口,覆盖从入门到精通的全流程。
一、接口基础认知
1. 核心功能
item_search接口通过关键字、分类、价格区间、起订量等条件筛选 1688 商品,返回符合条件的商品列表及 B2B 场景特有的数据,例如:基础信息:商品 ID、标题、主图、详情页链接
批发属性:批发价、价格区间(如 1-10 件 10 元 / 件,100 + 件 8 元 / 件)、起订量、混批支持
供应商信息:店铺名称、公司名称、诚信通等级、交易记录
库存与销量:可售数量、30 天成交件数、评价数
2. 接口环境
| 环境类型 | 接口地址 | 用途 |
|---|---|---|
| 沙箱环境 | https://gw.api.alibaba.com/dev/tools/api_test_sdk.htm(通过官方测试工具调用) | 功能验证、参数调试、签名测试 |
| 正式环境 | https://gw.open.1688.com/openapi/param2/2/portals.open.api.item.search | 生产环境业务调用 |
3. 核心参数
(1)公共参数
| 参数名 | 类型 | 说明 |
|---|---|---|
app_key | 字符串 | 应用唯一标识,从 1688 开放平台「应用管理」中获取 |
access_token | 字符串 | OAuth2.0 授权令牌,需通过system.oauth2.getToken接口获取,有效期 3600 秒 |
method | 字符串 | 接口名称,固定为portals.open.api.item.search |
format | 字符串 | 返回格式,固定为json(推荐)或xml |
v | 字符串 | API 版本,固定为1.0 |
timestamp | 字符串 | 毫秒级时间戳(如1699999999999),需与 1688 服务器时间误差≤5 分钟 |
sign | 字符串 | 签名,用于接口安全验证,生成规则见「接口调用流程」 |
(2)业务参数
| 参数名 | 类型 | 说明 | 是否必填 |
|---|---|---|---|
keywords | 字符串 | 搜索关键字(如 “纯棉 T 恤”“办公笔记本”),支持多关键词空格分隔 | 是 |
page | 整数 | 页码,默认 1,最大支持 50 页(1688 限制单次搜索最多返回 50 页数据) | 否 |
pageSize | 整数 | 每页条数,默认 20,最大 50(建议按业务需求选择,50 条 / 页可减少调用次数) | 否 |
categoryId | 字符串 | 商品分类 ID(如 “服装” 分类 ID 为 10001),可通过portals.open.api.category.get接口获取分类树 | 否 |
priceStart | 浮点数 | 最低价格(元),如10表示筛选 10 元以上商品 | 否 |
priceEnd | 浮点数 | 最高价格(元),如50表示筛选 50 元以下商品 | 否 |
minOrderAmount | 整数 | 最低起订量,如10表示筛选起订量≥10 件的商品 | 否 |
sort | 字符串 | 排序方式,可选值:- default(默认排序)- price_asc(价格升序)- price_desc(价格降序)- trade_num_desc(30 天销量降序)- credit_desc(供应商诚信通等级降序) | 否 |
mixEnabled | 布尔值 | 是否支持混批(多商品合并下单),true表示仅筛选支持混批的商品 | 否 |
二、对接前置准备
1. 注册开发者账号
访问1688 开放平台,使用企业支付宝或个人支付宝登录;
完成「开发者认证」:个人开发者需实名认证,企业开发者需上传营业执照(企业认证可获取更多接口权限);
进入「控制台」,确认账号状态为「已激活」。
2. 创建应用并获取密钥
在控制台左侧菜单选择「应用管理 → 创建应用」;
填写应用名称(如 “XX 采购系统”)、应用描述,选择应用类型(“企业自用” 或 “第三方服务”);
应用创建后,在「应用详情」页获取
app_key和app_secret(app_secret需妥善保管,不可泄露给第三方,建议存储在环境变量或加密配置文件中)。
3. 申请接口权限
在应用详情页选择「接口权限 → 申请权限」;
搜索 “商品搜索”,找到「portals.open.api.item.search」接口,点击「申请」;
填写申请理由(如 “企业采购选品需求,需按关键字筛选商品”),提交后通常 1-3 个工作日内审核通过;
审核通过后,在「已开通接口」中确认权限状态为「已生效」。
4. 环境与工具准备
开发语言:支持任何可发起 HTTP POST 请求的语言(Python/Java/PHP/Node.js 等,本文以 Python 为例);
测试工具:Postman(用于快速验证接口参数和签名)、1688 官方 API 测试工具(点击访问);
依赖库:Python 需安装
requests库(pip install requests)。
三、接口调用流程
item_search接口调用需遵循「获取令牌 → 组装参数 → 生成签名 → 发送请求 → 解析响应」的流程,其中「签名生成」和「令牌管理」是核心环节。1. 步骤 1:获取 access_token(OAuth2.0 授权)
item_search)均需携带access_token。获取方式有两种,企业自用场景推荐「客户端模式」(无需用户授权,直接通过app_key和app_secret获取令牌)。客户端模式获取令牌的接口参数:
接口地址:
https://gw.open.1688.com/openapi/http/1/system.oauth2/getToken请求方式:POST
业务参数:
grant_type:固定为client_credentialsclient_id:即app_keyclient_secret:即app_secret
令牌有效期:
生成的
access_token有效期为 3600 秒(1 小时),过期后需重新获取;建议在代码中实现令牌缓存逻辑,避免每次调用
item_search都重新请求令牌(减少无效请求)。
2. 步骤 2:组装参数
参数名区分大小写(如
keywords不可写为Keywords);可选参数若不使用,无需加入字典(避免冗余);
timestamp需为毫秒级时间戳(Python 中可通过int(time.time() * 1000)生成)。
3. 步骤 3:生成签名(关键步骤)
1001错误码,生成规则如下:排序:将所有参数(除
sign外)按参数名的 ASCII 码升序排序(如app_key在access_token之前,keywords在page之前);拼接:按 “
key1value1key2value2...” 的格式拼接排序后的参数(无分隔符,无=);加密:在拼接字符串的末尾追加
app_secret,然后进行 MD5 加密(32 位小写),最后转为大写;赋值:将加密结果赋值给
sign参数,加入参数字典。签名生成示例(伪代码):
params = {
"app_key": "your_app_key",
"access_token": "your_token",
"method": "portals.open.api.item.search",
"format": "json",
"v": "1.0",
"timestamp": "1699999999999",
"keywords": "纯棉T恤",
"page": 1,
"pageSize": 20
}
# 1. 排序
sorted_params = sorted(params.items(), key=lambda x: x[0])
# 2. 拼接
sign_str = ""
for key, value in sorted_params:
sign_str += f"{key}{value}"
# 3. 追加app_secret并加密
sign_str += "your_app_secret"
sign = hashlib.md5(sign_str.encode()).hexdigest().upper()
# 4. 加入参数字典
params["sign"] = sign4. 步骤 4:发送请求
请求方式:POST(1688 接口不支持 GET,仅支持 POST);
Content-Type:固定为
application/x-www-form-urlencoded;超时时间:建议设置为 10-15 秒(避免网络波动导致请求失败)。
5. 步骤 5:解析响应
成功响应:包含
item_search_response字段,商品列表在item_search_response → items → item中;错误响应:包含
error_response字段,需根据code(错误码)和msg(错误信息)排查问题。
四、代码实现示例(Python)
app_key和app_secret)。import requestsimport hashlibimport timeimport jsonclass AlibabaSearchApi:
def __init__(self, app_key, app_secret):
"""初始化API客户端"""
self.app_key = app_key
self.app_secret = app_secret # 接口地址
self.token_url = "https://gw.open.1688.com/openapi/http/1/system.oauth2/getToken" # 令牌接口
self.search_url = "https://gw.open.1688.com/openapi/param2/2/portals.open.api.item.search" # 搜索接口
# 令牌缓存(避免频繁请求令牌)
self.access_token = None
self.token_expire_at = 0 # 令牌过期时间(时间戳,秒)
def generate_sign(self, params):
"""生成签名(核心方法)"""
# 1. 按参数名ASCII升序排序
sorted_params = sorted(params.items(), key=lambda x: x[0])
# 2. 拼接参数(key+value)
sign_str = ""
for key, value in sorted_params:
# 注意:参数值需转为字符串,避免类型问题
sign_str += f"{key}{str(value)}"
# 3. 追加app_secret并MD5加密
sign_str += self.app_secret
sign = hashlib.md5(sign_str.encode("utf-8")).hexdigest().upper()
return sign def get_access_token(self):
"""获取/刷新access_token(自动判断有效期)"""
# 检查令牌是否有效(提前60秒刷新,避免过期)
current_time = time.time()
if self.access_token and current_time < self.token_expire_at - 60:
return self.access_token # 客户端模式参数
token_params = {
"grant_type": "client_credentials",
"client_id": self.app_key,
"client_secret": self.app_secret }
try:
response = requests.post(
url=self.token_url,
data=token_params,
timeout=10,
headers={"Content-Type": "application/x-www-form-urlencoded"}
)
response.raise_for_status() # 触发HTTP错误(如404、500)
result = response.json()
# 处理令牌请求错误
if "error" in result:
raise Exception(f"令牌请求失败:{result['error_description']}")
# 缓存令牌和过期时间
self.access_token = result["access_token"]
self.token_expire_at = current_time + int(result["expires_in"])
print(f"令牌获取成功,有效期至:{time.ctime(self.token_expire_at)}")
return self.access_token except Exception as e:
raise Exception(f"获取access_token异常:{str(e)}")
def item_search(self, keywords, page=1, page_size=20, **kwargs):
"""
按关键字搜索商品(核心业务方法)
:param keywords: 搜索关键字(必填)
:param page: 页码(默认1)
:param page_size: 每页条数(默认20,最大50)
:param kwargs: 可选参数(如categoryId、priceStart、sort等)
:return: 搜索结果(字典)
"""
# 1. 获取有效令牌
token = self.get_access_token()
# 2. 组装公共参数
common_params = {
"app_key": self.app_key,
"access_token": token,
"method": "portals.open.api.item.search",
"format": "json",
"v": "1.0",
"timestamp": str(int(current_time * 1000)), # 毫秒级时间戳
"keywords": keywords,
"page": page,
"pageSize": page_size }
# 3. 合并可选参数(kwargs)
all_params = {**common_params, **kwargs}
# 移除值为None的可选参数(避免无效参数)
all_params = {k: v for k, v in all_params.items() if v is not None}
# 4. 生成签名
all_params["sign"] = self.generate_sign(all_params)
# 5. 发送搜索请求
try:
response = requests.post(
url=self.search_url,
data=all_params,
timeout=15,
headers={"Content-Type": "application/x-www-form-urlencoded"}
)
response.raise_for_status()
result = response.json()
# 6. 处理响应
if "error_response" in result:
error = result["error_response"]
return {
"success": False,
"error_code": error.get("code"),
"error_msg": error.get("msg"),
"request_id": error.get("requestId") # 用于1688技术支持排查问题
}
# 提取商品数据
search_data = result["item_search_response"]
total_items = search_data.get("totalCount", 0) # 总商品数
item_list = search_data.get("items", {}).get("item", []) # 商品列表
return {
"success": True,
"total_count": total_items,
"page": page,
"page_size": page_size,
"total_pages": (total_items + page_size - 1) // page_size, # 总页数
"items": item_list }
except Exception as e:
return {
"success": False,
"error_msg": f"搜索请求异常:{str(e)}"
}# ------------------------------# 使用示例# ------------------------------if __name__ == "__main__":
# 替换为自己的app_key和app_secret
APP_KEY = "your_app_key"
APP_SECRET = "your_app_secret"
# 初始化API客户端
api = AlibabaSearchApi(APP_KEY, APP_SECRET)
# 搜索“纯棉T恤”,第1页,20条/页,价格10-50元,按销量降序
search_result = api.item_search(
keywords="纯棉T恤",
page=1,
page