Files
cid/YIDUN_API_DOCUMENTATION.md
2026-05-15 10:28:17 +08:00

1132 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 易盾内容安全 API 调用文档
## 📋 目录
- [概述](#概述)
- [配置说明](#配置说明)
- [模式切换](#模式切换)
- [API接口列表](#api接口列表)
- [文本检测](#1-文本检测)
- [图片检测](#2-图片检测)
- [视频检测](#3-视频检测)
- [回调与轮询接口](#回调与轮询接口)
- [错误码说明](#错误码说明)
- [常见问题](#常见问题)
---
## 概述
本项目集成了网易易盾内容安全SDK提供文本、图片、视频的内容安全检测服务。
### 产品凭证
| 检测类型 | SecretID | SecretKey | BusinessID |
|---------|----------|-----------|------------|
| **音视频检测** | f58a38341ca6227014df7c3bf0e6f16f | 526aa631ba5d518aedeb70b5a3b67371 | 需从易盾控制台获取 |
| **图片检测** | 9a82f90bfec61eb40d1c95605b894817 | f73a78954417a3713c36ec2d14eb2b5f | 需从易盾控制台获取 |
| **文本检测** | 待配置 | 待配置 | 待配置 |
### 服务地址
```
http://localhost:3001
```
---
## 配置说明
配置文件位置:`config.yml`
```yaml
yidun:
# 回调模式开关: true=使用回调模式(需要公网地址), false=使用轮询模式
callback_mode: false
# 视频检测配置
video:
secret_id: "f58a38341ca6227014df7c3bf0e6f16f"
secret_key: "526aa631ba5d518aedeb70b5a3b67371"
callback_url: "http://your-domain.com:3001/yidun/callback/receiveVideo"
# 图片检测配置
image:
business_id: "your_image_business_id"
secret_id: "9a82f90bfec61eb40d1c95605b894817"
secret_key: "f73a78954417a3713c36ec2d14eb2b5f"
callback_url: "http://your-domain.com:3001/yidun/callback/receiveImage"
# 文本检测配置
text:
business_id: "YOUR_TEXT_BUSINESS_ID"
secret_id: "YOUR_TEXT_SECRET_ID"
secret_key: "YOUR_TEXT_SECRET_KEY"
# 内容送检定时任务配置
content_check:
batch_size: 10 # 每批处理数量
image_enabled: true # 是否启用图片检测
video_enabled: true # 是否启用视频检测
interval_seconds: 30 # 定时任务执行间隔(秒)
```
---
## 模式切换
### 轮询模式(无公网地址)
适用于开发测试环境或没有公网地址的场景。
```yaml
yidun:
callback_mode: false # 使用轮询模式
```
**工作流程**
```
定时任务 → 提交检测 → 保存taskId → 手动轮询 → 获取结果 → 更新状态
```
### 回调模式(有公网地址)
适用于生产环境,需要配置公网可访问的回调地址。
```yaml
yidun:
callback_mode: true # 使用回调模式
image:
callback_url: "http://your-public-domain.com:3001/yidun/callback/receiveImage"
video:
callback_url: "http://your-public-domain.com:3001/yidun/callback/receiveVideo"
```
**工作流程**
```
定时任务 → 提交检测 → 易盾检测完成 → 易盾推送结果 → 自动更新状态
```
---
## API接口列表
### 送检接口
| 接口名称 | 请求方法 | 路径 | 说明 |
|---------|---------|------|------|
| 文本检测提交 | POST | `/yidun/detect-text` | 提交文本进行异步检测 |
| 图片检测提交 | POST | `/yidun/detect-image` | 提交图片进行异步检测 |
| 视频检测提交 | POST | `/yidun/detect-video` | 提交视频进行检测 |
### 回调模式接口
| 接口名称 | 请求方法 | 路径 | 说明 |
|---------|---------|------|------|
| 接收图片回调 | POST | `/yidun/callback/receiveImage` | 接收易盾图片检测结果推送 |
| 接收视频回调 | POST | `/yidun/callback/receiveVideo` | 接收易盾视频检测结果推送 |
### 轮询模式接口
| 接口名称 | 请求方法 | 路径 | 说明 |
|---------|---------|------|------|
| 轮询所有结果 | POST | `/yidun/callback/poll` | 轮询所有待处理结果(图片+视频) |
| 轮询图片结果 | POST | `/yidun/callback/pollImage` | 仅轮询图片待处理结果 |
| 轮询视频结果 | POST | `/yidun/callback/pollVideo` | 仅轮询视频待处理结果 |
| 查询单个结果 | POST | `/yidun/callback/pollTask` | 根据taskId查询单个结果 |
| 获取待处理数量 | GET | `/yidun/callback/pendingCount` | 查看待处理结果数量 |
**注意**:检测结果是异步的,提交接口只返回 `task_id`,需要通过回调或轮询获取结果。
---
## 1. 文本检测
### 提交文本检测任务
**接口地址**: `POST /yidun/detect-text`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| data_id | string | 是 | 数据唯一标识 |
| content | string | 是 | 待检测的文本内容 |
| ip | string | 否 | 用户IP地址 |
| token | string | 否 | 用户token反作弊 |
**请求示例**:
```bash
curl -X POST http://localhost:3002/yidun/detect-text \
-H "Content-Type: application/json" \
-d '{
"data_id": "text-001",
"content": "这是一段需要检测的文本内容",
"ip": "192.168.1.100"
}'
```
**响应示例**:
```json
{
"code": 0,
"message": "",
"data": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
}
```
**响应说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| data | string | 任务ID (task_id),用于后续查询检测结果 |
---
## 2. 图片检测
### 2.1 提交图片检测任务
**接口地址**: `POST /yidun/detect-image`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| data_id | string | 是 | 数据唯一标识 |
| image_url | string | 是 | 图片URL地址 |
| callback_url | string | 否 | 回调地址 |
**请求示例**:
```bash
curl -X POST http://localhost:3002/yidun/detect-image \
-H "Content-Type: application/json" \
-d '{
"data_id": "img-001",
"image_url": "https://example.com/image.jpg"
}'
```
**响应示例**:
```json
{
"code": 0,
"message": "",
"data": {
"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7",
"name": "img-001",
"dataId": "img-001",
"dealingCount": 0
}
}
```
**响应说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| taskId | string | 任务ID用于后续查询检测结果 |
| name | string | 图片唯一标识 |
| dataId | string | 客户图片唯一标识 |
| dealingCount | int64 | 缓冲池排队待处理数据量 |
### 2.2 查询图片检测结果(轮询模式)
**接口地址**: `POST /yidun/GetImageResult`
**SDK调用信息**:
- SDK方法: `ImageClient.ImageCallback(request)`
- 请求地址: `http://as.dun.163.com/v5/image/callback/results`
- 请求参数: `yidunRequestId` (taskId)
**请求示例**:
```bash
curl -X POST "http://localhost:3002/yidun/GetImageResult" \
-H "Content-Type: application/json" \
-d '{"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7"}'
```
**响应示例**:
```json
{
"code": 0,
"message": "",
"data": {
"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7",
"status": 2,
"suggestion": 0,
"label": 100,
"resultType": 2,
"dataId": "img-001",
"name": "img-001",
"censorTime": 1629426386079,
"url": "https://example.com/image.jpg",
"antispam": {
"taskId": "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7",
"name": "img-001",
"dataId": "img-001",
"status": 2,
"suggestion": 0,
"label": 100,
"resultType": 2,
"censorTime": 1629426386079,
"censorSource": 0,
"censorRound": 1,
"labels": [
{
"label": 400,
"level": 2,
"rate": 1.0
}
],
"censorLabels": [
{
"code": "审核标签编码",
"customCode": "自定义标签编码",
"name": "审核标签名称",
"desc": "风景"
}
],
"remark": "人审备注信息"
},
"ocr": { ... },
"face": { ... },
"quality": { ... },
"logo": { ... },
"discern": { ... },
"ad": { ... },
"userRisk": { ... },
"anticheat": { ... },
"riskControl": { ... },
"aigc": { ... },
"llmCheckInfo": [ ... ]
}
}
```
**antispam 字段完整说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| taskId | string | 任务ID |
| name | string | 图片名称 |
| dataId | string | 客户数据ID |
| status | int | 检测状态0=未开始1=检测中2=检测成功3=检测失败 |
| suggestion | int | 处置建议0=通过1=嫌疑2=不通过 |
| label | int | 一级分类 |
| secondLabel | string | 二级分类 |
| thirdLabel | string | 三级分类 |
| riskDescription | string | 风险描述 |
| resultType | int | 结果类型1=机器结果2=人审结果 |
| censorTime | int64 | 审核完成时间(毫秒时间戳) |
| censorSource | int | 审核来源 |
| censorRound | int | 审核轮数 |
| censorLabels | array | 审核标签数组 |
| remark | string | 审核备注 |
| overAllMarkDesc | string | 整体审核备注 |
| detailMarks | array | 细节标注 |
| labels | array | 分类标签详情 |
| url | string | 图片URL |
| imgMd5 | string | 图片MD5 |
| frameSize | int | 分帧数 |
| customLabels | array | 客户自定义标签 |
| censorExtension | object | 人审拓展字段 |
| strategyVersions | array | 策略版本 |
| hitType | int | 命中策略类型 |
| strategyType | int | 策略类型1=公有策略2=私有策略 |
| hitResult | string | 命中结果 |
| hitSource | int | 特征添加来源 |
| hidden | bool | 是否有隐藏文件 |
| hiddenFormat | string | 隐藏文件格式 |
| publicOpinionInfo | string | 舆情信息 |
**labels 数组结构**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| label | int | 标签类型 |
| level | int | 判断结果0=正常1=不确定2=确定 |
| rate | float | 置信度 |
| subLabels | array | 二级分类详情 |
| explain | string | LLM解释说明 |
| isLlmCheck | bool | 是否LLM检测命中 |
**censorLabels 数组结构**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| code | string | 审核标签编码 |
| customCode | string | 自定义标签编码 |
| name | string | 审核标签名称 |
| desc | string | 审核标签描述 |
| parentLabelId | string | 父标签ID |
| depth | int | 标签深度 |
### 2.3 接收图片检测回调(推送模式)
**接口地址**: `POST /yidun/receive-image-callback`
**易盾回调配置**:
- HTTP URL: 回调地址 `callbackUrl`
- HTTP Method: POST
- Content-Type: application/x-www-form-urlencoded
**请求参数** (form-data):
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| secretId | string | 是 | 产品密钥ID |
| businessId | string | 是 | 业务ID |
| signature | string | 是 | 请求签名 |
| callbackData | string | 是 | 回调数据(JSON字符串) |
**请求体示例**:
```
callbackData={"antispam":{...}}&signature=xxx&secretId=xxx&businessId=xxx
```
**回调数据格式**:
```json
{
"antispam": {
"taskId": "a2e53718f9c348d09206e4671304ca7c",
"suggestion": 2,
"remark": "人审备注信息,填写才会返回",
"dataId": "dataId",
"name": "name",
"labels": [
{
"label": 400,
"level": 2,
"rate": 1.0
},
{
"label": 500,
"level": 0,
"rate": 1.0
}
],
"censorLabels": [
{
"code": "审核标签编码",
"customCode": "自定义标签编码",
"name": "审核标签名称",
"desc": "风景"
}
],
"resultType": 2,
"censorTime": 1622036595467,
"censorSource": 0,
"censorRound": 1
}
}
```
**Suggestion值说明**:
| 值 | 含义 |
|----|------|
| 0 | 通过 |
| 1 | 嫌疑,需人工审核 |
| 2 | 不通过 |
**Status值说明**:
| 值 | 含义 |
|----|------|
| 0 | 未开始 |
| 1 | 检测中 |
| 2 | 检测成功 |
| 3 | 检测失败 |
---
## 3. 视频检测
### 提交视频检测任务
**接口地址**: `POST /yidun/detect-video`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| data_id | string | 是 | 数据唯一标识 |
| video_url | string | 是 | 视频URL地址 |
| callback_url | string | 否 | 回调地址 |
**请求示例**:
```bash
curl -X POST http://localhost:3002/yidun/detect-video \
-H "Content-Type: application/json" \
-d '{
"data_id": "video-001",
"video_url": "https://example.com/video.mp4"
}'
```
**响应示例**:
```json
{
"code": 0,
"message": "",
"data": {
"taskId": "c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8",
"dataId": "video-001",
"dealingCount": 0
}
}
```
**响应说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| taskId | string | 任务ID用于后续查询检测结果 |
| dataId | string | 调用检测时传递的数据ID |
| dealingCount | int64 | 缓冲池排队待处理数据量 |
**注意**: 视频检测是异步的,检测时间取决于视频长度(几分钟到几十分钟)。建议配置回调地址接收结果。
### 3.2 查询视频检测结果(轮询模式)
**接口地址**: `POST /yidun/GetVideoResult`
**SDK调用信息**:
- SDK方法: `VideoClient.Callback(request)`
- 请求地址: `http://as.dun.163.com/v2/videosolution/callback/results`
- 请求参数: `yidunRequestId` (taskId)
**请求示例**:
```bash
curl -X POST "http://localhost:3002/yidun/GetVideoResult" \
-H "Content-Type: application/json" \
-d '{"taskId": "c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8"}'
```
**响应示例**:
```json
{
"code": 0,
"message": "",
"data": {
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
"status": 2,
"suggestion": 2,
"label": 100,
"resultType": 1,
"dataId": "video-001",
"censorTime": 1633759853762,
"duration": 71339,
"antispam": {
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
"suggestion": 2,
"status": 2,
"resultType": 1,
"censorSource": 2,
"checkTime": 1633759861164,
"censorTime": 1633759853762,
"duration": 71339,
"censorLabels": [
{
"code": "101",
"desc": "自定义标签",
"customCode": "68684"
}
],
"evidences": {
"images": [...],
"text": {...},
"audio": {...},
"video": {...}
}
},
"language": { ... },
"voice": { ... },
"asr": { ... },
"ocr": { ... },
"discern": { ... },
"logo": { ... },
"face": { ... },
"aigc": { ... },
"quality": { ... }
}
}
```
**antispam 字段完整说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| taskId | string | 任务ID |
| dataId | string | 客户数据ID |
| callback | string | 回调参数 |
| suggestion | int | 处置建议0=通过1=嫌疑2=不通过 |
| status | int | 检测状态0=未开始1=检测中2=检测成功3=检测失败 |
| resultType | int | 结果类型1=机器结果2=人审结果 |
| censorRound | int | 人审轮次 |
| censor | string | 人审操作人 |
| censorSource | int | 审核来源0=易盾人审1=客户人审2=易盾机审 |
| checkTime | int64 | 机器检测结束时间 |
| censorTime | int64 | 人工审核完成时间 |
| duration | int64 | 音视频时长(毫秒) |
| durationMs | int64 | 音频时长(毫秒) |
| label | int | 一级垃圾类型 |
| secondLabel | string | 二级垃圾类型 |
| thirdLabel | string | 三级垃圾类型 |
| riskDescription | string | 风险描述 |
| picCount | int64 | 截图数量 |
| censorLabels | array | 审核标签数组 |
| censorExtension | object | 质检扩展结果 |
| evidences | object | 机器检测证据信息 |
| solutionExtra | object | 额外信息 |
| reviewEvidences | object | 人审证据信息 |
**evidences 对象说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| text | object | 文本证据(标题、简介等) |
| images | array | 图片证据(封面、截图中的图片) |
| audio | object | 音频证据(人声内容) |
| video | object | 视频证据(视频画面) |
**CensorSource值说明**:
| 值 | 含义 |
|----|------|
| 0 | 易盾人审 |
| 1 | 客户人审 |
| 2 | 易盾机审 |
### 3.3 接收视频检测回调(推送模式)
**接口地址**: `POST /yidun/receive-video-callback`
**易盾回调配置**:
- HTTP URL: 回调地址 `callbackUrl`
- HTTP Method: POST
- Content-Type: application/x-www-form-urlencoded
**请求参数** (form-data):
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| secretId | string | 是 | 产品密钥ID |
| signature | string | 是 | 请求签名 |
| callbackData | string | 是 | 回调数据(JSON字符串) |
**请求体示例**:
```
callbackData={"antispam":{...}}&signature=xxx&secretId=xxx
```
**回调数据格式**:
```json
{
"antispam": {
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
"suggestion": 2,
"status": 2,
"resultType": 1,
"censorSource": 2,
"checkTime": 1633759861164,
"censorTime": 1633759853762,
"duration": 71339,
"censorLabels": [
{
"code": "101",
"desc": "自定义标签",
"customCode": "68684"
}
],
"evidences": {
"images": [
{
"censorType": 0,
"labels": [
{
"label": 100,
"level": 2,
"rate": 0.9999,
"subLabels": [
{
"details": {
"hitInfos": [
{
"group": "色情部位分组",
"value": "女胸"
}
]
},
"rate": 1,
"subLabel": 10002
}
]
}
],
"name": "gpqis0e92czvfliemjpa3neg02009q6a",
"resultType": 1,
"status": 2,
"suggestion": 2,
"taskId": "0b2dd0e561a8457fbfcf7d79378eec37"
}
],
"text": {
"taskId": "44i3effo1j5w5for9l8xtdjg02009q6a",
"suggestion": 2,
"resultType": 1,
"censorType": 0,
"isRelatedHit": false,
"labels": [
{
"label": 200,
"level": 2,
"subLabels": [
{
"subLabel": "200009",
"details": {
"hitInfos": [
{
"value": "加我",
"positions": [
{
"fieldName": "content",
"startPos": 5,
"endPos": 8
}
]
}
]
}
}
]
}
]
},
"audio": {
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
"dataId": "",
"status": 2,
"suggestion": 2,
"label": 100,
"resultType": 1,
"callback": "",
"censorSource": 2,
"censorTime": 1633759861065,
"segments": [
{
"startTime": 0,
"endTime": 6,
"content": "第一次用这个软件上了半天,全是长得漂亮呢?",
"type": 0,
"labels": [
{
"label": 100,
"level": 2,
"subLabels": [
{
"subLabel": "100001",
"details": {
"hitInfos": [
{
"value": "120",
"startTime": 1684201,
"endTime": 1684201
}
],
"keywords": [
{
"word": "自定义敏感词"
}
],
"libInfos": [
{
"listType": 1,
"entity": "127.0.0.1"
}
]
}
}
]
}
]
}
],
"duration": 71
},
"video": {
"taskId": "18xrunm6fr35t49nnv506ukg02009q66",
"dataId": "",
"status": 2,
"suggestion": 2,
"resultType": 1,
"censorSource": 2,
"censorTime": 1633759858920,
"pictures": [
{
"type": 1,
"url": "https://xxx.nosdn.127.net/xxx.jpg",
"startTime": 5000,
"endTime": 5000,
"labels": [
{
"label": 100,
"level": 2,
"rate": 0.95157,
"subLabels": [
{
"subLabel": 10007,
"rate": 0.926,
"details": {
"hitInfos": [
{
"value": "卡通色情",
"group": "色情部位分组"
}
]
}
}
]
}
],
"censorSource": 2,
"frontPics": [
{
"url": "https://xxx.nosdn.127.net/xxx_0_0.jpg"
}
],
"backPics": [
{
"url": "https://xxx.nosdn.127.net/xxx_2_10000.jpg"
}
]
}
]
}
}
}
}
```
**Suggestion值说明**:
| 值 | 含义 |
|----|------|
| 0 | 通过 |
| 1 | 嫌疑,需人工审核 |
| 2 | 不通过 |
**Status值说明**:
| 值 | 含义 |
|----|------|
| 0 | 未开始 |
| 1 | 检测中 |
| 2 | 检测成功 |
| 3 | 检测失败 |
**images/images.labels 结构说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| label | int | 标签类型 |
| level | int | 级别0=正常1=嫌疑2=确定违规 |
| rate | float | 置信度 |
| subLabels | array | 二级分类详情 |
| subLabels.details.hitInfos | array | 命中信息 |
| subLabels.details.hitInfos.group | string | 分组名称 |
| subLabels.details.hitInfos.value | string | 命中值 |
**audio.segments 结构说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| startTime | int | 开始时间(秒) |
| endTime | int | 结束时间(秒) |
| content | string | 语音识别原文 |
| type | int | 片段类型0=语音识别1=声纹检测 |
| labels | array | 分类标签 |
| labels.details.keywords | array | 自定义敏感词 |
| labels.details.libInfos | array | 自定义名单 |
| labels.details.hitInfos | array | 命中内容 |
**video.pictures 结构说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| type | int | 截图类型 |
| url | string | 截图URL |
| startTime | int64 | 开始时间(毫秒) |
| endTime | int64 | 结束时间(毫秒) |
| labels | array | 分类标签 |
| frontPics | array | 关联前帧图片 |
| backPics | array | 关联后帧图片 |
---
## 回调与轮询接口
### 轮询模式接口详解
#### 轮询所有待处理结果
```
POST /yidun/callback/poll
```
**说明**:轮询所有图片和视频的待处理检测结果
**响应示例**
```json
{
"code": 200,
"msg": "轮询完成,成功处理 5 条,失败 1 条",
"data": {
"success_count": 5,
"fail_count": 1,
"pending_count": 10
}
}
```
#### 获取待处理数量
```
GET /yidun/callback/pendingCount
```
**响应示例**
```json
{
"code": 200,
"data": {
"pending_count": 15,
"description": "待查询结果的日志数量状态为pending且有taskID"
}
}
```
#### 查询单个结果
```
POST /yidun/callback/pollTask?taskId=xxx&type=image
```
**参数说明**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| taskId | string | 是 | 易盾任务ID |
| type | string | 否 | 类型:`image`/`video`,不填则自动识别 |
**响应示例**
```json
{
"code": 200,
"msg": "查询并处理成功"
}
```
---
## 使用示例
### 轮询模式使用流程
```bash
# 1. 查看待处理数量
curl http://localhost:3001/yidun/callback/pendingCount
# 2. 执行轮询(所有)
curl -X POST http://localhost:3001/yidun/callback/poll
# 3. 或分别轮询
curl -X POST http://localhost:3001/yidun/callback/pollImage
curl -X POST http://localhost:3001/yidun/callback/pollVideo
# 4. 查询单个结果
curl -X POST "http://localhost:3001/yidun/callback/pollTask?taskId=abc123&type=image"
```
### 配置定时轮询
```bash
# 每分钟轮询一次
*/1 * * * * curl -X POST http://localhost:3001/yidun/callback/poll
# 或更保守的频率每5分钟
*/5 * * * * curl -X POST http://localhost:3001/yidun/callback/poll
```
---
## 状态说明
### 检测状态转换
```
┌─────────────────────────────────────────────────────────────┐
│ 送检前 │
│ tencent_image/tencent_video: status = "pending" │
└─────────────────────────────────────────────────────────────┘
↓ 定时任务/手动送检
┌─────────────────────────────────────────────────────────────┐
│ 提交检测 │
│ material_verify_log: verify_status = "PENDING" │
│ material_verify_log: task_id = "易盾任务ID" │
│ tencent_xxx: status = "submitting" │
└─────────────────────────────────────────────────────────────┘
↓ 等待检测完成
↓ (回调模式)或(轮询查询)
┌─────────────────────────────────────────────────────────────┐
│ 检测完成 │
│ material_verify_log: verify_status = "VERIFIED" (通过) │
│ 或 "REJECTED" (不通过) │
│ 或 "PENDING" (嫌疑,需人工审核) │
│ tencent_xxx: status = "VERIFIED"/"REJECTED"/"PENDING" │
└─────────────────────────────────────────────────────────────┘
```
### 状态值说明
| 状态值 | 说明 | 触发条件 |
|--------|------|----------|
| `pending` / `PENDING` | 待检测 | 素材创建时 |
| `submitting` | 送检中 | 提交至易盾检测 |
| `VERIFIED` | 校验通过 | 易盾建议通过suggestion=0|
| `REJECTED` | 校验不通过 | 易盾建议不通过suggestion=2或检测失败 |
| `PENDING` (人审) | 嫌疑待审 | 易盾建议人工审核suggestion=1|
### 易盾处置建议对照
| suggestion值 | 说明 | 系统状态 |
|-------------|------|----------|
| 0 | 通过 | VERIFIED |
| 1 | 嫌疑,需人工审核 | PENDING |
| 2 | 不通过 | REJECTED |
---
## 常见问题
### Q1: 轮询后待处理数量没有减少?
**可能原因**
1. 检测仍在进行中(易盾尚未返回结果)
2. 上次查询出错,状态已更新为 REJECTED
**排查方法**
```bash
# 查看日志
grep "检测仍在进行中" resource/log/server/cid.log
# 查看数据库状态
SELECT id, task_id, verify_status FROM material_verify_log WHERE task_id = 'xxx';
```
### Q2: 如何判断是图片还是视频?
```bash
# 方法1查询日志
SELECT id, material_type, task_id, verify_status FROM material_verify_log WHERE task_id = 'xxx';
# 方法2调用接口指定类型
curl -X POST "http://localhost:3001/yidun/callback/pollTask?taskId=xxx&type=image"
```
### Q3: 回调模式收不到回调?
**排查步骤**
1. 确认公网地址可访问:`curl http://your-domain.com:3001/yidun/callback/receiveImage`
2. 确认易盾控制台配置了正确的回调地址
3. 检查服务器防火墙/安全组是否开放端口
4. 查看日志确认请求是否到达:`grep "收到易盾" resource/log/server/cid.log`
### Q4: 状态不一致?
如果 `material_verify_log``tencent_image/video` 表状态不一致,检查:
1. 代码执行过程中是否有报错
2. 是否有并发更新导致覆盖
3. 日志表和原表更新是否在同一事务中
---
## 错误码说明
| code | 说明 |
|------|------|
| 0 | 成功 |
| 400 | 请求参数错误 |
| 500 | 服务器内部错误 |
**易盾API错误码**:
| 错误码 | 说明 |
|--------|------|
| 200 | 成功 |
| 401 | 认证失败SecretID/SecretKey错误 |
| 403 | 权限不足 |
| 429 | 请求频率超限 |
---
## Go代码调用示例
```go
// 文本检测
func detectText() (string, error) {
req := map[string]interface{}{
"data_id": "text-001",
"content": "这是一段测试文本",
}
jsonData, _ := json.Marshal(req)
resp, err := http.Post("http://localhost:3002/yidun/detect-text", "application/json", bytes.NewBuffer(jsonData))
// ...
}
// 图片检测
func detectImage() (string, error) {
req := map[string]interface{}{
"data_id": "img-001",
"image_url": "https://example.com/image.jpg",
}
jsonData, _ := json.Marshal(req)
resp, err := http.Post("http://localhost:3002/yidun/detect-image", "application/json", bytes.NewBuffer(jsonData))
// ...
}
// 视频检测
func detectVideo() (string, error) {
req := map[string]interface{}{
"data_id": "video-001",
"video_url": "https://example.com/video.mp4",
}
jsonData, _ := json.Marshal(req)
resp, err := http.Post("http://localhost:3002/yidun/detect-video", "application/json", bytes.NewBuffer(jsonData))
// ...
}
```
---
**最后更新**: 2026-05-14