Salesforce Composite API:实现高效集成的综合指南

作者:Salesforce 集成工程师


背景与应用场景

作为一名 Salesforce 集成工程师 (Salesforce Integration Engineer),我的日常工作核心是构建稳定、高效且可靠的数据管道,将 Salesforce 与企业生态系统中的其他应用程序(如 ERP、营销自动化平台、客户支持系统等)连接起来。在这些集成场景中,我们经常面临需要在一个业务流程中执行多个关联操作的挑战。例如,当一个新客户在外部系统中注册时,我们可能需要在 Salesforce 中依次执行以下操作:

  1. 创建一个新的客户 (Account) 记录。
  2. 基于新创建的客户,为其创建一个主要的联系人 (Contact) 记录。
  3. 最后,为这个新客户创建一个初始的业务机会 (Opportunity)

在传统的集成模式下,要完成这个流程,客户端应用程序需要向 Salesforce 发送三个独立的 REST API (表述性状态传递应用程序编程接口) 请求。这种方法存在几个明显的缺点:

  • 高网络延迟 (Network Latency):每一次 API 调用都包含一次完整的网络往返。三次调用意味着三次往返,这会显著增加整个业务流程的总耗时,尤其是在网络不稳定的情况下。
  • 事务性缺失 (Lack of Transactionality):这三个操作在逻辑上是一个原子单元,即它们应该“要么全部成功,要么全部失败”。如果创建客户和联系人成功,但创建业务机会失败了,系统就会遗留下不完整的“孤儿”数据,破坏了数据一致性。后续需要复杂的补偿逻辑来清理这些数据,增加了集成的复杂性和脆弱性。
  • API 调用次数消耗:Salesforce 对每个组织在 24 小时内的 API 调用总数有严格的限制,即 Governor Limits (管控限制)。多次独立的调用会更快地消耗这些宝贵的 API 限额。

为了解决这些痛点,Salesforce Platform 提供了强大的 Composite API。它允许我们将一系列独立的 API 请求捆绑到一个单一的 HTTP 请求中进行调用。这不仅极大地减少了网络往返次数,还提供了一种原生的事务控制机制,从而完美地解决了上述挑战。对于我们集成工程师而言,Composite API 是优化性能、保证数据完整性和简化集成逻辑的利器。

原理说明

Salesforce Composite API 的核心原理非常直观:它将多个子请求 (subrequests) 聚合到一个 JSON 格式的请求体 (payload) 中,通过一次 HTTP POST 请求发送到 Salesforce 的特定端点 (endpoint)/services/data/vXX.X/composite

Salesforce 服务器在收到这个聚合请求后,会按顺序解析并执行其中的每一个子请求。执行完毕后,它会返回一个同样聚合的 JSON 响应,其中包含了每个子请求的执行结果。

关键特性与工作机制

1. 请求结构 (Request Structure):

一个典型的 Composite API 请求体是一个 JSON 对象,它包含一个名为 compositeRequest 的数组。这个数组中的每一个元素都是一个独立的子请求对象,其结构与标准的 Salesforce REST API 请求非常相似,通常包含以下属性:

  • method: HTTP 方法,如 "POST", "PATCH", "GET", "DELETE"。
  • url: 子请求的目标 URL,例如 /services/data/v58.0/sobjects/Account
  • referenceId: 一个在当前 Composite 请求中唯一的标识符。这是 Composite API 最强大的功能之一,它允许后续的子请求引用当前请求中前面子请求的执行结果(比如新创建记录的 ID)。
  • body: 对于 POST 或 PATCH 请求,这是包含要创建或更新的数据的 JSON 对象。

2. 事务控制 (Transactional Control):

请求体的顶层有一个布尔类型的属性 allOrNone。这个属性控制着整个 Composite 请求的事务行为。

  • allOrNone 设置为 true 时,整个 Composite 请求将作为一个原子事务执行。如果其中任何一个子请求失败,Salesforce 会自动回滚 (rollback) 在此之前所有已成功执行的子请求所做的更改。这确保了“要么全部成功,要么全部失败”的数据一致性,是处理相互依赖操作的理想选择。
  • allOrNone 设置为 false(默认值)时,各个子请求将独立执行。即使某个子请求失败,也不会影响其他子请求的提交。成功的操作会被保留,失败的操作会返回错误信息。这种模式适用于执行一系列互不相关的操作。

3. 引用 ID (Reference ID):

