关于 sf-integration
sf-integration 是面向 Salesforce 集成配置与架构设计的技能,适用于配置集成基础设施的团队。内容涵盖凭据、认证流程、外部服务及事件机制,并区分配置工作与 Apex 调用代码。
主要功能
- 01配置 Named Credentials 与认证
- 02设置 Connected Apps 和 OAuth 流程
- 03注册 OpenAPI 外部服务
- 04设计 Platform Events 与 CDC
- 05评估集成架构和迁移路径
适用场景
- 01配置 Salesforce 对外 API 身份验证
- 02让 Flow 调用外部 API 操作
- 03订阅记录变更或平台事件
- 04将 Remote Site Settings 迁移到 Named Credentials
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ clientell-ai/ salesforce-skills --skill sf-integration安装后在 Claude Code 中输入/sf-integration确认已加载。
附带文件references/integration-reference.md
详细介绍
Salesforce 集成配置与架构
你是一名 Salesforce 集成架构师。配置集成基础设施——命名凭据、Connected Apps、External Services、Platform Events、CDC 和身份验证流程。重点关注元数据设置、安全配置和架构决策。
范围边界:此技能涵盖集成配置和元数据。有关 Apex callout 代码模式(HttpRequest、@RestResource、SOAP、mocks),请参阅 sf-apex 集成模式。
1. 命名凭据
命名凭据将端点 URL 和身份验证与代码分离。存在两种架构。
旧版命名凭据
单个元数据文件结合了端点和身份验证。仍受支持,但功能有限。
<?xml version="1.0" encoding="UTF-8"?>
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>MyService</fullName>
<label>My Service</label>
<endpoint>https://api.example.com</endpoint>
<principalType>NamedUser</principalType>
<protocol>Password</protocol>
<username>api_user</username>
</NamedCredential>
旧版 protocol 值:Password、Oauth、Jwt、JwtExchange、AwsSv4、NoAuthentication。
增强型命名凭据(首选)
将关注点拆分为两种元数据类型:
| 组件 | 用途 | 文件后缀 |
|---|---|---|
| External Credential | 身份验证配置(协议、主体、身份) | .externalCredential-meta.xml |
| Named Credential | 端点 URL,引用 External Credential | .namedCredential-meta.xml |
引用 External Credential 的增强型命名凭据:
<?xml version="1.0" encoding="UTF-8"?>
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>MyService</fullName>
<label>My Service</label>
<endpoint>https://api.example.com</endpoint>
<externalCredential>MyService_Auth</externalCredential>
<generateAuthorizationHeader>true</generateAuthorizationHeader>
<allowMergeFieldsInBody>false</allowMergeFieldsInBody>
<allowMergeFieldsInHeader>true</allowMergeFieldsInHeader>
</NamedCredential>
使用 OAuth Client Credentials 的 External Credential:
<?xml version="1.0" encoding="UTF-8"?>
<ExternalCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>MyService_Auth</fullName>
<label>My Service Auth</label>
<authenticationProtocol>Oauth</authenticationProtocol>
<externalCredentialParameters>
<parameterName>ClientId</parameterName>
<parameterType>AuthProviderUrl</parameterType>
<parameterValue>YOUR_CLIENT_ID</parameterValue>
</externalCredentialParameters>
<externalCredentialParameters>
<parameterName>Scope</parameterName>
<parameterType>AuthParameter</parameterType>
<parameterValue>api read</parameterValue>
</externalCredentialParameters>
<principals>
<principalName>MyServicePrincipal</principalName>
<principalType>NamedPrincipal</principalType>
<sequenceNumber>1</sequenceNumber>
</principals>
</ExternalCredential>
External Credentials 的权限集映射
用户通过权限集映射访问 External Credentials。若未配置此项,callout 将失败并显示 NAMED_CREDENTIAL_NOT_FOUND。
<externalCredentialPrincipalAccesses>
<enabled>true</enabled>
<externalCredentialPrincipal>MyService_Auth - MyServicePrincipal</externalCredentialPrincipal>
</externalCredentialPrincipalAccesses>
如何选择
| 场景 | 建议 |
|---|---|
| 新建集成 | 增强型命名凭据 + External Credential |
| 简单的单用户身份验证 | 旧版命名凭据(可以接受) |
| 多个端点使用相同身份验证 | 一个 External Credential,多个命名凭据 |
| 每用户 OAuth 令牌 | 使用 Per-User 主体的 External Credential |
| 从 Remote Site Settings 迁移 | 改用命名凭据管理身份验证 |
2. Connected Apps
Connected Apps 为访问 Salesforce 的外部应用,或 Salesforce 到 Salesforce 的身份验证,定义 OAuth 客户端配置。
Connected App 元数据
<?xml version="1.0" encoding="UTF-8"?>
<ConnectedApp xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>MyConnectedApp</fullName>
<label>My Connected App</label>
<contactEmail>[email protected]</contactEmail>
<oauthConfig>
<callbackUrl>https://myapp.example.com/callback</callbackUrl>
<certificate>MyCertificateName</certificate>
<consumerKey>WILL_BE_GENERATED</consumerKey>
<isAdminApproved>true</isAdminApproved>
<isConsumerSecretOptional>false</isConsumerSecretOptional>
<scopes>Api</scopes>
<scopes>RefreshToken</scopes>
<scopes>OfflineAccess</scopes>
</oauthConfig>
<oauthPolicy>
<ipRelaxation>ENFORCE</ipRelaxation>
<refreshTokenPolicy>SPECIFIC_LIFETIME</refreshTokenPolicy>
<refreshTokenValidityPeriod>720</refreshTokenValidityPeriod>
<refreshTokenValidityUnits>HOURS</refreshTokenValidityUnits>
</oauthPolicy>
</ConnectedApp>
OAuth 范围参考
| 范围值 | 含义 |
|---|---|
Api | 访问 REST/SOAP API |
Web | 通过浏览器访问(Web 范围) |
Full | 完全访问权限(生产环境中避免使用) |
RefreshToken | 启用刷新令牌(offline_access) |
OfflineAccess | 与 RefreshToken 相同 |
Chatter | Chatter REST API |
CustomPermissions | 访问自定义权限 |
OpenID | OpenID Connect 身份 |
Profile | 用户个人资料信息 |
Email | 用户电子邮件 |
JWT Bearer 流程设置
适用于无需交互式登录的服务器到服务器场景:
- 生成 X.509 证书并上传到 Connected App
- 为集成用户的个人资料预授权 Connected App
- 将
isAdminApproved设置为true - 客户端使用私钥签名 JWT,并将其发送到令牌端点
- 令牌端点:
https://login.salesforce.com/services/oauth2/token
授权类型:urn:ietf:params:oauth:grant-type:jwt-bearer
Web Server 流程设置
适用于面向用户的应用:
- 配置回调 URL(必须使用 HTTPS,且必须完全匹配)
- 设置适当的范围(避免使用
Full) - 根据安全要求设置 IP 放宽策略
- 配置刷新令牌有效期
IP 放宽选项
| 值 | 行为 |
|---|---|
ENFORCE | 强制执行 Connected App 的 IP 限制 |
BYPASS | 绕过组织的 IP 限制 |
BYPASS_WITH_VALID_BROWSER_SESSION | 仅在存在活动浏览器会话时绕过 |
3. External Services
External Services 可让你注册 OpenAPI 规范,并自动生成可在 Flow、Einstein Bots 和 Apex 中使用的可调用操作。
注册步骤
- 为外部 API 端点创建一个命名凭据
- 导航至 Setup > External Services
- 提供 OpenAPI(Swagger)规范——URL 或粘贴 JSON/YAML
- Salesforce 解析操作并生成可调用操作
要求和限制
- 仅支持 OpenAPI 3.0(新注册不支持 2.0/Swagger)
- 规范大小上限:100 KB
- 每次注册最多 50 个操作
- 所有操作均使用命名凭据进行身份验证
- 生成的操作会显示为 Flow 外部服务操作
- 支持的 HTTP 方法:GET、POST、PUT、PATCH、DELETE
在 Flow 中使用外部服务
注册后,每个操作都会成为可调用操作:
- 在 Flow Builder 中添加一个 Action 元素
- 按类别“外部服务”筛选
- 选择操作(例如,
createOrder、getCustomer) - 将 Flow 变量映射到输入/输出参数
- 命名凭据会自动处理身份验证
外部服务元数据
<?xml version="1.0" encoding="UTF-8"?>
<ExternalServiceRegistration xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>MyExternalService</fullName>
<label>My External Service</label>
<namedCredential>MyService</namedCredential>
<schema>--- OpenAPI JSON spec inlined or referenced ---</schema>
<schemaType>OpenApi3</schemaType>
<serviceBinding>
<fieldName>operationName</fieldName>
<value>createOrder</value>
</serviceBinding>
<status>Complete</status>
</ExternalServiceRegistration>
4. 平台事件
用于在 Salesforce 内部以及与外部系统之间进行解耦、事件驱动集成的自定义事件总线。
事件定义
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Order_Event__e</fullName>
<label>Order Event</label>
<pluralLabel>Order Events</pluralLabel>
<publishBehavior>PublishAfterCommit</publishBehavior>
<fields>
<fullName>Order_Id__c</fullName>
<label>Order Id</label>
<type>Text</type>
<length>18</length>
</fields>
<fields>
<fullName>Action__c</fullName>
<label>Action</label>
<type>Text</type>
<length>50</length>
</fields>
<fields>
<fullName>Payload__c</fullName>
<label>Payload</label>
<type>LongTextArea</type>
<length>131072</length>
<visibleLines>5</visibleLines>
</fields>
</CustomObject>
发布行为
| 行为 | 事件发布时机 | 适用场景 |
|---|---|---|
PublishAfterCommit | 事务成功提交后 | 默认行为。事件应反映已提交的数据 |
PublishImmediately | 立即发布,即使事务回滚 | 日志记录、审计、即发即弃通知 |
关键规则:如果事务回滚,PublishAfterCommit 事件不会触发。PublishImmediately 事件无论如何都会触发——请谨慎使用。
订阅者模式
- Apex 触发器:
trigger OrderEventTrigger on Order_Event__e (after insert)——在其自身的执行上下文中运行 - Flow:使用平台事件触发的 Flow(记录触发的 Flow 无法订阅)
- 外部系统:外部系统订阅者使用 CometD 或 Pub/Sub API(gRPC)
重放和保留
- 标准平台事件:保留 24 小时,可通过 Replay ID 重放
- 高容量平台事件:保留 72 小时,吞吐量更高(150K/小时)
- 在 CometD 或 Pub/Sub API 中使用
ReplayId,以便在订阅者故障后从特定位置恢复 - 订阅者可以设置重放位置:
-1(最新位置)、-2(所有保留的事件)或特定的 Replay ID
5. 变更数据捕获(CDC)
将记录变更(创建、更新、删除、取消删除)作为事件流式传输到事件总线。
启用 CDC
- Setup > Change Data Capture
- 选择要跟踪的对象(标准对象或自定义对象)
- 变更会发布到频道:
/data/<ObjectName>ChangeEvent(例如,/data/AccountChangeEvent)
对于自定义对象:/data/<CustomObject__c>ChangeEvent 会变为 /data/Custom_Object__ChangeEvent
ChangeEventHeader 字段
每个 CDC 事件都包含一个带有变更元数据的标头:
| 字段 | 说明 |
|---|---|
entityName | SObject API 名称 |
changeType | CREATE、UPDATE、DELETE、UNDELETE |
changedFields | 发生变更的字段列表(仅限 UPDATE) |
commitTimestamp | 变更提交的时间 |
transactionKey | 对来自同一事务的变更进行分组 |
sequenceNumber | 事务内的顺序 |
recordIds | 发生变更的记录 ID |
commitUser | 执行变更的用户 |
commitNumber | 单调递增的提交序列 |
CDC 订阅者触发器
trigger AccountChangeEventTrigger on AccountChangeEvent (after insert) {
for (AccountChangeEvent event : Trigger.new) {
EventBus.ChangeEventHeader header = event.ChangeEventHeader;
String changeType = header.getChangeType();
List<String> changedFields = header.getChangedFields();
if (changeType == 'UPDATE' && changedFields.contains('Rating')) {
// React to Rating field changes
for (String recordId : header.getRecordIds()) {
// Queue processing for each changed record
}
}
}
}
CDC 与平台事件对比
| 方面 | CDC | 平台事件 |
|---|---|---|
| 触发方式 | 记录 DML 时自动触发 | 通过代码/Flow 显式发布 |
| 架构 | 与 SObject 字段一致 | 自定义定义的字段 |
| 使用场景 | 响应数据变更 | 解耦业务流程 |
| 保留时间 | 72 小时 | 24 小时(标准)/72 小时(高容量) |
| 外部订阅 | Pub/Sub API、CometD | Pub/Sub API、CometD |
6. 出站消息(旧版)
由工作流规则触发的基于 SOAP 的出站通知。此模式已过时——新工作建议优先使用平台事件。
- 仅由工作流规则触发(不支持 Process Builder 或 Flow)
- SOAP 格式,自动以指数退避方式重试 24 小时
- 端点必须返回 Ack ID;系统会持续重试,直到收到确认或超时 24 小时
- 每条消息最多包含 100 个字段
- 迁移到:平台事件(解耦的发布/订阅)、Flow + HTTP Callout(声明式)或 Apex Callout(适用于复杂的请求/响应)
7. 远程站点设置与命名凭据
迁移路径
远程站点设置仅将端点 URL 加入允许列表。命名凭据还增加了身份验证管理功能。
| 功能 | 远程站点设置 | 命名凭据 |
|---|---|---|
| URL 允许列表 | 是 | 是(隐式) |
| 身份验证管理 | 否(需在代码中手动处理) | 是(自动) |
| 凭据存储 | 由开发者负责 | 由平台管理 |
| 按环境配置 | 手动 | 内置 |
| 合并字段 | 否 | 是(标头、正文、URL) |
| 可部署 | 是 | 是 |
迁移步骤:
- 创建命名凭据,将远程站点 URL 设为端点
- 配置身份验证协议(OAuth、Password、JWT 等)
- 更新 Apex 代码:将硬编码的端点替换为
callout:NamedCredentialName - 从代码中移除身份验证标头的构造逻辑
- 删除远程站点设置
- 在生产环境部署前,先在沙盒中测试
8. 身份验证流程决策指南
| 流程 | 使用场景 | 客户端类型 | 用户交互 |
|---|---|---|---|
| JWT Bearer | 服务器到服务器、CI/CD、后端自动化 | 机密客户端 | 无(预先授权) |
| Web Server (Auth Code) | 带用户登录的 Web 应用 | 机密客户端 | 浏览器重定向 |
| Auth Code + PKCE | SPA、移动应用、公共客户端 | 公共客户端 | 浏览器重定向 |
| Client Credentials | M2M、服务帐户(无用户上下文) | 机密客户端 | 无 |
| Device Flow | CLI 工具、无头设备、IoT | 公共或机密客户端 | 带外用户身份验证 |
| Refresh Token | 无需重新验证即可维持会话 | 任一 | 无(静默) |
决策规则
- 不需要用户上下文? 使用 Client Credentials(如果可用)或 JWT Bearer
- 后端服务? 使用基于 X.509 证书的 JWT Bearer
- 面向用户的 Web 应用? 使用 Web Server 流程
- 公共客户端(SPA/移动端)? 使用 Auth Code + PKCE(强制要求)
- 没有浏览器? 使用 Device Flow
- 需要长期访问? 添加
RefreshToken/OfflineAccess范围
9. 注意事项
命名凭据
- 每个同步事务最多 100 次 Callout(与所有 HTTP 请求共用限额)
- 增强型命名凭据需要映射权限集,否则 Callout 会静默失败
- 外部凭据参数名称区分大小写
- 要自动注入 OAuth 标头,
generateAuthorizationHeader必须为true
平台事件
- 高容量发布限额为每小时 150,000 个事件;标准容量为 50,000 个
- 如果事务回滚,
PublishAfterCommit事件会丢失,且不会重试 - 至少投递一次:订阅者必须具备幂等性
- 订阅者触发器失败会导致自动重试(最多重试 8 次,并采用退避机制)
EventBus.publish()不会抛出异常——请检查SaveResult中的错误
更改数据捕获
- 72 小时重放窗口——超过 72 小时的事件会丢失
- 默认情况下,批量 API 操作不会触发 CDC 事件(必须启用)
- 大型事务的更改可能会拆分为多个事件(请检查
sequenceNumber) - 并非所有标准对象都可用——请查阅 Salesforce 文档
外部服务
- 仅支持 OpenAPI 3.0——必须转换 Swagger 2.0 规范
- 规范大小上限为 100 KB
- 每次注册最多支持 50 个操作
- 复杂的嵌套架构可能无法正确解析——请尽可能扁平化
Connected Apps
- 创建时生成的 Consumer key/secret——无法通过元数据设置
- JWT Bearer 和 Client Credentials 流程需要 管理员批准
- 证书过期会导致静默身份验证失败——请监控并轮换证书
- IP 放宽策略适用于 Connected App,而非用户的 IP 限制
- Connected App 的更改最多需要 10 分钟才能生效
通用
- 同一事务中无法同时执行同步 callout 和 DML,除非谨慎安排顺序(先执行 callout,再执行 DML,或使用
@future/Queueable) - Callout 超时时间上限:每个请求 120 秒,每个事务总计 120 秒
工作流
- 使用上述决策指南确定集成模式
- 使用 Glob 和 Grep 查找项目中现有的集成元数据
- 生成或更新 Named Credential / External Credential / Connected App 元数据
- 如果采用事件驱动方式,配置 Platform Events 或 CDC
- 如果由规范驱动,设置 External Services
- 验证 External Credentials 的 Permission Set 映射
- 建议部署:
sf project deploy start -d force-app/main/default/namedCredentials/
参考资料
- 集成参考——元数据 XML 模板、身份验证流程详情、架构决策指南
- Apex 集成模式——callout 代码、@RestResource、SOAP、模拟对象(单独的 skill)
- Governor Limits——每个事务的限制