API 签名是电商平台验证请求合法性的核心机制,新手常因复杂的签名规则而卡住。本文用 5 分钟带你掌握京东 / 淘宝 API 签名的核心逻辑,附带完整 Python 代码,直接复用!
一、API 签名原理:为什么需要签名?
API 签名是一种防止请求被篡改的加密机制。通过将请求参数、时间戳和密钥组合加密,服务器可以验证:
- 请求是否来自合法应用(通过 AppKey 和 AppSecret 验证)
- 请求参数是否在传输过程中被修改
- 请求是否过期(通过时间戳判断)
二、京东 API 签名:分步实现
1. 签名规则
- 参数排序:按参数名 ASCII 码从小到大排序
- 字符串拼接:AppSecret + 排序后的参数字符串 + AppSecret
- 加密方式:MD5 加密,转换为大写
2. Python 实现
python
运行
python
import hashlib
import time
import json
def generate_jd_sign(params, app_secret):
"""生成京东API签名"""
# 步骤1:排序参数
sorted_params = sorted(params.items(), key=lambda x: x[0])
# 步骤2:拼接参数字符串
sign_str = app_secret
for k, v in sorted_params:
sign_str += f"{k}{v}"
sign_str += app_secret
# 步骤3:MD5加密并转大写
sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
return sign
# 示例:生成商品搜索API的签名
app_key = "你的AppKey"
app_secret = "你的AppSecret"
method = "jingdong.search.v3.product.search"
# 公共参数
common_params = {
"app_key": app_key,
"method": method,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
"format": "json",
"v": "2.0",
"sign_method": "md5"
}
# 业务参数
biz_params = {
"keyword": "手机",
"page": 1,
"pageSize": 10
}
# 合并所有参数
all_params = {**common_params, **biz_params}
# 生成签名
sign = generate_jd_sign(all_params, app_secret)
print(f"生成的签名: {sign}")
三、淘宝 API 签名:分步实现
1. 签名规则
- 参数排序:按参数名 ASCII 码从小到大排序(不含 sign 本身)
- 字符串拼接:AppSecret + 排序后的参数字符串 + AppSecret
- 加密方式:MD5 加密,转换为大写
- 特殊要求:中文参数需 UTF-8 编码
2. Python 实现
python
运行
python
import hashlib
import time
import json
import urllib.parse
def generate_taobao_sign(params, app_secret):
"""生成淘宝API签名"""
# 步骤1:排除sign参数(如果已存在)
if "sign" in params:
params.pop("sign")
# 步骤2:排序参数
sorted_params = sorted(params.items(), key=lambda x: x[0])
# 步骤3:拼接参数字符串(中文需编码)
sign_str = app_secret
for k, v in sorted_params:
# 对参数值进行UTF-8编码
encoded_v = urllib.parse.quote(str(v), encoding='utf-8')
sign_str += f"{k}{encoded_v}"
sign_str += app_secret
# 步骤4:MD5加密并转大写
sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
return sign
# 示例:生成淘宝客商品搜索API的签名
app_key = "你的AppKey"
app_secret = "你的AppSecret"
method = "taobao.tbk.item.get"
# 公共参数
common_params = {
"app_key": app_key,
"method": method,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
"format": "json",
"v": "2.0",
"sign_method": "md5"
}
# 业务参数
biz_params = {
"q": "连衣裙", # 中文参数
"page_no": 1,
"page_size": 20,
"fields": "num_iid,title,price,pic_url"
}
# 合并所有参数
all_params = {**common_params, **biz_params}
# 生成签名
sign = generate_taobao_sign(all_params, app_secret)
print(f"生成的签名: {sign}")
四、通用 API 请求类:一键调用京东 / 淘宝 API
将签名生成和请求发送封装成一个通用类,支持京东和淘宝 API: python
运行
python
import requests
import hashlib
import time
import json
import urllib.parse
class EcommerceAPI:
def __init__(self, app_key, app_secret, api_type='jd'):
"""初始化电商API客户端"""
self.app_key = app_key
self.app_secret = app_secret
self.api_type = api_type
# 根据API类型设置不同的基础URL和签名函数
if api_type == 'jd':
self.base_url = "https://api.jd.com/routerjson"
self.sign_func = self._generate_jd_sign
elif api_type == 'taobao':
self.base_url = "https://eco.taobao.com/router/rest"
self.sign_func = self._generate_taobao_sign
else:
raise ValueError("不支持的API类型,可选值:jd, taobao")
def _generate_jd_sign(self, params):
"""生成京东API签名"""
sorted_params = sorted(params.items(), key=lambda x: x[0])
sign_str = self.app_secret
for k, v in sorted_params:
sign_str += f"{k}{v}"
sign_str += self.app_secret
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
def _generate_taobao_sign(self, params):
"""生成淘宝API签名"""
if "sign" in params:
params.pop("sign")
sorted_params = sorted(params.items(), key=lambda x: x[0])
sign_str = self.app_secret
for k, v in sorted_params:
encoded_v = urllib.parse.quote(str(v), encoding='utf-8')
sign_str += f"{k}{encoded_v}"
sign_str += self.app_secret
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
def call(self, method, params=None):
"""调用API接口"""
if params is None:
params = {}
# 添加公共参数
common_params = {
"app_key": self.app_key,
"method": method,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
"format": "json",
"v": "2.0",
"sign_method": "md5"
}
# 合并参数
all_params = {**common_params, **params}
# 生成签名
sign = self.sign_func(all_params)
all_params["sign"] = sign
# 发送请求
try:
response = requests.post(self.base_url, data=all_params, timeout=30)
response.raise_for_status()
return response.json()
except Exception as e:
print(f"API请求失败: {e}")
return None
五、使用示例:调用京东商品搜索 API
python
运行
ini
# 初始化API客户端
api = EcommerceAPI(
app_key="你的AppKey",
app_secret="你的AppSecret",
api_type='jd' # 可选 'jd' 或 'taobao'
)
# 调用京东商品搜索API
method = "jingdong.search.v3.product.search"
params = {
"keyword": "手机",
"page": 1,
"pageSize": 10
}
# 发送请求
result = api.call(method, params)
# 打印结果
if result:
print(json.dumps(result, indent=2, ensure_ascii=False))
else:
print("请求失败")
六、常见签名错误及解决方案
错误类型 | 可能原因 | 解决方案 |
---|---|---|
签名不匹配 | 参数排序错误 | 使用 sorted () 函数确保按 ASCII 码排序 |
时间戳格式错误 | 检查时间戳格式是否为 YYYY-MM-DD HH:MM:SS | |
AppSecret 错误 | 重新从平台获取 AppSecret 并确认无空格 | |
中文参数乱码 | 未对中文参数编码 | 使用 urllib.parse.quote () 进行 UTF-8 编码 |
签名验证失败 | 遗漏参数 | 确保所有参数(包括公共参数)都参与签名 |
参数值为空 | 移除值为空的参数或用空字符串占位 |
七、总结:签名生成的 3 个核心步骤
- 参数排序:按参数名 ASCII 码从小到大排序
- 字符串拼接:AppSecret + 排序后的参数字符串 + AppSecret
- MD5 加密 :对拼接后的字符串进行 MD5 加密并转换为大写 掌握这 3 个步骤,你就能轻松应对京东、淘宝等电商平台的 API 签名需求。遇到问题时,建议使用平台提供的在线调试工具验证签名,快速定位问题