这是实现操作链的关键。当一个子请求(例如,创建一个 Account)成功执行后,其结果(包括新记录的 ID)可以在后续的子请求中被引用。这是通过 referenceId 实现的。例如,第一个子请求可以定义一个 referenceId 为 "NewAccount"。在第二个子请求(例如,创建一个 Contact)中,我们可以通过特殊的语法 @{NewAccount.id} 来引用第一个请求创建的 Account 的 ID,并将其赋值给 Contact 的 AccountId 字段。这种动态引用能力使得构建复杂的、有依赖关系的数据结构变得异常简单。

4. 响应结构 (Response Structure):

Composite API 的响应结构与请求结构相对应。它返回一个 JSON 对象,其中包含一个名为 compositeResponse 的数组。这个数组中的每个元素都是一个子响应对象,按照原始子请求的顺序排列。每个子响应都包含了该子请求的执行结果,包括:

  • body: 响应体,例如新创建记录的 ID 和其他信息,或错误详情。
  • httpHeaders: 响应的 HTTP 头。
  • httpStatusCode: 该子请求的 HTTP 状态码(例如,201 表示创建成功,400 表示错误请求)。
  • referenceId: 与之对应的子请求的 referenceId,方便客户端进行匹配处理。

通过检查每个子响应的 httpStatusCode,我们可以精确地了解整个复合操作中每一步的成败情况。


示例代码(含详细注释)

下面的示例代码演示了一个经典的 Composite API 应用场景:在一个请求中,先创建一个新的客户 (Account) 记录,然后立即使用这个新客户的 ID 创建一个关联的联系人 (Contact) 记录。此示例直接源自 Salesforce 官方文档,确保了其准确性和权威性。

场景: 为 "Express Logistics and Transport" 公司创建一个客户记录,并为其创建一位名为 "Carol Ruiz" 的首席执行官 (CEO) 联系人。

HTTP 请求

Endpoint: POST /services/data/v58.0/composite

Request Body:

{
  "allOrNone" : true,
  "compositeRequest" : [{
    "method" : "POST",
    "url" : "/services/data/v58.0/sobjects/Account",
    "referenceId" : "refAccount",
    "body" : { "Name" : "Express Logistics and Transport" }
  },{
    "method" : "POST",
    "url" : "/services/data/v58.0/sobjects/Contact",
    "referenceId" : "refContact",
    "body" : {
      "LastName" : "Ruiz",
      "FirstName" : "Carol",
      "Title" : "CEO",
      "AccountId" : "@{refAccount.id}"
    }
  }]
}

代码注释

  • 第 2 行 "allOrNone" : true: 这是一个关键设置。它指示 Salesforce 将这两个操作视为一个原子事务。如果创建 Account 成功但创建 Contact 失败,那么已经创建的 Account 记录将被自动回滚,数据库中不会留下任何痕迹。这保证了数据的清洁和一致性。
  • 第 3-9 行 (第一个子请求):
    • "method" : "POST""url" : "..." 定义了这是一个创建新记录的请求,目标是 Account sObject (Salesforce 对象)
    • "referenceId" : "refAccount" 为这个子请求分配了一个唯一的引用 ID,"refAccount"。这个 ID 将在后续的子请求中用于引用此操作的结果。
    • "body" : { "Name" : "..." } 提供了创建 Account 所需的字段数据。
  • 第 10-18 行 (第二个子请求):
    • 这部分定义了创建 Contact 的请求。
    • 最关键的一行是 第 17 行 "AccountId" : "@{refAccount.id}"。这里的 @{refAccount.id} 是一个特殊的占位符语法。它告诉 Salesforce:“请获取 referenceIdrefAccount 的那个子请求的结果,并从中提取 id 字段的值,然后将这个值赋给当前 Contact 记录的 AccountId 字段。” 这就动态地将新的 Contact 与刚刚创建的 Account 关联起来,而无需客户端预先知道 Account 的 ID。

HTTP 响应 (成功时)

{
  "compositeResponse" : [{
    "body" : {
      "id" : "001xx000003DHPxAAO",
      "success" : true,
      "errors" : [ ]
    },
    "httpHeaders" : {
      "Location" : "/services/data/v58.0/sobjects/Account/001xx000003DHPxAAO"
    },
    "httpStatusCode" : 201,
    "referenceId" : "refAccount"
  },{
    "body" : {
      "id" : "003xx000004Wpr8AAC",
      "success" : true,
      "errors" : [ ]
    },
    "httpHeaders" : {
      "Location" : "/services/data/v58.0/sobjects/Contact/003xx000004Wpr8AAC"
    },
    "httpStatusCode" : 201,
    "referenceId" : "refContact"
  }]
}

响应注释

