简介:这份《Temu Api对接指南》面向需要将第三方ERP系统接入Temu平台的跨境电商卖家、ERP服务商及技术对接人员,帮助解决商品管理、订单处理、库存同步等环节的对接难题。文档梳理了半托管与全托管店铺的对接前提、2024年5月28日后的政策变更,并列出康特恩、指纹、千易、兴数、壹号云、店小秘、领星、马帮、通途等常用ERP的适用场景与功能限制,例如领星仅支持打单、上品建议改用店小秘,全托管店铺需上新满100件方可申请。资源包为1个PDF文件,约641KB,内容涵盖后台自行申请流程、订单履约权限授权、子店铺维度对接、自研功能10000元预备金说明及售后联系方式。目前已有2254人学习,适合希望快速理清对接路径、规避常见坑点的从业者参考。
1. Temu API 对接:从零到跑通第一单订单同步
很多做跨境电商 ERP 的团队,第一次接 Temu 开放平台时都会卡在同一个地方:文档看完了,App Key 和 App Secret 也申请下来了,但真到写代码调接口那一刻,签名算不对、Token 拿不到、订单拉不下来。这不是能力问题,而是 Temu 的对接链路和国内常见的电商 API 有几处不太一样的地方——它把授权、签名、业务接口拆得比较清楚,任何一环没对齐,后面全是 401 和签名错误。
这篇笔记面向两类人:一是正在给自家 ERP 或进销存系统加 Temu 渠道的开发者,二是想用 Python 快速验证 Temu 订单、商品、库存能不能打通的技术负责人。我会按「授权怎么走 → 签名怎么算 → 订单和商品接口怎么调 → 坑在哪」的顺序,把一条能复现的最小链路讲清楚。你不需要先读完所有官方文档,跟着这里的步骤就能把第一单订单同步跑通,再回头补细节。
2. Temu 开放平台的授权链路与签名机制
2.1 先搞清楚 Temu API 的三种凭证
Temu 开放平台(Temu Open Platform)的调用凭证分三层,很多人一上来就把它们搞混,导致后面签名怎么算都不对。
第一层是 App Key 和 App Secret,这是你在开放平台创建应用时拿到的,相当于应用的身份。App Key 是公开的,App Secret 绝对不能泄露,所有签名都靠它。
第二层是 access_token,这是店铺维度的授权凭证。Temu 的接口分两类:一类是平台级接口,比如查类目、查物流商,用 App Key 加签名就能调;另一类是店铺级接口,比如拉订单、改库存、发货,必须带上 access_token,而且这个 token 是绑定到具体店铺的。
第三层是签名 sign,每次请求都要现算,不是固定值。Temu 用的是 MD5 签名,把参数按规则拼成字符串,加上 App Secret,再 MD5 一次。
常见做法是:先用 App Key 和 App Secret 换 access_token,把 token 按店铺存到数据库,设置过期时间,后面所有店铺级接口都从数据库取 token。我一般会在 token 表里加一列 refresh_time,提前半小时刷新,避免请求打到一半 token 过期。
2.2 授权换 Token 的完整请求
Temu 的 token 获取接口是 POST 请求,参数放在 body 里,格式是 JSON。下面是一个最小可运行的 Python 示例,用的是 requests 库。
import hashlib import time import requests import json APP_KEY = "your_app_key" APP_SECRET = "your_app_secret" BASE_URL = "https://openapi.kuajingmaihuo.com/openapi/router" def calc_sign(params: dict, secret: str) -> str: """Temu MD5 签名:按 key 字典序拼接,首尾加 secret,再 MD5""" sorted_keys = sorted(params.keys()) raw = secret for k in sorted_keys: v = params[k] if v is None or v == "": continue raw += k + str(v) raw += secret return hashlib.md5(raw.encode("utf-8")).hexdigest().upper() def get_access_token(code: str) -> dict: params = { "type": "bg.open.accesstoken.info.get", "appKey": APP_KEY, "code": code, "timestamp": str(int(time.time())), } params["sign"] = calc_sign(params, APP_SECRET) resp = requests.post(BASE_URL, json=params, timeout=10) return resp.json() if __name__ == "__main__": # code 是从授权回调里拿到的临时码,只能用一次 result = get_access_token("callback_code_here") print(json.dumps(result, indent=2, ensure_ascii=False))这段代码有三个关键点。第一,calc_sign 里拼接顺序是「secret + 按 key 排序的 k+v + secret」,不是常见的「k+v+secret」,这是 Temu 签名最容易翻车的地方。第二,timestamp 是秒级时间戳,不是毫秒,和 Temu 服务器时间差超过 5 分钟会直接报签名过期。第三,code 只能用一次,换完 token 就失效,所以回调接口里拿到 code 要立刻换 token 并落库。
参数说明:type 是接口路由标识,Temu 所有接口都走同一个 BASE_URL,靠 type 区分具体方法。appKey 就是你的 App Key。code 是 OAuth 回调带回来的临时授权码。sign 是上面算出来的签名。
2.3 签名计算的三个边界条件
签名算不对,90% 是下面三种情况之一。
第一种,参数值为空。Temu 的规则是:值为 null 或空字符串的参数,不参与签名拼接。但很多语言里空字符串和 null 处理不一样,Python 里""和None都要跳过,Java 里还要注意"null"字符串这种脏数据。
第二种,参数值类型。数字要转成字符串再拼,布尔值要转成"true"或"false",不能直接拼 Python 的True。我见过有人把True拼进去,签名一直对不上,查了两小时。
第三种,中文和特殊字符。Temu 要求 UTF-8 编码后再 MD5,如果你的参数里有中文商品名,编码不对签名必错。建议在 calc_sign 里统一用str(v).encode("utf-8")。
提示:调试签名时,先把拼接前的原始字符串打印出来,和官方文档的示例对比。Temu 文档里每个接口都有签名示例,这是最快的排查方式。
3. 订单、商品、库存三类核心接口的调用方式
3.1 拉取订单列表的分页与时间窗口
订单接口是 ERP 对接 Temu 最核心的一个,type 是bg.order.list.v2.get。它有两个硬约束:一是必须传时间范围,二是分页有上限。
def fetch_orders(access_token: str, start_time: int, end_time: int, page: int = 1): params = { "type": "bg.order.list.v2.get", "appKey": APP_KEY, "accessToken": access_token, "timestamp": str(int(time.time())), "startTime": str(start_time), # 秒级时间戳 "endTime": str(end_time), "page": str(page), "pageSize": "50", # 最大 50,别贪多 } params["sign"] = calc_sign(params, APP_SECRET) resp = requests.post(BASE_URL, json=params, timeout=15) data = resp.json() if not data.get("success"): raise RuntimeError(f"Temu order fetch failed: {data}") return data["result"]时间窗口我一般设成 24 小时,因为 Temu 订单状态变更频繁,窗口太大容易漏掉状态更新,太小又请求太多次。pageSize 最大 50,设大了接口会直接报参数错误。分页要一直翻到返回列表为空为止,不要只取第一页。
订单返回里有个字段叫parentOrderSn和orderSn,前者是父单,后者是子单。Temu 支持一个父单拆多个子单发货,ERP 入库时要把父子关系存好,否则发货时会对不上。
3.2 商品接口的 SKU 映射
商品接口 type 是bg.goods.list.get,返回的是店铺在售商品列表。这里最大的坑是 SKU 编码:Temu 的 SKU 是平台生成的,和你自己 ERP 里的 SKU 不是一回事。
我一般会建一张映射表,字段包括:temu_sku_id、temu_goods_id、erp_sku_code、shop_id、update_time。每次拉商品列表时,用temu_sku_id去匹配,匹配不上就标记为「待映射」,人工确认一次,后面就自动了。
CREATE TABLE temu_sku_mapping ( id BIGINT PRIMARY KEY AUTO_INCREMENT, shop_id VARCHAR(64) NOT NULL, temu_goods_id VARCHAR(64) NOT NULL, temu_sku_id VARCHAR(64) NOT NULL, erp_sku_code VARCHAR(64), status TINYINT DEFAULT 0, -- 0 待映射 1 已映射 update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_sku (shop_id, temu_sku_id) );这张表是 ERP 对接 Temu 的地基,库存同步、订单发货都靠它。建议在 temu_sku_id 上加唯一索引,避免重复插入。
3.3 库存同步的幂等设计
库存接口 type 是bg.goods.stock.update,用来把 ERP 的库存推到 Temu。这个接口必须做幂等,因为网络超时重试很常见。
我的做法是:每次推送前,先在本地记一条stock_sync_log,包含shop_id、temu_sku_id、target_stock、request_id。request_id 用 UUID,推送时带上,Temu 侧如果收到重复 request_id 会直接返回上次结果,不会重复扣减。
import uuid def push_stock(access_token, temu_sku_id, stock): request_id = str(uuid.uuid4()) params = { "type": "bg.goods.stock.update", "appKey": APP_KEY, "accessToken": access_token, "timestamp": str(int(time.time())), "skuId": temu_sku_id, "stock": str(stock), "requestId": request_id, } params["sign"] = calc_sign(params, APP_SECRET) resp = requests.post(BASE_URL, json=params, timeout=10) return resp.json()参数说明:skuId 是 Temu 的 SKU,不是你的 ERP SKU。stock 是目标库存,不是增量。requestId 是幂等键,建议用 UUID 并落库,重试时复用同一个。
注意:库存推送频率别太高,Temu 对单店铺有 QPS 限制,常见做法是合并变更,每 5 分钟推一次全量差异,而不是每次库存变动都推。
4. Temu API 对接的避坑与排查清单
4.1 签名报错:sign invalid 的四种原因
现象:接口返回sign invalid或签名错误。
原因一:拼接顺序错了。Temu 是 secret 开头和结尾,不是只结尾。原因二:空值没跳过。原因三:timestamp 和服务器差太多。原因四:参数里有中文没做 UTF-8。
解决:把 calc_sign 里的原始字符串打印出来,和官方示例逐字符对比。我一般会在测试环境加一个 debug 开关,签名失败时把 raw 字符串写日志。
4.2 Token 过期:401 与 accessToken invalid
现象:接口返回 401 或accessToken invalid。
原因:access_token 过期,或者 token 和店铺不匹配。Temu 的 token 默认有效期是 7 天,但实际可能更短。
解决:在 token 表里存 expire_time,每次请求前检查,剩余时间小于 1 小时就刷新。刷新用 refresh_token,不要重新走授权。如果 refresh_token 也过期,只能让商家重新授权。
4.3 订单漏单:时间窗口与状态过滤
现象:ERP 里订单比 Temu 后台少。
原因一:时间窗口没覆盖,比如只拉了「待发货」,漏了「已发货」的状态变更。原因二:分页没翻完。原因三:时区问题,Temu 返回的是 UTC 时间,你按本地时间过滤就错了。
解决:拉订单时不要按状态过滤,全量拉回来在本地按状态分类。时间统一用 UTC 秒级时间戳。分页用 while 循环,直到返回空列表。
4.4 库存超卖:并发推送与幂等失效
现象:Temu 前台显示有货,实际 ERP 已经没库存,导致超卖。
原因:多个进程同时推库存,或者 requestId 没落库,重试时生成了新 requestId。
解决:库存推送走单线程队列,或者用分布式锁按 shop_id 加锁。requestId 必须落库,重试时从库里取原值。
4.5 接口限流:QPS 超限与退避策略
现象:接口返回rate limit或请求过于频繁。
原因:短时间内请求太多,Temu 对每个 appKey 和店铺都有 QPS 限制。
解决:在 HTTP 客户端加令牌桶限流,我一般设成单店铺 5 QPS。遇到限流错误时,用指数退避重试,第一次等 1 秒,第二次 2 秒,最多重试 3 次。
5. 用 Python 封装一个可复用的 Temu 客户端
5.1 把签名、Token、重试收进一个类
前面每个接口都手写签名和请求太啰嗦,实际项目里我会封装一个 TemuClient 类,把公共逻辑收进去。
class TemuClient: def __init__(self, app_key, app_secret, base_url): self.app_key = app_key self.app_secret = app_secret self.base_url = base_url self.session = requests.Session() def _sign(self, params): sorted_keys = sorted(params.keys()) raw = self.app_secret for k in sorted_keys: v = params[k] if v is None or v == "": continue raw += k + str(v) raw += self.app_secret return hashlib.md5(raw.encode("utf-8")).hexdigest().upper() def call(self, api_type, access_token=None, **kwargs): params = { "type": api_type, "appKey": self.app_key, "timestamp": str(int(time.time())), } if access_token: params["accessToken"] = access_token params.update({k: str(v) for k, v in kwargs.items() if v is not None}) params["sign"] = self._sign(params) for attempt in range(3): try: resp = self.session.post(self.base_url, json=params, timeout=15) data = resp.json() if data.get("success"): return data["result"] if "rate" in str(data).lower(): time.sleep(2 ** attempt) continue raise RuntimeError(f"Temu API error: {data}") except requests.RequestException: if attempt == 2: raise time.sleep(2 ** attempt)这个类做了三件事:签名统一算、token 可选传、失败自动重试。重试只针对网络异常和限流,业务错误直接抛,避免掩盖问题。
参数说明:api_type 是 Temu 的接口路由,比如bg.order.list.v2.get。access_token 是店铺级接口必传,平台级接口可以不传。kwargs 是各接口自己的业务参数,统一转成字符串。
5.2 用配置表管理多店铺 Token
多店铺场景下,token 不能写死在代码里。我一般用一张 shop_auth 表管理。
CREATE TABLE shop_auth ( shop_id VARCHAR(64) PRIMARY KEY, shop_name VARCHAR(128), access_token TEXT, refresh_token TEXT, expire_time DATETIME, status TINYINT DEFAULT 1, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );每次调用店铺级接口前,从这张表取 token,检查 expire_time,快过期就刷新。刷新逻辑单独写一个 refresh_token 方法,刷新成功后更新表。
5.3 用日志定位签名和限流问题
Temu 对接出问题时,日志是唯一的后悔药。我会在 call 方法里加两个日志点:请求前打印 params(去掉 sign 和 token),响应后打印 success 和 error_msg。
import logging logging.basicConfig(level=logging.INFO) # 请求前 logging.info("Temu request type=%s params=%s", api_type, {k: v for k, v in params.items() if k not in ("sign", "accessToken")}) # 响应后 logging.info("Temu response type=%s success=%s msg=%s", api_type, data.get("success"), data.get("errorMsg"))这样签名错了能对比参数,限流了能看到频率,token 过期了能看到错误码。别小看这两行日志,排查 Temu 问题时能省一半时间。
5.4 验证对接是否成功的三个检查点
第一,用测试店铺拉一单订单,确认 orderSn、parentOrderSn、skuId 都能正确解析。第二,推一次库存,去 Temu 后台看库存数字有没有变。第三,模拟 token 过期,看刷新逻辑能不能自动恢复。
这三个检查点过了,基本对接就算跑通了。剩下的就是按业务补接口,比如发货、退款、物流回传。
我自己的习惯是:每接一个新渠道,先写一个最小验证脚本,把授权、签名、一个业务接口跑通,再往 ERP 里集成。Temu 这个渠道,签名和 token 是两道坎,跨过去后面就顺了。希望帮到你。
本文还有配套的精品资源,点击获取