datai/datai-scenes/datai-scene-salesforce/docs/api-docs/2026-02-06-003-06-api.md

576 lines
15 KiB
Markdown
Raw Normal View History

# API 文档 - 检索操作
## 元数据
- 需求编号003-06
- 创建时间2026-02-06
- 创建人AI Assistant
- 状态:已完成
- 版本v1.0.0
## API 概述
本文档描述了 Salesforce Metadata API 检索操作相关的 REST API 接口,包括元数据检索请求提交、状态轮询、状态检查和历史查询功能。
### 核心功能
1. **提交检索请求**:向 Salesforce 提交元数据检索请求,返回异步操作 ID
2. **轮询检索状态**:循环检查检索状态直到完成或超时
3. **单次状态检查**:单次检查检索状态,返回当前状态
4. **检索历史查询**:查询检索操作的历史记录
5. **检索记录查询**:根据 asyncId 查询具体的检索记录
### 技术栈
- Spring Boot 2.7.x
- Spring Security权限控制
- MyBatis Plus数据持久化
- Salesforce Metadata API
### 基础路径
```
/salesforce/metadata/retrieve
```
## 接口列表
### 接口 1提交检索请求
#### 功能描述
向 Salesforce 提交元数据检索请求。检索操作是异步的,提交后会立即返回一个异步操作 IDasyncId客户端需要使用这个 ID 轮询检索状态或查询结果。
#### 请求方式
`POST`
#### 请求路径
```
/salesforce/metadata/retrieve
```
#### 权限要求
- 权限标识:`salesforce:metadata:retrieve`
- 使用 `@PreAuthorize("@ss.hasPermi('salesforce:metadata:retrieve')")` 控制
#### 请求参数
##### 请求体参数JSON
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| apiVersion | Double | 是 | API 版本 | `59.0` |
| singlePackage | Boolean | 否 | 是否为单个包,默认 false | `false` |
| unpackaged | Object | 条件 | 未打包的元数据类型列表(与 packageNames 二选一) | 见下方示例 |
| packageNames | String[] | 条件 | 包名称列表(与 unpackaged 二选一) | `["MyPackage"]` |
| specificFiles | String[] | 否 | 特定文件列表 | `["package.xml"]` |
##### Unpackaged 对象结构
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| types | Array | 是 | 元数据类型列表 | 见下方示例 |
##### PackageTypeMember 对象结构
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| name | String | 是 | 元数据类型名称 | `"CustomObject"` |
| members | String[] | 是 | 成员列表,`*` 表示所有 | `["*"]` |
#### 请求示例
##### 示例 1检索所有 CustomObject
```json
POST /salesforce/metadata/retrieve
Content-Type: application/json
{
"apiVersion": 59.0,
"singlePackage": false,
"unpackaged": {
"types": [
{
"name": "CustomObject",
"members": ["*"]
}
]
}
}
```
##### 示例 2检索特定包
```json
POST /salesforce/metadata/retrieve
Content-Type: application/json
{
"apiVersion": 59.0,
"singlePackage": true,
"packageNames": ["MyManagedPackage"]
}
```
##### 示例 3检索多种元数据类型
```json
POST /salesforce/metadata/retrieve
Content-Type: application/json
{
"apiVersion": 59.0,
"unpackaged": {
"types": [
{
"name": "CustomObject",
"members": ["Account", "Contact"]
},
{
"name": "ApexClass",
"members": ["MyClass", "MyTestClass"]
},
{
"name": "ApexTrigger",
"members": ["*"]
}
]
}
}
```
#### 响应参数
##### 成功响应HTTP 200
| 参数名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| code | Integer | 状态码200 表示成功 | `200` |
| msg | String | 提示信息 | `"操作成功"` |
| data | Object | 异步结果对象 | 见下方说明 |
##### AsyncResult 对象
| 参数名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| id | String | 异步操作 ID | `"09Sxx0000000001EAA"` |
| done | Boolean | 是否完成 | `false` |
| state | String | 状态Queued、InProgress、Completed、Error | `"Queued"` |
#### 成功响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"id": "09Sxx0000000001EAA",
"done": false,
"state": "Queued"
}
}
```
#### 错误响应示例
```json
{
"code": 500,
"msg": "检索元数据失败: 连接超时",
"data": null
}
```
---
### 接口 2轮询检索状态
#### 功能描述
轮询检索状态直到完成或超时。此接口会循环检查检索状态,直到检索完成(成功或失败)或达到超时时间。适用于需要等待检索完成的场景。
#### 请求方式
`GET`
#### 请求路径
```
/salesforce/metadata/retrieve/status/{asyncId}
```
#### 权限要求
- 权限标识:`salesforce:metadata:retrieve`
#### 请求参数
##### 路径参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| asyncId | String | 是 | 异步操作 ID | `"09Sxx0000000001EAA"` |
##### 查询参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| interval | Long | 否 | 轮询间隔(毫秒),默认 5000 | `5000` |
| timeout | Long | 否 | 超时时间(毫秒),默认 3000005分钟 | `300000` |
#### 请求示例
```
GET /salesforce/metadata/retrieve/status/09Sxx0000000001EAA?interval=5000&timeout=300000
```
#### 响应参数
##### 成功响应HTTP 200
| 参数名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| code | Integer | 状态码200 表示成功 | `200` |
| msg | String | 提示信息 | `"操作成功"` |
| data | Object | 检索结果对象 | 见下方说明 |
##### RetrieveResultVo 对象
| 参数名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| asyncId | String | 异步操作 ID | `"09Sxx0000000001EAA"` |
| status | String | 检索状态 | `"Succeeded"` |
| success | Boolean | 是否成功 | `true` |
| zipFile | String | ZIP 文件数据Base64 编码) | `"UEsDBBQ..."` |
| errorMessage | String | 错误消息(失败时) | `null` |
| messages | Array | 检索消息列表 | 见下方说明 |
| completedTime | Date | 完成时间 | `"2026-02-06T10:30:00"` |
| done | Boolean | 是否完成 | `true` |
##### RetrieveMessageVo 对象
| 参数名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| fileName | String | 文件名 | `"objects/Account.object"` |
| problem | String | 问题描述 | `"Entity is not found"` |
| problemType | String | 问题类型 | `"Warning"` |
#### 成功响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"asyncId": "09Sxx0000000001EAA",
"status": "Succeeded",
"success": true,
"zipFile": "UEsDBBQACAAI...",
"errorMessage": null,
"messages": [],
"completedTime": "2026-02-06T10:30:00",
"done": true
}
}
```
#### 超时响应示例
```json
{
"code": 500,
"msg": "检索操作超时",
"data": null
}
```
---
### 接口 3单次检查状态
#### 功能描述
单次检查检索状态,立即返回当前状态。适用于前端主动轮询的场景,由前端控制轮询间隔。
#### 请求方式
`GET`
#### 请求路径
```
/salesforce/metadata/retrieve/check/{asyncId}
```
#### 权限要求
- 权限标识:`salesforce:metadata:retrieve`
#### 请求参数
##### 路径参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| asyncId | String | 是 | 异步操作 ID | `"09Sxx0000000001EAA"` |
#### 请求示例
```
GET /salesforce/metadata/retrieve/check/09Sxx0000000001EAA
```
#### 响应参数
##### 成功响应HTTP 200
与"轮询检索状态"接口的响应参数相同,但只返回当前状态,不会等待完成。
#### 进行中响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"asyncId": "09Sxx0000000001EAA",
"status": "InProgress",
"success": null,
"zipFile": null,
"errorMessage": null,
"messages": [],
"completedTime": null,
"done": false
}
}
```
#### 已完成响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"asyncId": "09Sxx0000000001EAA",
"status": "Succeeded",
"success": true,
"zipFile": "UEsDBBQACAAI...",
"errorMessage": null,
"messages": [],
"completedTime": "2026-02-06T10:30:00",
"done": true
}
}
```
---
### 接口 4获取检索历史
#### 功能描述
获取检索操作的历史记录列表。返回最近的检索记录,支持限制返回数量。
#### 请求方式
`GET`
#### 请求路径
```
/salesforce/metadata/retrieve/history
```
#### 权限要求
- 权限标识:`salesforce:metadata:retrieve`
#### 请求参数
##### 查询参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| limit | Integer | 否 | 返回数量限制,默认 50最大 100 | `50` |
#### 请求示例
```
GET /salesforce/metadata/retrieve/history?limit=20
```
#### 响应参数
##### 成功响应HTTP 200
| 参数名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| code | Integer | 状态码200 表示成功 | `200` |
| msg | String | 提示信息 | `"操作成功"` |
| data | Array | 检索历史列表 | 见下方说明 |
##### DataiMetadataRetrieve 对象
| 参数名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| id | Long | 记录 ID | `1` |
| asyncId | String | 异步操作 ID | `"09Sxx0000000001EAA"` |
| status | String | 检索状态 | `"Succeeded"` |
| done | Boolean | 是否完成 | `true` |
| message | String | 消息 | `"Retrieve completed successfully"` |
| errorMessage | String | 错误消息 | `null` |
| retrieveTime | Date | 检索时间 | `"2026-02-06T10:30:00"` |
| updateTime | Date | 更新时间 | `"2026-02-06T10:30:00"` |
| userId | Long | 用户 ID | `1` |
| createBy | String | 创建者 | `"admin"` |
| createTime | Date | 创建时间 | `"2026-02-06T10:25:00"` |
#### 成功响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": [
{
"id": 1,
"asyncId": "09Sxx0000000001EAA",
"status": "Succeeded",
"done": true,
"message": "Retrieve completed successfully",
"errorMessage": null,
"retrieveTime": "2026-02-06T10:30:00",
"updateTime": "2026-02-06T10:30:00",
"userId": 1,
"createBy": "admin",
"createTime": "2026-02-06T10:25:00"
},
{
"id": 2,
"asyncId": "09Sxx0000000002EAA",
"status": "Failed",
"done": true,
"message": null,
"errorMessage": "Invalid API version",
"retrieveTime": "2026-02-06T10:20:00",
"updateTime": "2026-02-06T10:20:00",
"userId": 1,
"createBy": "admin",
"createTime": "2026-02-06T10:15:00"
}
]
}
```
---
### 接口 5查询检索记录
#### 功能描述
根据 asyncId 查询具体的检索记录。用于获取某个特定检索操作的详细信息。
#### 请求方式
`GET`
#### 请求路径
```
/salesforce/metadata/retrieve/record/{asyncId}
```
#### 权限要求
- 权限标识:`salesforce:metadata:retrieve`
#### 请求参数
##### 路径参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| asyncId | String | 是 | 异步操作 ID | `"09Sxx0000000001EAA"` |
#### 请求示例
```
GET /salesforce/metadata/retrieve/record/09Sxx0000000001EAA
```
#### 响应参数
##### 成功响应HTTP 200
与"获取检索历史"接口中的单个对象结构相同。
#### 成功响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"id": 1,
"asyncId": "09Sxx0000000001EAA",
"status": "Succeeded",
"done": true,
"message": "Retrieve completed successfully",
"errorMessage": null,
"retrieveTime": "2026-02-06T10:30:00",
"updateTime": "2026-02-06T10:30:00",
"userId": 1,
"createBy": "admin",
"createTime": "2026-02-06T10:25:00"
}
}
```
#### 记录不存在响应示例
```json
{
"code": 200,
"msg": "操作成功",
"data": null
}
```
---
## 错误码
### 业务错误码
| 错误码 | 说明 | 处理建议 |
|--------|------|----------|
| RETRIEVE_001 | 获取 MetadataConnection 失败 | 检查 Salesforce 连接配置 |
| RETRIEVE_002 | 检索元数据操作失败 | 检查请求参数和 API 版本 |
| RETRIEVE_003 | 检索操作超时 | 增加超时时间或稍后重试 |
| RETRIEVE_004 | 检查检索状态失败 | 检查 asyncId 是否正确 |
| RETRIEVE_005 | 获取检索历史失败 | 检查数据库连接 |
| RETRIEVE_006 | 根据 asyncId 查询检索记录失败 | 检查 asyncId 是否正确 |
| RETRIEVE_007 | 请求参数不能为空 | 检查请求体是否为空 |
| RETRIEVE_008 | API 版本不能为空 | 检查 apiVersion 字段 |
| RETRIEVE_009 | 未打包的元数据类型列表不能为空 | 检查 unpackaged.types 字段 |
| RETRIEVE_010 | 检索元数据失败 | 查看详细错误信息 |
### HTTP 状态码
| 状态码 | 说明 |
|--------|------|
| 200 | 请求成功 |
| 400 | 请求参数错误 |
| 401 | 未授权,需要登录 |
| 403 | 禁止访问,权限不足 |
| 500 | 服务器内部错误 |
---
## 使用流程
### 典型使用场景 1简单检索并等待结果
```
1. 调用 POST /salesforce/metadata/retrieve 提交检索请求
2. 获取返回的 asyncId
3. 调用 GET /salesforce/metadata/retrieve/status/{asyncId} 轮询状态
4. 等待返回结果(包含 ZIP 文件 Base64 数据)
5. 前端解码 Base64 并下载 ZIP 文件
```
### 典型使用场景 2前端主动轮询
```
1. 调用 POST /salesforce/metadata/retrieve 提交检索请求
2. 获取返回的 asyncId
3. 前端使用定时器,每隔 5 秒调用 GET /salesforce/metadata/retrieve/check/{asyncId}
4. 检查返回的 done 字段,为 true 时表示完成
5. 如果成功,获取 ZIP 文件数据;如果失败,显示错误信息
```
### 典型使用场景 3查询历史记录
```
1. 调用 GET /salesforce/metadata/retrieve/history 获取检索历史列表
2. 用户选择某条历史记录
3. 调用 GET /salesforce/metadata/retrieve/record/{asyncId} 获取详细信息
4. 显示检索状态和结果
```
---
## 注意事项
### 1. 异步操作特性
- 检索操作是异步的,提交请求后立即返回 asyncId
- 需要使用 asyncId 轮询或查询状态
- 检索时间取决于元数据数量和复杂度,可能需要几秒到几分钟
### 2. ZIP 文件处理
- ZIP 文件内容以 Base64 编码返回
- 不在数据库中存储 ZIP 文件内容
- 对于大文件,建议设置合理的超时时间
### 3. 超时控制
- 轮询接口默认超时时间为 5 分钟
- 可以通过 timeout 参数调整超时时间
- 超时后会抛出异常,需要客户端处理
### 4. 权限控制
- 所有接口都需要 `salesforce:metadata:retrieve` 权限
- 使用 Spring Security 的 `@PreAuthorize` 注解控制
- 确保用户有权限访问目标 Salesforce 组织的元数据
---
## 相关文档
- [需求文档](../requirements/sub/2026-01-28-003-06-检索操作.md)
- [设计文档](../design/2026-02-03-003-06-检索操作-设计.md)
- [决策记录](../decisions/2026-02-03-003-06-ADR-检索操作技术选型.md)
- [变更日志](../changelog/2026-02-06-003-06-changelog.md)
- [复盘文档](../retros/2026-02-06-003-06-retro.md)
- [会话记录](../sessions/2026-02-03-003-06-session.md)