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

740 lines
19 KiB
Markdown
Raw Permalink 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 文档 - Apex 代码编译和执行
## 元数据
- 需求编号002-02
- 需求名称Apex 代码编译和执行
- 创建时间2026-02-02
- 创建人AI Assistant
- 版本v1.0.0
- 状态:已完成
## API 概述
Apex 代码编译和执行 API 提供了一套完整的接口,用于在 Salesforce 平台上编译和执行 Apex 代码。支持编译 Apex 类、编译 Apex 触发器、编译并运行测试、执行匿名 Apex 代码等功能,同时提供查询编译历史、测试结果和代码覆盖率的能力。
### 核心功能
1. **编译 Apex 类**:将 Apex 类代码编译到 Salesforce 平台
2. **编译 Apex 触发器**:将 Apex 触发器代码编译到 Salesforce 平台
3. **编译并测试**:编译代码并运行单元测试
4. **执行匿名代码**:执行匿名的 Apex 代码片段
5. **查询功能**:查询编译历史、测试结果和代码覆盖率
### 技术架构
- **协议**HTTP/HTTPS
- **数据格式**JSON
- **认证方式**JWT Token通过请求头 Authorization: Bearer {token}
- **权限控制**Spring Security @PreAuthorize
- **基础路径**`/api/apex`
## 接口列表
### 1. 编译 Apex 类
**功能描述**:编译一个或多个 Apex 类到 Salesforce 平台
**请求方式**POST
**请求路径**`/api/apex/compile/classes`
**权限要求**`@PreAuthorize("@ss.hasPermi('apex:compile:execute')")`
**请求参数**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| classes | String[] | 是 | Apex 类代码数组,每个元素是一个完整的类定义 |
**请求示例**
```json
{
"classes": [
"public class MyClass {\n public String name;\n public Integer count;\n}",
"public class AnotherClass {\n public static void doSomething() {\n System.debug('Hello');\n }\n}"
]
}
```
**响应参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 状态码200 成功,其他失败) |
| msg | String | 提示信息 |
| data | CompileClassResultVo[] | 编译结果数组 |
**CompileClassResultVo 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | Boolean | 是否编译成功 |
| id | String | 编译后的类 ID |
| name | String | 类名 |
| problem | String | 编译问题描述(如果有) |
| line | Integer | 错误行号(如果有) |
| column | Integer | 错误列号(如果有) |
| bodyCrc | Long | 代码体 CRC 校验值 |
| problems | CompileIssueVo[] | 编译问题数组 |
| warnings | CompileIssueVo[] | 编译警告数组 |
**成功响应示例**
```json
{
"code": 200,
"msg": "编译成功",
"data": [
{
"success": true,
"id": "01pxx0000003DHb2AAG",
"name": "MyClass",
"problem": null,
"line": 0,
"column": 0,
"bodyCrc": 123456789,
"problems": [],
"warnings": []
},
{
"success": true,
"id": "01pxx0000003DHc2AAG",
"name": "AnotherClass",
"problem": null,
"line": 0,
"column": 0,
"bodyCrc": 987654321,
"problems": [],
"warnings": []
}
]
}
```
**失败响应示例**
```json
{
"code": 500,
"msg": "编译失败: 类 MyClass 编译错误",
"data": [
{
"success": false,
"id": null,
"name": "MyClass",
"problem": "Unexpected token 'public'",
"line": 2,
"column": 5,
"bodyCrc": 0,
"problems": [
{
"message": "Unexpected token 'public'",
"line": 2,
"column": 5
}
],
"warnings": []
}
]
}
```
---
### 2. 编译 Apex 触发器
**功能描述**:编译一个或多个 Apex 触发器到 Salesforce 平台
**请求方式**POST
**请求路径**`/api/apex/compile/triggers`
**权限要求**`@PreAuthorize("@ss.hasPermi('apex:compile:execute')")`
**请求参数**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| triggers | String[] | 是 | Apex 触发器代码数组,每个元素是一个完整的触发器定义 |
**请求示例**
```json
{
"triggers": [
"trigger MyTrigger on Account (before insert) {\n for (Account acc : Trigger.new) {\n acc.Name = acc.Name.toUpperCase();\n }\n}"
]
}
```
**响应参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 状态码200 成功,其他失败) |
| msg | String | 提示信息 |
| data | CompileTriggerResultVo[] | 编译结果数组 |
**CompileTriggerResultVo 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | Boolean | 是否编译成功 |
| id | String | 编译后的触发器 ID |
| name | String | 触发器名称 |
| problem | String | 编译问题描述(如果有) |
| line | Integer | 错误行号(如果有) |
| column | Integer | 错误列号(如果有) |
| bodyCrc | Long | 代码体 CRC 校验值 |
| problems | CompileIssueVo[] | 编译问题数组 |
| warnings | CompileIssueVo[] | 编译警告数组 |
**成功响应示例**
```json
{
"code": 200,
"msg": "编译成功",
"data": [
{
"success": true,
"id": "01qxx0000003DHb2AAG",
"name": "MyTrigger",
"problem": null,
"line": 0,
"column": 0,
"bodyCrc": 123456789,
"problems": [],
"warnings": []
}
]
}
```
---
### 3. 编译并测试
**功能描述**:编译 Apex 代码并运行单元测试
**请求方式**POST
**请求路径**`/api/apex/compile/compile-and-test`
**权限要求**`@PreAuthorize("@ss.hasPermi('apex:compile:execute')")`
**请求参数**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| checkOnly | Boolean | 否 | 是否仅检查而不实际部署,默认 false |
| classes | String[] | 否 | Apex 类代码数组 |
| triggers | String[] | 否 | Apex 触发器代码数组 |
| deleteClasses | String[] | 否 | 要删除的类名称数组 |
| deleteTriggers | String[] | 否 | 要删除的触发器名称数组 |
| runTestsRequest | RunTestsRequestDto | 否 | 测试运行请求 |
**RunTestsRequestDto 字段说明**
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| allTests | Boolean | 否 | 是否运行所有测试,默认 false |
| classes | String[] | 否 | 要测试的类名称数组 |
| namespace | String | 否 | 命名空间 |
| maxFailedTests | Integer | 否 | 最大失败测试数 |
**请求示例**
```json
{
"checkOnly": false,
"classes": [
"public class TestClass {\n @isTest\n static void testMethod() {\n System.assertEquals(1, 1);\n }\n}"
],
"runTestsRequest": {
"allTests": false,
"classes": ["TestClass"]
}
}
```
**响应参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 状态码200 成功,其他失败) |
| msg | String | 提示信息 |
| data | CompileAndTestResultVo | 编译并测试结果 |
**CompileAndTestResultVo 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| compileSuccess | Boolean | 编译是否成功 |
| testSuccess | Boolean | 测试是否全部通过 |
| compileResults | CompileClassResultVo[] | 类编译结果 |
| triggerResults | CompileTriggerResultVo[] | 触发器编译结果 |
| testResults | RunTestsResultVo | 测试结果 |
**RunTestsResultVo 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| numTestsRun | Integer | 运行的测试数量 |
| numFailures | Integer | 失败的测试数量 |
| totalTime | Double | 总执行时间(毫秒) |
| successes | TestSuccessVo[] | 成功的测试 |
| failures | TestFailureVo[] | 失败的测试 |
| codeCoverage | CodeCoverageResultVo[] | 代码覆盖率结果 |
| apexLogId | String | Apex 日志 ID |
**成功响应示例**
```json
{
"code": 200,
"msg": "编译并测试成功",
"data": {
"compileSuccess": true,
"testSuccess": true,
"compileResults": [
{
"success": true,
"id": "01pxx0000003DHb2AAG",
"name": "TestClass",
"problem": null,
"line": 0,
"column": 0,
"bodyCrc": 123456789,
"problems": [],
"warnings": []
}
],
"triggerResults": [],
"testResults": {
"numTestsRun": 1,
"numFailures": 0,
"totalTime": 150.5,
"successes": [
{
"className": "TestClass",
"methodName": "testMethod",
"time": 150.5
}
],
"failures": [],
"codeCoverage": [
{
"id": "01pxx0000003DHb2AAG",
"name": "TestClass",
"type": "Class",
"namespace": null,
"numLocations": 10,
"numLocationsNotCovered": 2,
"coveragePercent": 80.0
}
],
"apexLogId": "07Lxx0000003DHb2AAG"
}
}
}
```
---
### 4. 执行匿名 Apex 代码
**功能描述**:执行匿名的 Apex 代码片段
**请求方式**POST
**请求路径**`/api/apex/execute/anonymous`
**权限要求**`@PreAuthorize("@ss.hasPermi('apex:execute:anonymous')")`
**请求参数**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| code | String | 是 | 要执行的 Apex 代码 |
**请求示例**
```json
{
"code": "System.debug('Hello, Salesforce!');\nInteger sum = 1 + 2;\nSystem.debug('Sum: ' + sum);"
}
```
**响应参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 状态码200 成功,其他失败) |
| msg | String | 提示信息 |
| data | ExecuteAnonymousResultVo | 执行结果 |
**ExecuteAnonymousResultVo 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| success | Boolean | 是否执行成功 |
| compiled | Boolean | 是否编译成功 |
| compileProblem | String | 编译问题描述(如果有) |
| exceptionMessage | String | 异常消息(如果有) |
| exceptionStackTrace | String | 异常堆栈(如果有) |
| line | Integer | 错误行号(如果有) |
| column | Integer | 错误列号(如果有) |
**成功响应示例**
```json
{
"code": 200,
"msg": "执行成功",
"data": {
"success": true,
"compiled": true,
"compileProblem": null,
"exceptionMessage": null,
"exceptionStackTrace": null,
"line": 0,
"column": 0
}
}
```
**编译失败响应示例**
```json
{
"code": 500,
"msg": "编译失败",
"data": {
"success": false,
"compiled": false,
"compileProblem": "Unexpected token 'System'",
"exceptionMessage": null,
"exceptionStackTrace": null,
"line": 1,
"column": 1
}
}
```
**运行时异常响应示例**
```json
{
"code": 500,
"msg": "执行失败",
"data": {
"success": false,
"compiled": true,
"compileProblem": null,
"exceptionMessage": "Divide by 0",
"exceptionStackTrace": "AnonymousBlock: line 1, column 1",
"line": 1,
"column": 1
}
}
```
---
### 5. 查询编译历史
**功能描述**:查询 Apex 代码编译历史记录
**请求方式**GET
**请求路径**`/api/apex/compile/history`
**权限要求**`@PreAuthorize("@ss.hasPermi('apex:compile:query')")`
**请求参数**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| compileType | String | 否 | 编译类型class/trigger/compile_and_test |
| startTime | String | 否 | 开始时间格式yyyy-MM-dd HH:mm:ss |
| endTime | String | 否 | 结束时间格式yyyy-MM-dd HH:mm:ss |
| pageNum | Integer | 否 | 页码,默认 1 |
| pageSize | Integer | 否 | 每页大小,默认 10 |
**响应参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 状态码200 成功,其他失败) |
| msg | String | 提示信息 |
| data | PageResult<DataiApexCompileHistory> | 分页结果 |
**DataiApexCompileHistory 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| id | Long | 主键 ID |
| compileType | String | 编译类型 |
| codeContent | String | 代码内容 |
| compileSuccess | Boolean | 编译是否成功 |
| compileProblem | String | 编译问题描述 |
| compileTime | Date | 编译时间 |
| createBy | String | 创建人 |
| createTime | Date | 创建时间 |
**成功响应示例**
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"total": 100,
"rows": [
{
"id": 1,
"compileType": "class",
"codeContent": "public class MyClass { ... }",
"compileSuccess": true,
"compileProblem": null,
"compileTime": "2026-02-02T10:30:00",
"createBy": "admin",
"createTime": "2026-02-02T10:30:00"
}
]
}
}
```
---
### 6. 查询测试结果
**功能描述**:查询 Apex 测试结果记录
**请求方式**GET
**请求路径**`/api/apex/test/results`
**权限要求**`@PreAuthorize("@ss.hasPermi('apex:test:query')")`
**请求参数**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| testRunId | String | 否 | 测试运行 ID |
| startTime | String | 否 | 开始时间格式yyyy-MM-dd HH:mm:ss |
| endTime | String | 否 | 结束时间格式yyyy-MM-dd HH:mm:ss |
| pageNum | Integer | 否 | 页码,默认 1 |
| pageSize | Integer | 否 | 每页大小,默认 10 |
**响应参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 状态码200 成功,其他失败) |
| msg | String | 提示信息 |
| data | PageResult<DataiApexTestResult> | 分页结果 |
**DataiApexTestResult 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| id | Long | 主键 ID |
| testRunId | String | 测试运行 ID |
| numTestsRun | Integer | 运行的测试数量 |
| numFailures | Integer | 失败的测试数量 |
| totalTime | Double | 总执行时间(毫秒) |
| apexLogId | String | Apex 日志 ID |
| testTime | Date | 测试时间 |
| allPassed | Boolean | 是否全部通过 |
| totalCoverage | Double | 总体覆盖率 |
| createBy | String | 创建人 |
| createTime | Date | 创建时间 |
**成功响应示例**
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"total": 50,
"rows": [
{
"id": 1,
"testRunId": "707xx0000003DHb2AAG",
"numTestsRun": 10,
"numFailures": 0,
"totalTime": 1500.5,
"apexLogId": "07Lxx0000003DHb2AAG",
"testTime": "2026-02-02T10:30:00",
"allPassed": true,
"totalCoverage": 85.5,
"createBy": "admin",
"createTime": "2026-02-02T10:30:00"
}
]
}
}
```
---
### 7. 查询代码覆盖率
**功能描述**:查询 Apex 代码覆盖率记录
**请求方式**GET
**请求路径**`/api/apex/test/coverage`
**权限要求**`@PreAuthorize("@ss.hasPermi('apex:test:query')")`
**请求参数**
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| testResultId | Long | 否 | 测试结果 ID |
| name | String | 否 | 类/触发器名称 |
| type | String | 否 | 类型Class/Trigger |
| pageNum | Integer | 否 | 页码,默认 1 |
| pageSize | Integer | 否 | 每页大小,默认 10 |
**响应参数**
| 参数名 | 类型 | 说明 |
|--------|------|------|
| code | Integer | 状态码200 成功,其他失败) |
| msg | String | 提示信息 |
| data | PageResult<DataiApexCodeCoverage> | 分页结果 |
**DataiApexCodeCoverage 字段说明**
| 字段名 | 类型 | 说明 |
|--------|------|------|
| id | Long | 主键 ID |
| testResultId | Long | 测试结果 ID |
| name | String | 类/触发器名称 |
| type | String | 类型Class/Trigger |
| namespace | String | 命名空间 |
| numLocations | Integer | 总位置数 |
| numLocationsNotCovered | Integer | 未覆盖的位置数 |
| coveragePercent | Double | 覆盖率百分比 |
| createTime | Date | 创建时间 |
**成功响应示例**
```json
{
"code": 200,
"msg": "查询成功",
"data": {
"total": 30,
"rows": [
{
"id": 1,
"testResultId": 1,
"name": "MyClass",
"type": "Class",
"namespace": null,
"numLocations": 100,
"numLocationsNotCovered": 20,
"coveragePercent": 80.0,
"createTime": "2026-02-02T10:30:00"
}
]
}
}
```
---
## 错误码
### 系统错误码
| 错误码 | 说明 | 处理建议 |
|--------|------|----------|
| 200 | 操作成功 | 无需处理 |
| 401 | 未授权 | 检查 JWT Token 是否有效 |
| 403 | 无权限 | 检查用户是否有相应权限 |
| 404 | 资源不存在 | 检查请求路径是否正确 |
| 500 | 服务器内部错误 | 查看服务器日志,联系管理员 |
### 业务错误码
| 错误码 | 说明 | 处理建议 |
|--------|------|----------|
| 1001 | Salesforce 认证失败 | 检查 Salesforce 连接配置 |
| 1002 | Salesforce 会话过期 | 重新登录获取新会话 |
| 1003 | 编译失败 | 检查代码语法是否正确 |
| 1004 | 测试执行失败 | 检查测试代码是否正确 |
| 1005 | 执行匿名代码失败 | 检查代码语法和逻辑 |
| 1006 | 查询参数错误 | 检查请求参数是否符合要求 |
### 常见错误场景
#### 1. 认证失败
```json
{
"code": 401,
"msg": "认证失败:无效的令牌"
}
```
**原因**JWT Token 无效或已过期
**解决方案**:重新登录获取新的 JWT Token
#### 2. 无权限访问
```json
{
"code": 403,
"msg": "无权限访问:缺少 apex:compile:execute 权限"
}
```
**原因**:当前用户没有执行编译操作的权限
**解决方案**:联系管理员分配相应权限
#### 3. Salesforce 连接失败
```json
{
"code": 500,
"msg": "Salesforce 认证失败:连接超时"
}
```
**原因**:无法连接到 Salesforce 或认证信息无效
**解决方案**
- 检查 Salesforce 连接配置
- 检查网络连接
- 确认认证信息(用户名、密码、安全令牌)是否正确
#### 4. 编译错误
```json
{
"code": 500,
"msg": "编译失败",
"data": {
"success": false,
"problem": "Unexpected token 'public'",
"line": 2,
"column": 5
}
}
```
**原因**Apex 代码存在语法错误
**解决方案**:根据返回的错误信息(行号、列号、问题描述)修复代码
#### 5. 运行时异常
```json
{
"code": 500,
"msg": "执行失败",
"data": {
"success": false,
"exceptionMessage": "Divide by 0",
"exceptionStackTrace": "AnonymousBlock: line 1, column 1"
}
}
```
**原因**:执行的代码在运行时抛出异常
**解决方案**:根据异常消息和堆栈跟踪修复代码逻辑
## 相关文档
- [需求文档](../requirements/sub/2026-01-28-002-02-Apex代码编译和执行.md)
- [设计文档](../design/2026-02-02-002-02-Apex代码编译和执行-设计.md)
- [决策记录](../decisions/2026-02-02-002-02-ADR-Apex代码编译和执行技术选型.md)
- [变更日志](../changelog/2026-02-02-002-02-changelog.md)
- [复盘文档](../retros/2026-02-02-002-02-retro.md)