beervid-app-cli 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -7
- package/SKILL.md +16 -8
- package/agents/openai.yaml +7 -0
- package/dist/cli.mjs +210 -217
- package/package.json +3 -1
- package/references/api-reference.md +605 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
# BEERVID 第三方应用 Open API — 请求/响应参考
|
|
2
|
+
|
|
3
|
+
> 本文档包含 BEERVID 面向第三方应用开放的所有端点的详细请求参数、响应结构和错误码示例。
|
|
4
|
+
> API 路径统一前缀:`/api/v1/open/`,认证方式:`X-API-KEY` 请求头。
|
|
5
|
+
|
|
6
|
+
## 目录
|
|
7
|
+
|
|
8
|
+
1. [账号授权](#1-账号授权)
|
|
9
|
+
2. [视频上传](#2-视频上传)
|
|
10
|
+
3. [视频发布](#3-视频发布)
|
|
11
|
+
4. [发布状态查询](#4-发布状态查询)
|
|
12
|
+
5. [视频数据查询](#5-视频数据查询)
|
|
13
|
+
6. [TTS 商品查询](#6-tts-商品查询)
|
|
14
|
+
7. [错误码速查表](#7-错误码速查表)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. 账号授权
|
|
19
|
+
|
|
20
|
+
### GET /api/v1/open/thirdparty-auth/tt-url
|
|
21
|
+
|
|
22
|
+
获取 TikTok 普通账号 OAuth 授权链接。
|
|
23
|
+
|
|
24
|
+
**请求:** 无参数
|
|
25
|
+
|
|
26
|
+
**响应:**
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"code": 0,
|
|
30
|
+
"success": true,
|
|
31
|
+
"message": "ok",
|
|
32
|
+
"data": "https://www.tiktok.com/v2/auth/authorize?client_key=..."
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**调用示例:**
|
|
37
|
+
```typescript
|
|
38
|
+
const { data: url } = await openApiGet<string>('/api/v1/open/thirdparty-auth/tt-url')
|
|
39
|
+
// url = "https://www.tiktok.com/v2/auth/authorize?client_key=..."
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### GET /api/v1/open/thirdparty-auth/tts-url
|
|
45
|
+
|
|
46
|
+
获取 TikTok Shop 账号 OAuth 授权链接(跨境)。
|
|
47
|
+
|
|
48
|
+
**请求:** 无参数
|
|
49
|
+
|
|
50
|
+
**响应:**
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"code": 0,
|
|
54
|
+
"success": true,
|
|
55
|
+
"message": "ok",
|
|
56
|
+
"data": {
|
|
57
|
+
"crossBorderUrl": "https://services.tiktokshop.com/open/authorize?..."
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**调用示例:**
|
|
63
|
+
```typescript
|
|
64
|
+
const { data } = await openApiGet<{ crossBorderUrl: string }>('/api/v1/open/thirdparty-auth/tts-url')
|
|
65
|
+
const url = data.crossBorderUrl
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### POST /api/v1/open/account/info
|
|
71
|
+
|
|
72
|
+
查询已授权账号的详细信息。
|
|
73
|
+
|
|
74
|
+
**请求:**
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"accountType": "TT",
|
|
78
|
+
"accountId": "7281234567890"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
83
|
+
|------|------|------|------|
|
|
84
|
+
| `accountType` | `'TT' \| 'TTS'` | 是 | 账号类型 |
|
|
85
|
+
| `accountId` | `string` | 是 | 平台返回的账号 ID |
|
|
86
|
+
|
|
87
|
+
**响应:**
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"code": 0,
|
|
91
|
+
"success": true,
|
|
92
|
+
"data": {
|
|
93
|
+
"accountType": "TT",
|
|
94
|
+
"accountId": "7281234567890",
|
|
95
|
+
"username": "creator_name",
|
|
96
|
+
"displayName": "Creator Display Name",
|
|
97
|
+
"sellerName": "",
|
|
98
|
+
"profileUrl": "https://p16-sign.tiktokcdn.com/...",
|
|
99
|
+
"followersCount": 15000,
|
|
100
|
+
"accessToken": "act.xxx...",
|
|
101
|
+
"ext": {}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| 响应字段 | 类型 | 说明 |
|
|
107
|
+
|---------|------|------|
|
|
108
|
+
| `accountType` | `string` | 账号类型 |
|
|
109
|
+
| `accountId` | `string` | 账号 ID |
|
|
110
|
+
| `username` | `string` | 用户名 |
|
|
111
|
+
| `displayName` | `string` | 显示名称 |
|
|
112
|
+
| `sellerName` | `string` | 卖家名称(TTS 账号) |
|
|
113
|
+
| `profileUrl` | `string` | 头像 URL |
|
|
114
|
+
| `followersCount` | `number` | 粉丝数 |
|
|
115
|
+
| `accessToken` | `string` | 访问令牌 |
|
|
116
|
+
| `ext` | `Record<string, unknown>` | 扩展字段 |
|
|
117
|
+
|
|
118
|
+
**调用示例:**
|
|
119
|
+
```typescript
|
|
120
|
+
const { data: accountInfo } = await openApiPost<AccountInfo>(
|
|
121
|
+
'/api/v1/open/account/info',
|
|
122
|
+
{ accountType: 'TT', accountId: '7281234567890' }
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 2. 视频上传
|
|
129
|
+
|
|
130
|
+
### POST /api/v1/open/upload-token/generate
|
|
131
|
+
|
|
132
|
+
生成视频上传凭证。
|
|
133
|
+
|
|
134
|
+
**请求:** 无 body
|
|
135
|
+
|
|
136
|
+
**响应:**
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"code": 0,
|
|
140
|
+
"success": true,
|
|
141
|
+
"data": {
|
|
142
|
+
"uploadToken": "upt.xxx...",
|
|
143
|
+
"expiresIn": 1800,
|
|
144
|
+
"message": ""
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
| 响应字段 | 类型 | 说明 |
|
|
150
|
+
|---------|------|------|
|
|
151
|
+
| `uploadToken` | `string` | 上传凭证 |
|
|
152
|
+
| `expiresIn` | `number` | 过期时间(秒) |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
### POST /api/v1/open/file-upload
|
|
157
|
+
|
|
158
|
+
上传普通视频文件(TT 账号使用)。
|
|
159
|
+
|
|
160
|
+
**请求:** `multipart/form-data`
|
|
161
|
+
|
|
162
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
163
|
+
|------|------|------|------|
|
|
164
|
+
| `file` | `File` | 是 | 视频文件 |
|
|
165
|
+
|
|
166
|
+
**请求头:** `X-UPLOAD-TOKEN`(值为上传凭证接口返回的 `uploadToken`)
|
|
167
|
+
|
|
168
|
+
**响应:**
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"code": 0,
|
|
172
|
+
"success": true,
|
|
173
|
+
"data": {
|
|
174
|
+
"fileUrl": "https://cdn.beervid.ai/uploads/xxx.mp4",
|
|
175
|
+
"fileName": "video.mp4",
|
|
176
|
+
"fileSize": 15728640,
|
|
177
|
+
"contentType": "video/mp4"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| 响应字段 | 类型 | 说明 |
|
|
183
|
+
|---------|------|------|
|
|
184
|
+
| `fileUrl` | `string` | 上传后的视频 URL,用于后续发布 |
|
|
185
|
+
| `fileName` | `string` | 文件名 |
|
|
186
|
+
| `fileSize` | `number` | 文件大小(字节) |
|
|
187
|
+
| `contentType` | `string` | MIME 类型 |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### POST /api/v1/open/file-upload/tts-video
|
|
192
|
+
|
|
193
|
+
上传挂车视频文件(TTS 账号使用)。
|
|
194
|
+
|
|
195
|
+
**请求:** `multipart/form-data`
|
|
196
|
+
|
|
197
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
198
|
+
|------|------|------|------|
|
|
199
|
+
| `file` | `File` | 是 | 视频文件 |
|
|
200
|
+
|
|
201
|
+
**Query 参数:**
|
|
202
|
+
|
|
203
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
204
|
+
|------|------|------|------|
|
|
205
|
+
| `creatorUserOpenId` | `string` | 是 | TTS 账号的 OpenId |
|
|
206
|
+
|
|
207
|
+
**响应:**
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"code": 0,
|
|
211
|
+
"success": true,
|
|
212
|
+
"data": {
|
|
213
|
+
"videoFileId": "vf_abc123def456",
|
|
214
|
+
"md5": "d41d8cd98f00b204e9800998ecf8427e",
|
|
215
|
+
"uploadType": "tts"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
| 响应字段 | 类型 | 说明 |
|
|
221
|
+
|---------|------|------|
|
|
222
|
+
| `videoFileId` | `string` | 视频文件 ID,用于后续挂车发布 |
|
|
223
|
+
| `md5` | `string` | 文件 MD5 |
|
|
224
|
+
| `uploadType` | `string` | 上传类型标识 |
|
|
225
|
+
|
|
226
|
+
**注意:** 普通上传返回 `fileUrl`,TTS 上传返回 `videoFileId`,两者用于不同的发布端点。
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 3. 视频发布
|
|
231
|
+
|
|
232
|
+
### POST /api/v1/open/tiktok/video/publish
|
|
233
|
+
|
|
234
|
+
发布普通 TikTok 视频。
|
|
235
|
+
|
|
236
|
+
**请求:**
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"businessId": "biz_12345",
|
|
240
|
+
"videoUrl": "https://cdn.beervid.ai/uploads/xxx.mp4",
|
|
241
|
+
"caption": "Check out this amazing video! #viral"
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
246
|
+
|------|------|------|------|
|
|
247
|
+
| `businessId` | `string` | 是 | TT 账号的 businessId |
|
|
248
|
+
| `videoUrl` | `string` | 是 | 上传后获得的视频 URL |
|
|
249
|
+
| `caption` | `string` | 否 | 视频描述/文案 |
|
|
250
|
+
|
|
251
|
+
**响应:**
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"code": 0,
|
|
255
|
+
"success": true,
|
|
256
|
+
"data": {
|
|
257
|
+
"shareId": "share_abc123",
|
|
258
|
+
"status": "PROCESSING_DOWNLOAD",
|
|
259
|
+
"message": ""
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**后续:** 使用返回的 `shareId` 轮询 `/api/v1/open/tiktok/video/status` 获取发布进度。
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### POST /api/v1/open/tts/shoppable-video/publish
|
|
269
|
+
|
|
270
|
+
发布挂车视频(TTS 账号,带商品链接)。
|
|
271
|
+
|
|
272
|
+
**请求:**
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"creatorUserOpenId": "open_user_abc",
|
|
276
|
+
"fileId": "vf_abc123def456",
|
|
277
|
+
"title": "Amazing product review",
|
|
278
|
+
"productId": "prod_789",
|
|
279
|
+
"productTitle": "Premium Widget Pro"
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
284
|
+
|------|------|------|------|
|
|
285
|
+
| `creatorUserOpenId` | `string` | 是 | TTS 账号 OpenId |
|
|
286
|
+
| `fileId` | `string` | 是 | 上传返回的 `videoFileId` |
|
|
287
|
+
| `title` | `string` | 否 | 视频标题 |
|
|
288
|
+
| `productId` | `string` | 是 | 商品 ID |
|
|
289
|
+
| `productTitle` | `string` | 是 | 商品标题(**最多 29 字符**,超出应截断) |
|
|
290
|
+
|
|
291
|
+
**响应:**
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"code": 0,
|
|
295
|
+
"success": true,
|
|
296
|
+
"data": {
|
|
297
|
+
"videoId": "vid_xyz789",
|
|
298
|
+
"status": "PUBLISH_COMPLETE",
|
|
299
|
+
"message": ""
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**注意:** 挂车视频发布后立即完成(`PUBLISH_COMPLETE`),无需轮询状态。
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## 4. 发布状态查询
|
|
309
|
+
|
|
310
|
+
### POST /api/v1/open/tiktok/video/status
|
|
311
|
+
|
|
312
|
+
查询普通视频的发布进度(仅 TT 普通视频需要,TTS 挂车视频无需轮询)。
|
|
313
|
+
|
|
314
|
+
**请求:**
|
|
315
|
+
```json
|
|
316
|
+
{
|
|
317
|
+
"businessId": "biz_12345",
|
|
318
|
+
"shareId": "share_abc123"
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
323
|
+
|------|------|------|------|
|
|
324
|
+
| `businessId` | `string` | 是 | TT 账号的 businessId |
|
|
325
|
+
| `shareId` | `string` | 是 | 发布时返回的 shareId |
|
|
326
|
+
|
|
327
|
+
**响应 — 处理中:**
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"code": 0,
|
|
331
|
+
"success": true,
|
|
332
|
+
"data": {
|
|
333
|
+
"status": "PROCESSING_DOWNLOAD"
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**响应 — 发布成功:**
|
|
339
|
+
```json
|
|
340
|
+
{
|
|
341
|
+
"code": 0,
|
|
342
|
+
"success": true,
|
|
343
|
+
"data": {
|
|
344
|
+
"status": "PUBLISH_COMPLETE",
|
|
345
|
+
"post_ids": ["7123456789012345678"]
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**响应 — 发布失败:**
|
|
351
|
+
```json
|
|
352
|
+
{
|
|
353
|
+
"code": 0,
|
|
354
|
+
"success": true,
|
|
355
|
+
"data": {
|
|
356
|
+
"status": "FAILED",
|
|
357
|
+
"reason": "Video format not supported"
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**状态值说明:**
|
|
363
|
+
|
|
364
|
+
| 状态 | 含义 | 是否终态 |
|
|
365
|
+
|------|------|---------|
|
|
366
|
+
| `PROCESSING_DOWNLOAD` | 视频处理中 | 否,继续轮询 |
|
|
367
|
+
| `PUBLISH_COMPLETE` | 发布接口已完成;当 `post_ids` 非空时可视为成功完成 | 条件成立时是 |
|
|
368
|
+
| `FAILED` | 发布失败 | 是 |
|
|
369
|
+
|
|
370
|
+
**注意:** 如果返回 `PUBLISH_COMPLETE` 但 `post_ids` 为空,应继续轮询,直到拿到 `post_ids` 或达到超时上限。
|
|
371
|
+
|
|
372
|
+
**成功后:** `post_ids[0]` 即为 TikTok 上的视频 ID,可用于后续数据查询。
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## 5. 视频数据查询
|
|
377
|
+
|
|
378
|
+
### POST /api/v1/open/tiktok/video/query
|
|
379
|
+
|
|
380
|
+
批量查询视频统计数据(播放量、点赞、评论、分享等)。
|
|
381
|
+
|
|
382
|
+
**请求:**
|
|
383
|
+
```json
|
|
384
|
+
{
|
|
385
|
+
"businessId": "biz_12345",
|
|
386
|
+
"itemIds": ["7123456789012345678", "7123456789012345679"]
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
391
|
+
|------|------|------|------|
|
|
392
|
+
| `businessId` | `string` | 是 | TT 账号的 businessId |
|
|
393
|
+
| `itemIds` | `string[]` | 是 | 视频 ID 数组 |
|
|
394
|
+
|
|
395
|
+
**响应(新版格式 — camelCase):**
|
|
396
|
+
```json
|
|
397
|
+
{
|
|
398
|
+
"code": 0,
|
|
399
|
+
"success": true,
|
|
400
|
+
"data": {
|
|
401
|
+
"videoList": [
|
|
402
|
+
{
|
|
403
|
+
"itemId": "7123456789012345678",
|
|
404
|
+
"thumbnailUrl": "https://p16-sign.tiktokcdn.com/...",
|
|
405
|
+
"shareUrl": "https://www.tiktok.com/@user/video/...",
|
|
406
|
+
"videoViews": 52300,
|
|
407
|
+
"likes": 1200,
|
|
408
|
+
"comments": 89,
|
|
409
|
+
"shares": 45
|
|
410
|
+
}
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**响应(旧版格式 — snake_case):**
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"code": 0,
|
|
420
|
+
"success": true,
|
|
421
|
+
"data": {
|
|
422
|
+
"videos": [
|
|
423
|
+
{
|
|
424
|
+
"item_id": "7123456789012345678",
|
|
425
|
+
"thumbnail_url": "https://...",
|
|
426
|
+
"share_url": "https://...",
|
|
427
|
+
"video_views": 52300,
|
|
428
|
+
"likes": 1200,
|
|
429
|
+
"comments": 89,
|
|
430
|
+
"shares": 45
|
|
431
|
+
}
|
|
432
|
+
]
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**字段对照表:**
|
|
438
|
+
|
|
439
|
+
| 数据项 | 新版字段 | 旧版字段 | 类型 |
|
|
440
|
+
|--------|---------|---------|------|
|
|
441
|
+
| 视频列表 | `videoList` | `videos` | `array` |
|
|
442
|
+
| 视频 ID | `itemId` | `item_id` | `string` |
|
|
443
|
+
| 缩略图 | `thumbnailUrl` | `thumbnail_url` | `string` |
|
|
444
|
+
| 分享链接 | `shareUrl` | `share_url` | `string` |
|
|
445
|
+
| 播放量 | `videoViews` | `video_views` | `number` |
|
|
446
|
+
| 点赞数 | `likes` | `likes` | `number` |
|
|
447
|
+
| 评论数 | `comments` | `comments` | `number` |
|
|
448
|
+
| 分享数 | `shares` | `shares` | `number` |
|
|
449
|
+
|
|
450
|
+
**兼容写法示例:**
|
|
451
|
+
```typescript
|
|
452
|
+
const list = data.videoList ?? data.videos ?? []
|
|
453
|
+
const video = list[0]
|
|
454
|
+
if (video) {
|
|
455
|
+
const itemId = video.itemId ?? video.item_id
|
|
456
|
+
const views = video.videoViews ?? video.video_views ?? 0
|
|
457
|
+
const thumbnailUrl = video.thumbnailUrl ?? video.thumbnail_url
|
|
458
|
+
const shareUrl = video.shareUrl ?? video.share_url
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
**约束:** 仅拥有 TT 授权的账号才可查询视频数据。TTS-only 账号无此能力。
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## 6. TTS 商品查询
|
|
467
|
+
|
|
468
|
+
### POST /api/v1/open/tts/products/query
|
|
469
|
+
|
|
470
|
+
查询创作者的店铺/橱窗商品列表,用于挂车发布时选择商品。
|
|
471
|
+
|
|
472
|
+
**请求:**
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"creatorUserOpenId": "open_user_abc",
|
|
476
|
+
"productType": "shop",
|
|
477
|
+
"pageSize": 20,
|
|
478
|
+
"pageToken": ""
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
483
|
+
|------|------|------|------|
|
|
484
|
+
| `creatorUserOpenId` | `string` | 是 | TTS 账号 OpenId |
|
|
485
|
+
| `productType` | `'shop' \| 'showcase'` | 是 | 商品来源类型 |
|
|
486
|
+
| `pageSize` | `number` | 是 | 每页数量(建议 20) |
|
|
487
|
+
| `pageToken` | `string` | 否 | 分页游标(首页留空) |
|
|
488
|
+
|
|
489
|
+
**响应:**
|
|
490
|
+
```json
|
|
491
|
+
{
|
|
492
|
+
"code": 0,
|
|
493
|
+
"success": true,
|
|
494
|
+
"data": [
|
|
495
|
+
{
|
|
496
|
+
"productType": "shop",
|
|
497
|
+
"products": [
|
|
498
|
+
{
|
|
499
|
+
"id": "prod_123",
|
|
500
|
+
"title": "Premium Widget Pro",
|
|
501
|
+
"price": { "amount": "29.99", "currency": "USD" },
|
|
502
|
+
"images": ["{height=200, url=https://img.tiktokcdn.com/xxx.jpg, width=200}"],
|
|
503
|
+
"addedStatus": "ADDED",
|
|
504
|
+
"reviewStatus": "APPROVED",
|
|
505
|
+
"inventoryStatus": "IN_STOCK",
|
|
506
|
+
"brandName": "WidgetCo",
|
|
507
|
+
"shopName": "Widget Store",
|
|
508
|
+
"salesCount": 1500,
|
|
509
|
+
"source": "shop"
|
|
510
|
+
}
|
|
511
|
+
],
|
|
512
|
+
"totalCount": 45,
|
|
513
|
+
"nextPageToken": "eyJ..."
|
|
514
|
+
}
|
|
515
|
+
]
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
**商品字段说明:**
|
|
520
|
+
|
|
521
|
+
| 字段 | 类型 | 说明 |
|
|
522
|
+
|------|------|------|
|
|
523
|
+
| `id` | `string` | 商品 ID,发布时传入 `productId` |
|
|
524
|
+
| `title` | `string` | 商品标题,发布时传入 `productTitle`(注意 29 字符限制) |
|
|
525
|
+
| `price` | `object` | 价格信息 |
|
|
526
|
+
| `images` | `string[]` | 商品图片(特殊格式,需解析) |
|
|
527
|
+
| `addedStatus` | `string` | 添加状态 |
|
|
528
|
+
| `reviewStatus` | `string` | 审核状态 |
|
|
529
|
+
| `inventoryStatus` | `string` | 库存状态 |
|
|
530
|
+
| `salesCount` | `number` | 销量 |
|
|
531
|
+
| `nextPageToken` | `string \| null` | 下一页游标(`null` 表示最后一页) |
|
|
532
|
+
|
|
533
|
+
**图片 URL 提取:**
|
|
534
|
+
|
|
535
|
+
商品图片返回特殊格式,需正则解析:
|
|
536
|
+
```typescript
|
|
537
|
+
// 原始格式: "{height=200, url=https://img.tiktokcdn.com/xxx.jpg, width=200}"
|
|
538
|
+
function extractImageUrl(imageStr: string): string {
|
|
539
|
+
const match = imageStr.match(/url=([^,}]+)/)
|
|
540
|
+
return match?.[1]?.trim() ?? ''
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
**分页游标处理:**
|
|
545
|
+
|
|
546
|
+
建议同时查询 `shop` 和 `showcase` 两种类型,使用复合游标管理分页状态:
|
|
547
|
+
```typescript
|
|
548
|
+
// 编码游标
|
|
549
|
+
function encodeCursor(shopToken?: string, showcaseToken?: string): string {
|
|
550
|
+
return btoa(JSON.stringify({ shopToken: shopToken ?? '', showcaseToken: showcaseToken ?? '' }))
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// 解码游标
|
|
554
|
+
function decodeCursor(cursor: string): { shopToken: string; showcaseToken: string } {
|
|
555
|
+
return JSON.parse(atob(cursor))
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
**去重合并:** 同一商品可能同时出现在 shop 和 showcase 中,应按 `id` 去重。
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## 7. 错误码速查表
|
|
564
|
+
|
|
565
|
+
### Open API 层
|
|
566
|
+
|
|
567
|
+
所有端点共用的响应 `code` 字段:
|
|
568
|
+
|
|
569
|
+
| code | 含义 | 处理方式 |
|
|
570
|
+
|------|------|---------|
|
|
571
|
+
| `0` | 成功 | 正常处理 `data` 字段 |
|
|
572
|
+
| 非零 | 业务错误 | 读取 `message` 获取错误详情 |
|
|
573
|
+
|
|
574
|
+
### 常见业务错误场景
|
|
575
|
+
|
|
576
|
+
| 场景 | 建议 HTTP 状态码 | 建议 code | 示例 message |
|
|
577
|
+
|------|-----------------|-----------|-------------|
|
|
578
|
+
| 缺少必填参数 | 400 | 400 | `"accountId 为必填项"` |
|
|
579
|
+
| 参数值非法 | 400 | 400 | `"publishType 非法"` |
|
|
580
|
+
| 账号未授权 | 403 | 403 | `"该账号未授权普通视频发布"` |
|
|
581
|
+
| OAuth 授权过期 | 403 | 403 | `"授权已过期或无效,请重新授权"` |
|
|
582
|
+
| State Token 用户不匹配 | 403 | 403 | `"授权用户不匹配,请重新登录后授权"` |
|
|
583
|
+
| 资源不存在 | 404 | 404 | `"TikTok 账号不存在"` |
|
|
584
|
+
| Open API 调用失败 | 500 | 500 | `"Open API 错误 [/api/v1/open/xxx]: Bad request (code: 40001)"` |
|
|
585
|
+
| 上传凭证获取失败 | 500 | 500 | `"获取上传凭证失败"` |
|
|
586
|
+
| API 成功但本地存储失败 | 200 | 200 | `"视频已提交至 TikTok,但本地记录保存失败"`(附 `dbSaved: false`) |
|
|
587
|
+
|
|
588
|
+
### 客户端上传错误
|
|
589
|
+
|
|
590
|
+
| 错误消息 | 原因 | 处理建议 |
|
|
591
|
+
|---------|------|---------|
|
|
592
|
+
| `上传失败,响应解析失败` | 服务端返回非 JSON 内容 | 检查上传 URL 和凭证是否正确 |
|
|
593
|
+
| `上传失败,状态码: {status}` | HTTP 非 2xx | 检查认证头和文件格式 |
|
|
594
|
+
| `上传失败` | API 返回 `code !== 0` | 查看 `message` 获取具体原因 |
|
|
595
|
+
| `上传成功但未返回可用结果` | 响应中既无 `fileUrl` 也无 `videoFileId` | API 异常,需排查 |
|
|
596
|
+
| `上传失败,网络错误` | 网络连接中断 | 提示用户检查网络后重试 |
|
|
597
|
+
| `Upload aborted` | 用户取消或页面卸载 | 正常行为,无需处理 |
|
|
598
|
+
|
|
599
|
+
### 队列重试建议
|
|
600
|
+
|
|
601
|
+
| 参数 | 建议值 | 说明 |
|
|
602
|
+
|------|--------|------|
|
|
603
|
+
| 最大重试次数 | 3 | 超过后停止重试并记录日志 |
|
|
604
|
+
| 重试间隔 | 2 秒 | 固定间隔或指数退避均可 |
|
|
605
|
+
| 超限处理 | acknowledge | 防止消息无限重投 |
|