响应体中的 compositeResponse 数组包含了两个子响应,顺序与请求中的子请求一致。每个子响应都包含:

  • body: 包含了操作结果,如新记录的 ID ("id")。
  • httpStatusCode: 201 表示 "Created",说明资源创建成功。
  • referenceId: 对应请求中的 referenceId,便于客户端代码将请求和响应一一对应。

注意事项

在使用 Composite API 时,集成工程师必须考虑以下几个关键点,以确保集成的健壮性和可扩展性。

1. Governor Limits (管控限制):

Salesforce 平台对资源的使用有严格的限制。对于 Composite API,最主要的限制是单个请求中子请求的数量。一个 Composite API 请求中最多只能包含 25 个子请求。如果超出这个数量,整个请求将会失败。因此,在设计集成流程时,如果需要处理超过 25 个关联操作,应将其分拆成多个 Composite 请求。

2. DML 操作限制:

整个 Composite 请求被视为一个单一的事务。因此,它内部所有子请求执行的 DML (Data Manipulation Language) 操作(如 insert, update, delete)总数会共同计入该事务的 DML 限制(例如,一个事务中最多执行 10,000 条记录的 DML 操作)。如果复合操作过于庞大,可能会触及这些更深层次的 Governor Limits。

3. 权限与可见性 (Permissions and Visibility):

执行 Composite API 请求的用户必须拥有对所有子请求中涉及的对象和字段的相应权限(创建、读取、更新、删除)。字段级别的安全性 (Field-Level Security) 和记录共享规则 (Sharing Rules) 同样会生效。如果用户缺少对某个对象或字段的访问权限,对应的子请求将会失败。

4. 错误处理 (Error Handling):

健壮的错误处理至关重要。客户端代码必须迭代检查 compositeResponse 数组中的每一个子响应。判断成功的标准是检查每个子响应的 httpStatusCode 是否在 200-299 的范围内。对于失败的子请求(状态码在 400 或 500 范围),其 body 中会包含一个详细的错误信息数组,通常包含错误码 (errorCode) 和错误消息 (message),必须对这些信息进行解析和记录,以便于调试和问题排查。

5. API 版本兼容性:

请求 URL 和子请求 URL 中的 API 版本 (如 v58.0) 应该保持一致。使用不同版本可能会导致不可预期的行为或错误。始终建议使用当前组织支持的最新、稳定的 API 版本。


总结与最佳实践

Salesforce Composite API 是集成工具箱中一件非常强大的工具,它通过将多个请求捆绑为单一调用,显著提升了集成效率和数据一致性。

总结

  • 性能提升: 大幅减少了客户端与服务器之间的网络往返次数,降低了延迟,特别适合于需要执行一系列连续操作的场景。
  • 事务保障: 通过 allOrNone 参数提供了原生的原子事务控制,简化了数据一致性的管理,避免了手动实现复杂的回滚逻辑。
  • 简化逻辑: 使用 referenceId 可以在一个请求内部轻松处理记录之间的依赖关系,使集成代码更简洁、更易于维护。
  • API 限额友好: 将多个操作合并为一次 API 调用,有助于节省宝贵的 API 调用限额。

最佳实践

  1. 优先用于原子业务流程: 当你需要执行一个逻辑上不可分割的业务流程时(如创建订单及其订单项),Composite API 是首选。
  2. 始终设置 `allOrNone=true` 用于关联操作: 对于相互依赖的数据操作,强烈建议将 allOrNone 设置为 true,以确保数据的完整性。
  3. 设计详尽的错误处理逻辑: 不要假设整个 Composite 请求会整体成功或失败。务必编写代码来遍历所有子响应,检查它们各自的状态码,并对失败的子请求进行适当的记录、告警或重试。
  4. 注意请求大小和限制: 监控并控制每个 Composite 请求中子请求的数量,确保不超过 25 个。对于大规模、非事务性的数据批量操作,应考虑使用 Composite Batch APIBulk API 2.0,它们更适合处理成千上万条记录的场景。
  5. 充分利用 `referenceId`: 在设计请求时,积极利用 `referenceId` 来构建数据依赖链,避免在客户端进行不必要的中间数据处理。

作为 Salesforce 集成工程师,深刻理解并熟练运用 Composite API,将使我们能够构建出更高效、更可靠、更具扩展性的集成解决方案,从而为企业创造更大的业务价值。

评论

此博客中的热门博文

Salesforce 登录取证:深入解析用户访问监控与安全

Salesforce Experience Cloud 技术深度解析:构建社区站点 (Community Sites)

Salesforce Data Loader 全方位指南:数据迁移与管理的最佳实践