OpenAPI 调用指南
抖音小程序 OpenAPI 是抖音开放平台为开发者提供的,可让外部程序访问抖音小程序特定功能和资源的 API。借助这些接口,开发者能突破小程序限制,与抖音生态深度交互,拓展功能边界,为用户带来更优体验。例如,可获取用户授权信息实现个性化服务,或对接抖音其他功能提升操作流畅性。
使用场景
- 1.社交互动场景:通过 OpenAPI,小程序可获取用户抖音账号的粉丝数、关注列表、点赞评论记录等信息。比如社交类小程序,能依据这些数据为用户推荐可能认识的人、兴趣相投的抖音好友,或者基于用户点赞评论过的内容,精准推送相关话题讨论组,增强用户间互动,提升小程序社交活跃度。以一款抖音小程序 “趣友圈” 为例,它利用 OpenAPI 获取用户抖音点赞数据,为用户匹配相同兴趣爱好的人,建立聊天群组,用户月均互动时长增长了 30%。
- 2.内容创作与推广场景:开发者可调用 OpenAPI 将小程序内优质内容,如文章、视频等,直接分享至用户抖音账号,借助抖音庞大流量池实现内容快速传播。同时,能获取内容在抖音上的传播数据,如播放量、转发数、评论数等,依据数据反馈优化内容创作与推广策略。例如 “创意视频秀” 小程序,使用 OpenAPI 分享用户创作视频到抖音,视频平均播放量提升了 5 倍,新增用户注册量月环比增长 25%。
- 3.电商交易场景:在电商小程序中,OpenAPI 发挥着关键作用。它支持获取用户在抖音内的收货地址、支付信息等,简化购物流程,提升购买转化率。还能实现订单状态同步,用户在抖音内就能随时查看小程序电商订单物流进度。像 “抖品优选” 电商小程序接入 OpenAPI 后,支付成功率从 70% 提升至 85%,用户复购率提高了 15%。
类型
API 类型 | 功能描述 | 示例效果 |
用户信息类 API | 用于获取用户在抖音平台的基础信息,如头像、昵称、性别、地区等,以及用户授权的更详细信息,如手机号、粉丝列表等。有助于小程序为用户提供个性化服务,增强用户对小程序的认同感和归属感。 | “个性装扮” 小程序通过获取用户性别、地区信息,为用户精准推荐符合当地风格和个人喜好的装扮方案,用户留存率提高了 20%。 |
内容管理类 API | 允许开发者对小程序内内容进行创建、编辑、删除、查询等操作,同时可将内容分享至抖音平台,并获取分享后的反馈数据。 | 某 “热点快报” 小程序使用内容管理类 API 分享新闻后,日访问量增长了 40%。 |
交易类 API | 涵盖电商交易全流程,包括创建订单、查询订单状态、处理支付、退款等功能。确保电商小程序交易的稳定性和流畅性,为用户提供安全可靠的购物环境。 | “美妆商城” 小程序接入交易类 API 后,交易成功率提升了 12%,用户投诉率降低了 30%。 |
数据分析类 API | 提供小程序运营数据统计分析功能,如访问量、用户留存率、页面浏览路径、用户行为分析等。开发者依据这些数据洞察用户需求,优化小程序功能和用户体验。 | “运动健身” 小程序通过数据分析类 API 发现用户在特定课程页面停留时间长,增加相关课程推荐后,课程购买转化率提高了 18%。 |
通用调用指南
注意事项
- •凭证安全:
- ◦ClientSecret 严禁暴露在前端代码中,必须在后端服务器处理。
- ◦建议将 access_token 存储在 Redis 或数据库中,并设置过期时间。
- •调用频率限制:
- ◦应用级 access_token 每日限调用 2000 次,需缓存复用。
- ◦部分 API 有单独的频率限制,需参考官方文档。
申请权限
在调用任何 OpenAPI 前,必须先申请并获得对应的接口权限。抖音开放平台通过权限管理确保数据安全和合规使用,不同类型的 API(如用户信息、交易、内容分享等)需单独申请。
注意
- •避免超范围使用:仅在申请场景中使用权限,例如不得将“获取手机号”权限用于非客服沟通场景。
- •定期检查权限状态:在控制台实时查看权限是否被封禁或过期(部分权限可能因政策调整更新)。
- 1.登录开放平台:访问 抖音开放平台控制台,选择目标小程序应用。
- 2.选择能力权限:在应用详情页左侧导航栏进入「能力管理」,根据API类型(如「用户信息-获取手机号」「交易-订单创建」等)找到对应的权限项。
- 3.提交申请材料:点击「申请开通」,填写清晰的使用场景说明(例如:“用户在小程序内下单时需校验收货地址,需申请‘获取用户收货地址’权限”)、上传场景示意图(如交互流程图),确保符合《抖音开放平台开发者协议》。
- 4.等待审核:审核通常在 1~3 个工作日内完成,通过后权限状态显示为「已开通」。
步骤一:获取用户临时登录凭证(code)
- 1.在小程序前端代码中,调用 tt.login 获取用户临时登录凭证
code
。// pages/index.js tt.login({ success: (res) => { if (res.code) { // 将 code 发送到后端服务器 tt.request({ url: 'https://your-server.com/api/auth', method: 'POST', data: { code: res.code }, success: (res) => { console.log('登录成功,获取到用户身份:', res.data); }, fail: (err) => { console.error('登录失败:', err); } }); } else { console.error('获取 code 失败:', res.errMsg); } }, fail: (err) => { console.error('调用 tt.login 失败:', err); } });
- 2.(可选)若需获取用户敏感信息(如手机号、昵称),需先引导用户授权。
// 示例:获取用户信息授权 tt.getUserInfo({ success: (res) => { console.log('用户信息:', res.userInfo); }, fail: (err) => { console.error('用户拒绝授权:', err); } });
步骤二:获取 open_id 和 access_token
import com.aliyun.tea.TeaException; import com.douyin.openapi.client.Client; import com.douyin.openapi.client.models.*; import com.douyin.openapi.credential.models.Config; public class Main { public static void main(String[] args) { try { Config config = new Config().setClientKey("tt******").setClientSecret("cbs***"); // 改成自己的app_id跟secret Client client = new Client(config); /* 构建请求参数,该代码示例中只给出部分参数,请用户根据需要自行构建参数值 token: 1.若用户自行维护token,将用户维护的token赋值给该参数即可 2.SDK包中有获取token的函数,请根据接口path在《OpenAPI SDK 总览》文档中查找获取token函数的名字 在使用过程中,请注意token互刷问题 header: sdk中默认填充content-type请求头,若不需要填充除content-type之外的请求头,删除该参数即可 */ V2Jscode2sessionRequest sdkRequest = new V2Jscode2sessionRequest(); sdkRequest.setAnonymousCode("EpFjYuaoOl"); sdkRequest.setAppid("tt4233**"); sdkRequest.setCode("YAH9JFcEc4"); sdkRequest.setSecret("83Soi1UKQ6"); V2Jscode2sessionResponse sdkResponse = client.V2Jscode2session(sdkRequest); } catch (TeaException e) { System.out.println(e.getMessage()); } catch (Exception e) { System.out.println(e.getMessage()); } } }
区分两种 access_token 类型
- •用户级 access_token:通过
code2session
接口获取,与特定用户关联,用于调用用户相关 API(如获取用户信息)。- •应用级 access_token:通过 client_credential 接口获取,全局唯一,用于调用无用户身份的 API(如获取小程序配置)。
# 获取应用级 access_token def get_app_access_token(): url = f"https://developer.toutiao.com/api/apps/token" params = { "appid": CLIENT_KEY, "secret": CLIENT_SECRET, "grant_type": "client_credential" } response = requests.get(url, params=params) result = response.json() if "access_token" in result: return result["access_token"] else: raise Exception(f"获取应用级 access_token 失败: {result}")
步骤三:使用 access_token 调用 OpenAPI
用户级 API 调用示例(获取用户信息)
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import com.alibaba.fastjson.JSONObject; public class DouyinUserApi { // 替换为你的应用凭证 private static final String APP_ID = "your_app_id"; private static final String APP_SECRET = "your_app_secret"; // API 接口地址 private static final String TOKEN_URL = "https://developer.toutiao.com/api/apps/jscode2session"; private static final String REFRESH_TOKEN_URL = "https://developer.toutiao.com/api/apps/refresh_token"; private static final String USER_INFO_URL = "https://developer.toutiao.com/api/user/info"; /** * 使用 code 获取 session 信息(含 access_token 和 open_id) */ public static JSONObject getSessionByCode(String code) { try { String url = TOKEN_URL + "?" + "appid=" + URLEncoder.encode(APP_ID, StandardCharsets.UTF_8) + "&secret=" + URLEncoder.encode(APP_SECRET, StandardCharsets.UTF_8) + "&js_code=" + URLEncoder.encode(code, StandardCharsets.UTF_8) + "&grant_type=authorization_code"; return sendGetRequest(url); } catch (Exception e) { System.err.println("获取 session 失败: " + e.getMessage()); return null; } } /** * 刷新 access_token */ public static JSONObject refreshAccessToken(String refreshToken) { try { String url = REFRESH_TOKEN_URL + "?" + "appid=" + URLEncoder.encode(APP_ID, StandardCharsets.UTF_8) + "&grant_type=refresh_token" + "&refresh_token=" + URLEncoder.encode(refreshToken, StandardCharsets.UTF_8); return sendGetRequest(url); } catch (Exception e) { System.err.println("刷新 access_token 失败: " + e.getMessage()); return null; } } /** * 获取用户信息 */ public static JSONObject getUserInfo(String accessToken, String openId) { try { String url = USER_INFO_URL + "?" + "access_token=" + URLEncoder.encode(accessToken, StandardCharsets.UTF_8) + "&open_id=" + URLEncoder.encode(openId, StandardCharsets.UTF_8); return sendGetRequest(url); } catch (Exception e) { System.err.println("获取用户信息失败: " + e.getMessage()); return null; } } /** * 发送 HTTP GET 请求 */ private static JSONObject sendGetRequest(String url) throws IOException { URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); // 设置请求头和超时 con.setRequestMethod("GET"); con.setConnectTimeout(5000); con.setReadTimeout(5000); // 获取响应 int responseCode = con.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { BufferedReader in = new BufferedReader(new InputStreamReader( con.getInputStream(), StandardCharsets.UTF_8)); String inputLine; StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); return JSONObject.parseObject(response.toString()); } else { System.err.println("HTTP 请求失败,状态码: " + responseCode); return null; } } /** * 示例调用流程 */ public static void main(String[] args) { // 1. 从前端获取 code(实际开发中由前端传递) String code = "code_from_frontend"; // 2. 使用 code 获取 session 信息 JSONObject sessionInfo = getSessionByCode(code); if (sessionInfo == null || sessionInfo.containsKey("errcode")) { System.err.println("获取 session 失败: " + sessionInfo); return; } String accessToken = sessionInfo.getString("access_token"); String openId = sessionInfo.getString("openid"); String refreshToken = sessionInfo.getString("refresh_token"); System.out.println("获取 access_token 成功: " + accessToken); // 3. 使用 access_token 获取用户信息 JSONObject userInfo = getUserInfo(accessToken, openId); if (userInfo != null && !userInfo.containsKey("errcode")) { System.out.println("用户信息: " + userInfo.toJSONString()); } else { System.err.println("获取用户信息失败: " + userInfo); // 4. 尝试刷新 access_token(假设原 token 已过期) JSONObject refreshedToken = refreshAccessToken(refreshToken); if (refreshedToken != null && !refreshedToken.containsKey("errcode")) { accessToken = refreshedToken.getString("access_token"); System.out.println("刷新 access_token 成功: " + accessToken); // 5. 使用新的 access_token 再次尝试获取用户信息 userInfo = getUserInfo(accessToken, openId); if (userInfo != null && !userInfo.containsKey("errcode")) { System.out.println("刷新后获取用户信息成功: " + userInfo.toJSONString()); } } } } }
应用级 API 调用示例(获取小程序配置)
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import com.alibaba.fastjson.JSONObject; public class DouyinAppApi { // 替换为你的应用凭证 private static final String APP_ID = "your_app_id"; private static final String APP_SECRET = "your_app_secret"; // API 接口地址 private static final String APP_TOKEN_URL = "https://developer.toutiao.com/api/apps/token"; private static final String USER_INFO_URL = "https://developer.toutiao.com/api/user/info"; // 缓存应用级 access_token private static String appAccessToken; private static long tokenExpireTime = 0; /** * 获取应用级 access_token(自动缓存并刷新) */ public static String getAppAccessToken() throws IOException { // 检查缓存的 token 是否有效(提前 5 分钟刷新) if (appAccessToken != null && System.currentTimeMillis() < tokenExpireTime - 5 * 60 * 1000) { return appAccessToken; } // 构建请求 URL String url = APP_TOKEN_URL + "?" + "appid=" + URLEncoder.encode(APP_ID, StandardCharsets.UTF_8) + "&secret=" + URLEncoder.encode(APP_SECRET, StandardCharsets.UTF_8) + "&grant_type=client_credential"; // 发送请求 JSONObject response = sendGetRequest(url); if (response == null || response.containsKey("errcode")) { throw new IOException("获取应用级 access_token 失败: " + response); } // 缓存 token 和过期时间 appAccessToken = response.getString("access_token"); int expiresIn = response.getIntValue("expires_in"); tokenExpireTime = System.currentTimeMillis() + expiresIn * 1000; return appAccessToken; } /** * 获取用户信息(应用级 API) */ public static JSONObject getUserInfo(String openId) throws IOException { // 获取应用级 access_token String accessToken = getAppAccessToken(); // 构建请求 URL String url = USER_INFO_URL + "?" + "access_token=" + URLEncoder.encode(accessToken, StandardCharsets.UTF_8) + "&open_id=" + URLEncoder.encode(openId, StandardCharsets.UTF_8); // 发送请求 return sendGetRequest(url); } /** * 发送 HTTP GET 请求 */ private static JSONObject sendGetRequest(String url) throws IOException { URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); // 设置请求头和超时 con.setRequestMethod("GET"); con.setConnectTimeout(5000); con.setReadTimeout(5000); // 获取响应 int responseCode = con.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { BufferedReader in = new BufferedReader(new InputStreamReader( con.getInputStream(), StandardCharsets.UTF_8)); String inputLine; StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); return JSONObject.parseObject(response.toString()); } else { // 读取错误信息 BufferedReader errorReader = new BufferedReader(new InputStreamReader( con.getErrorStream(), StandardCharsets.UTF_8)); String errorLine; StringBuilder errorResponse = new StringBuilder(); while ((errorLine = errorReader.readLine()) != null) { errorResponse.append(errorLine); } errorReader.close(); throw new IOException("HTTP 请求失败,状态码: " + responseCode + ", 错误信息: " + errorResponse.toString()); } } /** * 示例调用流程 */ public static void main(String[] args) { try { // 用户的 open_id(从数据库或其他途径获取) String openId = "user_open_id"; // 获取用户信息 JSONObject userInfo = getUserInfo(openId); if (userInfo != null && !userInfo.containsKey("errcode")) { System.out.println("用户信息获取成功:"); System.out.println("昵称: " + userInfo.getString("nickname")); System.out.println("头像: " + userInfo.getString("avatar")); // 其他字段... } else { System.err.println("获取用户信息失败: " + userInfo); } } catch (IOException e) { System.err.println("调用 API 异常: " + e.getMessage()); } } }
通过以上流程,开发者可以完整实现抖音小程序 OpenAPI 的调用,从创建应用到获取用户身份,再到调用具体 API 功能。
常见问题
access_token 相关问题
- •过期问题:由于 access_token 有效期较短,若在调用 API 时频繁出现 “access_token 过期” 错误,开发者需优化获取和存储 access_token 的逻辑。可采用缓存机制,如在服务器端使用 Redis 缓存 access_token,每次调用 API 前先检查缓存中是否存在有效 token,若存在则直接使用,若不存在或已过期再重新获取。
- •获取失败问题:当获取 access_token 返回错误时,需验证三项要素:
- a.appid 与开放平台注册一致。
- b.secret 密钥未重置。
- c.网络策略开 放抖音 API 域名,检查网络连接是否正常。同时,可查看错误信息提示,如 “invalid appid” 表示 appid 错误,需及时更正。
调用频率限制问题
抖音开放平台对部分 OpenAPI 设置了调用频率限制,以防止恶意请求和保障平台稳定性。若调用 API 时收到 “调用频率超限” 错误,开发者可考虑优化业务逻辑,减少不必要的 API 调用。例如在获取用户信息时,若短时间内多次重复获取相同用户信息,可将首次获取的信息缓存起来,后续直接从缓存读取。若业务确实需要较高调用频率,可在抖音开放平台申请提升配额,提交详细的业务需求说明和合理的调用频率规划,等待平台审核通过。
- •默认限流:单个接口 1000次/分钟(具体以文档为准)
- •解决方案:
- ◦增加请求间隔 + 失败重试机制
- ◦申请提升配额(需企业认证)
权限相关问题
- •权限审核驳回:当权限申请被驳回时,开放平台会反馈具体驳回原因代码。开发者应当:
- a.对照驳回代码检查申报材料。
- b.补充场景示意图和技术实现文档。
- c.重新提交申请,确保符合平台要求。例如若因场景示意图不清晰未通过,需重新绘制清晰展示权限使用流程的示意图,并补充更详细的文字说明。
- •权限被封禁:若在使用权限过程中违反平台规则,如滥用用户信息、进行未经授权的数据处理等,权限可能会被封禁。此时需立即停止违规操作,按照平台要求进行整改,并提交整改报告申请解封。整改过程中要深入学习平台规则,确保后续合规使用权限。