beervid-app-cli 0.2.6 → 0.2.7
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 +19 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.mjs +165 -73
- package/dist/index.d.ts +255 -0
- package/dist/index.mjs +1 -0
- package/package.json +11 -2
- package/skills/beervid-app-cli/FAQ.md +214 -0
- package/skills/beervid-app-cli/QUICKSTART.md +206 -0
- package/skills/beervid-app-cli/SKILL.md +52 -9
- package/skills/beervid-app-cli/docs/database-schema.md +12 -2
- package/skills/beervid-app-cli/docs/oauth-callback.md +70 -21
- package/skills/beervid-app-cli/docs/performance-and-limits.md +153 -0
- package/skills/beervid-app-cli/docs/security-best-practices.md +132 -0
- package/skills/beervid-app-cli/docs/testing-guide.md +689 -0
- package/skills/beervid-app-cli/docs/troubleshooting.md +468 -0
- package/skills/beervid-app-cli/example/express/README.md +6 -0
- package/skills/beervid-app-cli/example/express/server.ts +23 -5
- package/skills/beervid-app-cli/example/nextjs/README.md +6 -0
- package/skills/beervid-app-cli/example/nextjs/app/api/oauth/callback/route.ts +22 -6
- package/skills/beervid-app-cli/example/nextjs/app/api/publish/tts/route.ts +2 -2
- package/skills/beervid-app-cli/example/standard/README.md +6 -0
- package/skills/beervid-app-cli/example/standard/tts-publish-flow.ts +1 -1
- package/skills/beervid-app-cli/references/api-reference.md +37 -11
- package/skills/beervid-app-cli/skill.json +36 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
# 故障排查指南
|
|
2
|
+
|
|
3
|
+
本文档帮助你快速定位和解决 BEERVID Open API 集成中的常见问题。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
1. [认证问题](#认证问题)
|
|
8
|
+
2. [上传问题](#上传问题)
|
|
9
|
+
3. [发布问题](#发布问题)
|
|
10
|
+
4. [轮询问题](#轮询问题)
|
|
11
|
+
5. [查询问题](#查询问题)
|
|
12
|
+
6. [网络问题](#网络问题)
|
|
13
|
+
7. [调试技巧](#调试技巧)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 认证问题
|
|
18
|
+
|
|
19
|
+
### 错误:401 Unauthorized
|
|
20
|
+
|
|
21
|
+
**症状:**
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"code": 401,
|
|
25
|
+
"message": "Unauthorized",
|
|
26
|
+
"success": false
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**可能原因:**
|
|
31
|
+
1. `BEERVID_APP_KEY` 未设置或错误
|
|
32
|
+
2. API Key 已过期或被撤销
|
|
33
|
+
3. 请求头 `X-API-KEY` 未正确设置
|
|
34
|
+
|
|
35
|
+
**解决方案:**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 检查当前配置
|
|
39
|
+
beervid config --show
|
|
40
|
+
|
|
41
|
+
# 重新设置 API Key
|
|
42
|
+
beervid config --app-key "your-correct-api-key"
|
|
43
|
+
|
|
44
|
+
# 或使用环境变量
|
|
45
|
+
export BEERVID_APP_KEY="your-correct-api-key"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**验证:**
|
|
49
|
+
```bash
|
|
50
|
+
# 测试 API Key 是否有效
|
|
51
|
+
beervid get-oauth-url --type tt
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 错误:X-API-KEY header is required
|
|
55
|
+
|
|
56
|
+
**症状:**
|
|
57
|
+
API 返回缺少认证头的错误。
|
|
58
|
+
|
|
59
|
+
**解决方案:**
|
|
60
|
+
|
|
61
|
+
检查你的代码是否正确设置了请求头:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const headers = {
|
|
65
|
+
'X-API-KEY': process.env.BEERVID_APP_KEY,
|
|
66
|
+
'Content-Type': 'application/json'
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 上传问题
|
|
73
|
+
|
|
74
|
+
### 错误:上传凭证获取失败
|
|
75
|
+
|
|
76
|
+
**症状:**
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"code": 400,
|
|
80
|
+
"message": "Invalid account type"
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**可能原因:**
|
|
85
|
+
- TTS 上传需要 `creatorUserOpenId`,但你传了 `businessId`
|
|
86
|
+
- TT 上传不需要额外参数,但你传了 `creatorUserOpenId`
|
|
87
|
+
|
|
88
|
+
**解决方案:**
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# TT 普通上传(不需要额外参数)
|
|
92
|
+
beervid upload --file ./video.mp4
|
|
93
|
+
|
|
94
|
+
# TTS 上传(需要 creator-id)
|
|
95
|
+
beervid upload --file ./video.mp4 --type tts --creator-id "open_user_abc"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 错误:文件上传超时
|
|
99
|
+
|
|
100
|
+
**症状:**
|
|
101
|
+
上传大文件时请求超时。
|
|
102
|
+
|
|
103
|
+
**解决方案:**
|
|
104
|
+
|
|
105
|
+
1. **检查文件大小:** TikTok 限制视频大小通常为 4GB
|
|
106
|
+
2. **检查网络连接:** 确保网络稳定
|
|
107
|
+
3. **增加超时时间:** 如果使用代码集成,增加请求超时
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// 示例:增加超时时间
|
|
111
|
+
const controller = new AbortController()
|
|
112
|
+
const timeout = setTimeout(() => controller.abort(), 300000) // 5分钟
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
await fetch(uploadUrl, {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
body: formData,
|
|
118
|
+
signal: controller.signal
|
|
119
|
+
})
|
|
120
|
+
} finally {
|
|
121
|
+
clearTimeout(timeout)
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 错误:Invalid file format
|
|
126
|
+
|
|
127
|
+
**症状:**
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"code": 400,
|
|
131
|
+
"message": "Unsupported video format"
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**解决方案:**
|
|
136
|
+
|
|
137
|
+
确保视频格式符合 TikTok 要求:
|
|
138
|
+
- 支持格式:MP4, MOV, MPEG, 3GP, AVI, WebM
|
|
139
|
+
- 推荐格式:MP4 (H.264 编码)
|
|
140
|
+
- 分辨率:最小 720p,推荐 1080p
|
|
141
|
+
- 时长:3秒 - 10分钟
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 发布问题
|
|
146
|
+
|
|
147
|
+
### 错误:businessId not found
|
|
148
|
+
|
|
149
|
+
**症状:**
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"code": 404,
|
|
153
|
+
"message": "Account not found"
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**可能原因:**
|
|
158
|
+
1. `businessId` 或 `creatorUserOpenId` 错误
|
|
159
|
+
2. 账号未完成 OAuth 授权
|
|
160
|
+
3. 账号已被解绑
|
|
161
|
+
|
|
162
|
+
**解决方案:**
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# 验证账号是否存在
|
|
166
|
+
beervid get-account-info --type TT --account-id "your-business-id"
|
|
167
|
+
|
|
168
|
+
# 如果账号不存在,重新获取授权
|
|
169
|
+
beervid get-oauth-url --type tt
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 错误:productTitle too long
|
|
173
|
+
|
|
174
|
+
**症状:**
|
|
175
|
+
TTS 发布时提示商品标题过长。
|
|
176
|
+
|
|
177
|
+
**解决方案:**
|
|
178
|
+
|
|
179
|
+
`productTitle` 最多 30 个字符,需要提前截断:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
const productTitle = originalTitle.length > 30
|
|
183
|
+
? originalTitle.slice(0, 30)
|
|
184
|
+
: originalTitle
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 错误:Invalid video URL
|
|
188
|
+
|
|
189
|
+
**症状:**
|
|
190
|
+
TT 普通发布时提示视频 URL 无效。
|
|
191
|
+
|
|
192
|
+
**可能原因:**
|
|
193
|
+
1. `videoUrl` 不是可公开访问的 URL
|
|
194
|
+
2. URL 已过期
|
|
195
|
+
3. URL 格式错误
|
|
196
|
+
|
|
197
|
+
**解决方案:**
|
|
198
|
+
|
|
199
|
+
确保 `videoUrl` 是上传接口返回的 `fileUrl`:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# 先上传,获取 fileUrl
|
|
203
|
+
beervid upload --file ./video.mp4
|
|
204
|
+
|
|
205
|
+
# 使用返回的 fileUrl 发布
|
|
206
|
+
beervid publish --type normal \
|
|
207
|
+
--business-id "biz_123" \
|
|
208
|
+
--video-url "https://cdn.beervid.ai/uploads/xxx.mp4"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 轮询问题
|
|
214
|
+
|
|
215
|
+
### 问题:轮询一直不返回 PUBLISH_COMPLETE
|
|
216
|
+
|
|
217
|
+
**症状:**
|
|
218
|
+
轮询状态一直是 `PROCESSING_DOWNLOAD` 或 `SEND_TO_USER_INBOX`。
|
|
219
|
+
|
|
220
|
+
**可能原因:**
|
|
221
|
+
1. TikTok 平台处理较慢(正常情况)
|
|
222
|
+
2. 视频文件有问题
|
|
223
|
+
3. TikTok 账号有限制
|
|
224
|
+
|
|
225
|
+
**解决方案:**
|
|
226
|
+
|
|
227
|
+
1. **增加轮询次数和间隔:**
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
beervid poll-status \
|
|
231
|
+
--business-id "biz_123" \
|
|
232
|
+
--share-id "share_abc" \
|
|
233
|
+
--interval 10000 \
|
|
234
|
+
--max-polls 60
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
2. **检查状态详情:**
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// 查看完整状态信息
|
|
241
|
+
const status = await pollStatus(businessId, shareId)
|
|
242
|
+
console.log('Status:', status.status)
|
|
243
|
+
console.log('Error:', status.error_code, status.error_message)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
3. **常见状态及含义:**
|
|
247
|
+
|
|
248
|
+
| 状态 | 含义 | 是否正常 |
|
|
249
|
+
|------|------|----------|
|
|
250
|
+
| `PROCESSING_DOWNLOAD` | TikTok 正在下载视频 | 正常,继续等待 |
|
|
251
|
+
| `SEND_TO_USER_INBOX` | 视频已发送到收件箱 | 正常,继续等待 |
|
|
252
|
+
| `PUBLISH_COMPLETE` | 发布完成 | 成功 |
|
|
253
|
+
| `FAILED` | 发布失败 | 失败,检查错误信息 |
|
|
254
|
+
|
|
255
|
+
### 问题:post_ids 为空
|
|
256
|
+
|
|
257
|
+
**症状:**
|
|
258
|
+
状态是 `PUBLISH_COMPLETE`,但 `post_ids` 数组为空。
|
|
259
|
+
|
|
260
|
+
**解决方案:**
|
|
261
|
+
|
|
262
|
+
这通常表示视频还在处理中,需要继续轮询:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// 正确的完成判断
|
|
266
|
+
const isComplete =
|
|
267
|
+
status.status === 'PUBLISH_COMPLETE' &&
|
|
268
|
+
status.post_ids &&
|
|
269
|
+
status.post_ids.length > 0
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## 查询问题
|
|
275
|
+
|
|
276
|
+
### 错误:Only TT accounts can query video data
|
|
277
|
+
|
|
278
|
+
**症状:**
|
|
279
|
+
使用 TTS 账号查询视频数据时报错。
|
|
280
|
+
|
|
281
|
+
**解决方案:**
|
|
282
|
+
|
|
283
|
+
视频数据查询仅支持 TT 账号:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# 正确:使用 TT 账号的 businessId
|
|
287
|
+
beervid query-video \
|
|
288
|
+
--business-id "7281234567890" \
|
|
289
|
+
--item-ids "7123456789012345678"
|
|
290
|
+
|
|
291
|
+
# 错误:使用 TTS 账号的 creatorUserOpenId
|
|
292
|
+
# TTS 账号不支持视频数据查询
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
如果同一达人已经完成了 TTS 授权,但你还想查询该账号的视频数据:
|
|
296
|
+
|
|
297
|
+
- 还需要额外完成一次 TT 授权
|
|
298
|
+
- 官方当前没有提供 `uno_id` 这类 TT/TTS 强关联字段
|
|
299
|
+
- 当前推荐在你方系统里通过 `account/info` 返回的 `username` 建立 TT/TTS 关联
|
|
300
|
+
- 查数时使用关联后的 TT `businessId`,不要直接使用 TTS `creatorUserOpenId`
|
|
301
|
+
|
|
302
|
+
### 问题:查询返回的字段不一致
|
|
303
|
+
|
|
304
|
+
**症状:**
|
|
305
|
+
有时返回 `playCount`,有时返回 `play_count`。
|
|
306
|
+
|
|
307
|
+
**解决方案:**
|
|
308
|
+
|
|
309
|
+
API 可能同时返回 camelCase 和 snake_case 字段,建议兼容处理:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
const playCount = data.playCount ?? data.play_count ?? 0
|
|
313
|
+
const likeCount = data.likeCount ?? data.like_count ?? 0
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 网络问题
|
|
319
|
+
|
|
320
|
+
### 错误:ECONNREFUSED 或 ETIMEDOUT
|
|
321
|
+
|
|
322
|
+
**症状:**
|
|
323
|
+
请求无法连接到服务器。
|
|
324
|
+
|
|
325
|
+
**解决方案:**
|
|
326
|
+
|
|
327
|
+
1. **检查 BASE_URL 配置:**
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
beervid config --show
|
|
331
|
+
|
|
332
|
+
# 确保 BASE_URL 正确
|
|
333
|
+
beervid config --base-url "https://open.beervid.ai"
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
2. **检查网络连接:**
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# 测试网络连通性
|
|
340
|
+
curl -I https://open.beervid.ai/api/v1/open/thirdparty-auth/tt-url
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
3. **检查防火墙和代理:**
|
|
344
|
+
|
|
345
|
+
如果在企业网络环境,可能需要配置代理:
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
export HTTP_PROXY="http://proxy.company.com:8080"
|
|
349
|
+
export HTTPS_PROXY="http://proxy.company.com:8080"
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### 错误:SSL certificate problem
|
|
353
|
+
|
|
354
|
+
**症状:**
|
|
355
|
+
SSL 证书验证失败。
|
|
356
|
+
|
|
357
|
+
**解决方案:**
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
# 临时禁用 SSL 验证(仅用于调试,生产环境不推荐)
|
|
361
|
+
export NODE_TLS_REJECT_UNAUTHORIZED=0
|
|
362
|
+
|
|
363
|
+
# 更好的方案:更新系统证书
|
|
364
|
+
# macOS
|
|
365
|
+
brew install ca-certificates
|
|
366
|
+
|
|
367
|
+
# Ubuntu/Debian
|
|
368
|
+
sudo apt-get update && sudo apt-get install ca-certificates
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## 调试技巧
|
|
374
|
+
|
|
375
|
+
### 1. 启用详细日志
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
# 设置环境变量启用调试模式
|
|
379
|
+
export DEBUG=beervid:*
|
|
380
|
+
|
|
381
|
+
# 运行命令查看详细日志
|
|
382
|
+
beervid upload --file ./video.mp4
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### 2. 使用 --verbose 标志
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
# 如果 CLI 支持 verbose 模式
|
|
389
|
+
beervid publish-tt-flow \
|
|
390
|
+
--business-id "biz_123" \
|
|
391
|
+
--file ./video.mp4 \
|
|
392
|
+
--verbose
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### 3. 检查原始响应
|
|
396
|
+
|
|
397
|
+
在代码中打印完整响应:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
try {
|
|
401
|
+
const response = await openApiPost('/api/v1/open/tiktok/video/publish', data)
|
|
402
|
+
console.log('Full response:', JSON.stringify(response, null, 2))
|
|
403
|
+
} catch (error) {
|
|
404
|
+
console.error('Error details:', error)
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### 4. 使用 curl 测试 API
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
# 测试获取授权链接
|
|
412
|
+
curl -X GET \
|
|
413
|
+
-H "X-API-KEY: your-api-key" \
|
|
414
|
+
https://open.beervid.ai/api/v1/open/thirdparty-auth/tt-url
|
|
415
|
+
|
|
416
|
+
# 测试账号信息查询
|
|
417
|
+
curl -X POST \
|
|
418
|
+
-H "X-API-KEY: your-api-key" \
|
|
419
|
+
-H "Content-Type: application/json" \
|
|
420
|
+
-d '{"accountType":"TT","accountId":"7281234567890"}' \
|
|
421
|
+
https://open.beervid.ai/api/v1/open/account/info
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### 5. 检查 CLI 版本
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
# 确保使用最新版本
|
|
428
|
+
npm list -g beervid-app-cli
|
|
429
|
+
|
|
430
|
+
# 更新到最新版本
|
|
431
|
+
npm update -g beervid-app-cli
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### 6. 清理本地配置
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
# 查看配置文件位置
|
|
438
|
+
ls -la ~/.beervid/
|
|
439
|
+
|
|
440
|
+
# 删除配置文件重新开始
|
|
441
|
+
rm -rf ~/.beervid/config.json
|
|
442
|
+
|
|
443
|
+
# 重新配置
|
|
444
|
+
beervid config --app-key "your-api-key"
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## 常见错误码速查
|
|
450
|
+
|
|
451
|
+
| 错误码 | 含义 | 解决方案 |
|
|
452
|
+
|--------|------|----------|
|
|
453
|
+
| 400 | 请求参数错误 | 检查参数格式和必填字段 |
|
|
454
|
+
| 401 | 认证失败 | 检查 API Key 是否正确 |
|
|
455
|
+
| 403 | 权限不足 | 检查账号权限或 API Key 权限 |
|
|
456
|
+
| 404 | 资源不存在 | 检查 ID 是否正确 |
|
|
457
|
+
| 429 | 请求过于频繁 | 降低请求频率,参考限流说明 |
|
|
458
|
+
| 500 | 服务器错误 | 稍后重试,或联系技术支持 |
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## 仍然无法解决?
|
|
463
|
+
|
|
464
|
+
1. **查看完整 API 文档:** [references/api-reference.md](../references/api-reference.md)
|
|
465
|
+
2. **查看 FAQ:** [FAQ.md](../FAQ.md)
|
|
466
|
+
3. **查看示例代码:** [example/](../example/)
|
|
467
|
+
4. **提交 Issue:** https://github.com/Lupeiwen0/beervid-app-cli/issues
|
|
468
|
+
5. **联系技术支持:** support@beervid.ai
|
|
@@ -56,3 +56,9 @@ curl -X POST http://localhost:3000/api/publish/tts \
|
|
|
56
56
|
-H "Content-Type: application/json" \
|
|
57
57
|
-d '{"creatorId": "open_user_abc", "videoFileId": "vf_abc123", "productId": "prod_789", "productTitle": "Widget"}'
|
|
58
58
|
```
|
|
59
|
+
|
|
60
|
+
## 账号关联提醒
|
|
61
|
+
|
|
62
|
+
- 如果同一达人既要做 TTS 挂车发布,又要查询视频数据,需要分别完成 TTS 和 TT 授权。
|
|
63
|
+
- 官方当前没有提供 `uno_id` 这类 TT/TTS 关联字段。
|
|
64
|
+
- 这个示例更推荐在 OAuth 回调后的 `account/info` 同步阶段持久化 `username`,并在你方数据库里用它建立 TT/TTS 关联。
|
|
@@ -182,10 +182,26 @@ app.get('/oauth/tts', async (_req, res) => {
|
|
|
182
182
|
|
|
183
183
|
// OAuth 回调处理
|
|
184
184
|
app.get('/oauth/callback', async (req, res) => {
|
|
185
|
-
const
|
|
186
|
-
const ttsAbId = req.query['ttsAbId'] as string | undefined
|
|
185
|
+
const stateParam = req.query['state'] as string | undefined
|
|
187
186
|
|
|
188
|
-
|
|
187
|
+
if (!stateParam) {
|
|
188
|
+
res.status(400).json({ error: '缺少 state 参数' })
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 回调字段在 state JSON 内部
|
|
193
|
+
let stateObj: Record<string, unknown>
|
|
194
|
+
try {
|
|
195
|
+
stateObj = JSON.parse(stateParam) as Record<string, unknown>
|
|
196
|
+
} catch {
|
|
197
|
+
res.status(400).json({ error: 'state 不是合法 JSON' })
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const ttAbId = stateObj['ttAbId'] as string | undefined
|
|
202
|
+
const ttsAbId = stateObj['ttsAbId'] as string | undefined
|
|
203
|
+
|
|
204
|
+
// 生产环境:① 验证 state 中你方追加的自定义安全字段 ② 一次性消费检查
|
|
189
205
|
// 详见 docs/oauth-callback.md
|
|
190
206
|
|
|
191
207
|
if (!ttAbId && !ttsAbId) {
|
|
@@ -209,6 +225,8 @@ app.get('/oauth/callback', async (req, res) => {
|
|
|
209
225
|
openApiPost('/api/v1/open/account/info', { accountType, accountId })
|
|
210
226
|
.then((info) => {
|
|
211
227
|
const existing = accountStore.get(accountId) ?? {}
|
|
228
|
+
// 生产环境建议在这里把 username 持久化,并作为当前推荐的 TT/TTS 关联键。
|
|
229
|
+
// 官方没有提供 uno_id 这类可直接关联 TT/TTS 的稳定字段。
|
|
212
230
|
accountStore.set(accountId, { ...existing, ...info })
|
|
213
231
|
console.log(`[异步] 账号信息已同步: ${accountId}`)
|
|
214
232
|
})
|
|
@@ -300,8 +318,8 @@ app.post('/api/publish/tts', async (req, res) => {
|
|
|
300
318
|
}
|
|
301
319
|
|
|
302
320
|
try {
|
|
303
|
-
// 商品标题最多
|
|
304
|
-
const normalizedTitle = productTitle.slice(0,
|
|
321
|
+
// 商品标题最多 30 字符
|
|
322
|
+
const normalizedTitle = productTitle.slice(0, 30)
|
|
305
323
|
|
|
306
324
|
// 挂车发布(不重试——发布操作非幂等)
|
|
307
325
|
const publishResult = await openApiPost<{ videoId: string }>(
|
|
@@ -52,3 +52,9 @@ npm run dev
|
|
|
52
52
|
- `lib/beervid-client.ts` — 服务端 BEERVID API 客户端封装
|
|
53
53
|
- `app/api/` — API Route Handlers
|
|
54
54
|
- `app/page.tsx` — 简单首页展示 API 调用方式
|
|
55
|
+
|
|
56
|
+
## 账号关联提醒
|
|
57
|
+
|
|
58
|
+
- TTS 账号只能用于挂车发布和商品查询,不能直接查视频数据。
|
|
59
|
+
- 如果同一达人还要查视频数据,需要额外完成 TT 授权。
|
|
60
|
+
- 官方当前没有提供 `uno_id` 这类 TT/TTS 关联字段,建议在 OAuth 回调后调用 `account/info`,并用返回的 `username` 建立本地关联。
|
|
@@ -1,25 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GET /api/oauth/callback?ttAbId
|
|
3
|
-
* OAuth 回调处理
|
|
2
|
+
* GET /api/oauth/callback?state={"ttAbId":"xxx",...}
|
|
3
|
+
* OAuth 回调处理 — 回调字段在 state JSON 内部
|
|
4
4
|
*/
|
|
5
5
|
import { NextRequest, NextResponse } from 'next/server'
|
|
6
6
|
import { openApiPost } from '@/lib/beervid-client'
|
|
7
7
|
|
|
8
8
|
export async function GET(request: NextRequest) {
|
|
9
|
-
const
|
|
10
|
-
const ttsAbId = request.nextUrl.searchParams.get('ttsAbId')
|
|
9
|
+
const stateParam = request.nextUrl.searchParams.get('state')
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
if (!stateParam) {
|
|
12
|
+
return NextResponse.json({ error: '缺少 state 参数' }, { status: 400 })
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// 回调字段在 state JSON 内部
|
|
16
|
+
let stateObj: Record<string, unknown>
|
|
17
|
+
try {
|
|
18
|
+
stateObj = JSON.parse(stateParam) as Record<string, unknown>
|
|
19
|
+
} catch {
|
|
20
|
+
return NextResponse.json({ error: 'state 不是合法 JSON' }, { status: 400 })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const ttAbId = stateObj['ttAbId'] as string | undefined
|
|
24
|
+
const ttsAbId = stateObj['ttsAbId'] as string | undefined
|
|
25
|
+
|
|
26
|
+
// 生产环境:① 验证 state 中你方追加的自定义安全字段 ② 一次性消费检查
|
|
13
27
|
// 详见 docs/oauth-callback.md
|
|
14
28
|
|
|
15
29
|
if (!ttAbId && !ttsAbId) {
|
|
16
|
-
return NextResponse.json({ error: '
|
|
30
|
+
return NextResponse.json({ error: 'state 中缺少 ttAbId 或 ttsAbId' }, { status: 400 })
|
|
17
31
|
}
|
|
18
32
|
|
|
19
33
|
const accountId = (ttAbId ?? ttsAbId)!
|
|
20
34
|
const accountType = ttAbId ? 'TT' : 'TTS'
|
|
21
35
|
|
|
22
36
|
// 异步拉取账号详情(不阻塞回调响应)
|
|
37
|
+
// 生产环境建议在这里把 username 写入数据库,并作为当前推荐的 TT/TTS 关联键。
|
|
38
|
+
// 官方没有提供 uno_id 这类可直接关联 TT/TTS 的稳定字段。
|
|
23
39
|
openApiPost('/api/v1/open/account/info', { accountType, accountId }).catch((err) => {
|
|
24
40
|
console.error('[异步] 账号信息同步失败:', (err as Error).message)
|
|
25
41
|
})
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { NextRequest, NextResponse } from 'next/server'
|
|
9
9
|
import { openApiPost } from '@/lib/beervid-client'
|
|
10
10
|
|
|
11
|
-
const MAX_PRODUCT_TITLE_LENGTH =
|
|
11
|
+
const MAX_PRODUCT_TITLE_LENGTH = 30
|
|
12
12
|
|
|
13
13
|
export async function POST(request: NextRequest) {
|
|
14
14
|
const body = await request.json()
|
|
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
try {
|
|
31
|
-
// 商品标题最多
|
|
31
|
+
// 商品标题最多 30 字符,超出自动截断
|
|
32
32
|
const normalizedTitle = productTitle.slice(0, MAX_PRODUCT_TITLE_LENGTH)
|
|
33
33
|
const wasTruncated = normalizedTitle !== productTitle
|
|
34
34
|
|
|
@@ -49,3 +49,9 @@ npx tsx query-products.ts --creator-id open_user_abc
|
|
|
49
49
|
| `tts-publish-flow.ts` | ⭐ TTS 完整发布流程最佳实践(含商品筛选策略) |
|
|
50
50
|
| `get-oauth-url.ts` | 获取 TT/TTS OAuth 授权 URL |
|
|
51
51
|
| `query-products.ts` | TTS 商品查询与分页遍历 |
|
|
52
|
+
|
|
53
|
+
## 账号关联提醒
|
|
54
|
+
|
|
55
|
+
- TTS 账号不能直接查询视频数据。
|
|
56
|
+
- 如果同一达人既要跑 `tts-publish-flow.ts`,又要查视频数据,还需要额外授权 TT 账号。
|
|
57
|
+
- 官方当前没有提供 `uno_id` 可直接关联 TT/TTS,示例项目当前推荐使用 `account/info` 返回的 `username` 做关联。
|