

# 连接到 Salesforce Marketing Cloud
<a name="connecting-to-data-salesforce-marketing-cloud"></a>

Salesforce Marketing Cloud 是一家营销自动化和分析软件供应商，其软件产品用于进行电子邮件、移动、社交及在线营销。该供应商还提供咨询和实施服务。Salesforce Marketing Cloud 用户可以将 AWS Glue 连接到 Salesforce Marketing Cloud 账户。然后可以使用 Salesforce Marketing Cloud 作为 ETL 作业中的数据来源或目的地。通过运行这些作业，可在 Salesforce Marketing Cloud 与 AWS 服务或其他受支持的应用程序之间传输数据。

**Topics**
+ [AWS Glue 对 Salesforce Marketing Cloud 的支持](salesforce-marketing-cloud-support.md)
+ [包含创建和使用连接的 API 操作的策略](salesforce-marketing-cloud-configuring-iam-permissions.md)
+ [配置 Salesforce Marketing Cloud](salesforce-marketing-cloud-configuring.md)
+ [配置 Salesforce Marketing Cloud 连接](salesforce-marketing-cloud-configuring-connections.md)
+ [从 Salesforce Marketing Cloud 实体中读取](salesforce-marketing-cloud-reading-from-entities.md)
+ [写入 Salesforce Marketing Cloud 实体](salesforce-marketing-cloud-writing-to-entities.md)
+ [Salesforce Marketing Cloud 连接选项](salesforce-marketing-cloud-connection-options.md)
+ [Salesforce Marketing Cloud 连接器的限制和说明](salesforce-marketing-cloud-connector-limitations.md)

# AWS Glue 对 Salesforce Marketing Cloud 的支持
<a name="salesforce-marketing-cloud-support"></a>

AWS Glue 对 Salesforce Marketing Cloud 的支持如下：

**是否支持作为来源？**  
是。您可以使用 AWS Glue ETL 作业查询 Salesforce Marketing Cloud 中的数据。

**是否支持作为目标？**  
否。

**支持的 Salesforce Marketing Cloud API 版本**  
支持以下 Salesforce Marketing Cloud API 版本：
+ v1

# 包含创建和使用连接的 API 操作的策略
<a name="salesforce-marketing-cloud-configuring-iam-permissions"></a>

以下示例策略描述了创建和使用连接所需的 AWS IAM 权限。如果您要创建新角色，请创建包含以下内容的策略：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "glue:ListConnectionTypes",
        "glue:DescribeConnectionType",
        "glue:RefreshOAuth2Tokens",
        "glue:ListEntities",
        "glue:DescribeEntity"
      ],
      "Resource": "*"
    }
  ]
}
```

------

如果您不想使用上述方法，也可以使用以下托管 IAM 策略：
+ [AWSGlueServiceRole](https://console.aws.amazon.com/iam/home#policies/arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole) – 授予对各种 AWS Glue 进程代表您运行所需的资源的访问权限。这些资源包括 AWS Glue、Amazon S3、IAM、CloudWatch Logs 和 Amazon EC2。如果您遵循此策略中指定的资源的命名约定，则 AWS Glue 进程具有所需的权限。此策略通常附加到在定义爬网程序、作业和开发终端节点时指定的角色。
+ [AWSGlueConsoleFullAccess](https://console.aws.amazon.com/iam/home#policies/arn:aws:iam::aws:policy/AWSGlueConsoleFullAccess)：当策略所附加到的身份使用 AWS 管理控制台时，授予对 AWS Glue 资源的完全访问权限。如果遵循此策略中指定的资源的命名约定，则用户具有完全控制台功能。此策略通常附加到 AWS Glue 控制台的用户。

# 配置 Salesforce Marketing Cloud
<a name="salesforce-marketing-cloud-configuring"></a>

您必须满足以下要求，才能使用 AWS Glue 从 Salesforce Marketing Cloud 传输数据：

## 最低要求
<a name="salesforce-marketing-cloud-configuring-min-requirements"></a>

以下是最低要求：
+ 您有一个 Salesforce Marketing Cloud 账户。有关更多信息，请参阅 [创建 Salesforce Marketing Cloud 账户](#salesforce-marketing-cloud-configuring-creating-salesforce-marketing-cloud-account)。
+ 您的 Salesforce Marketing Cloud 账户已启用 API 访问权限。默认情况下，Enterprise、Unlimited、Developer 和 Performance 版已启用 API 访问权限。

如果您满足这些要求，就可以将 AWS Glue 连接到您的 Salesforce Marketing Cloud 账户。对于典型连接，您无需在 Salesforce Marketing Cloud 中执行任何其他操作。

## 创建 Salesforce Marketing Cloud 账户
<a name="salesforce-marketing-cloud-configuring-creating-salesforce-marketing-cloud-account"></a>

对于 Salesforce Marketing Cloud，您需要联系供应商以创建账户。如果您或您的公司与 Salesforce 有关联，则请联系您的 Salesforce 客户经理申请 Salesforce Marketing Cloud 许可证。否则，您可以通过以下方式请求与 Salesforce 代表进行联系：

1. 访问 https://www.salesforce.com/in/products/marketing-cloud/overview/ 然后选择**注册**。

1. 选择页面右上角的**联系我们**链接。

1. 在表单中输入所需信息，然后选择**联系我**。

Salesforce 代表将与您联系，讨论您的要求。

## 创建项目和 OAuth 2.0 凭证
<a name="salesforce-marketing-cloud-configuring-creating-salesforce-marketing-cloud-project-oauth"></a>

要获取项目和 OAuth 2.0 凭证：

1. 使用您的用户名和密码登录 [Salesforce Marketing Cloud 实例](https://mc.login.exacttarget.com/hub-cas/login)，并使用您注册的手机号码进行身份验证。

1. 单击右上角的个人资料，然后进入**设置**。

1. 在**平台工具**下，选择**应用程序**，然后选择**已安装的软件包**。  
![\[\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/images/sfmc-platform-tools.png)

1. 在**已安装的软件包**页面上，单击右上角的**新建**。提供该软件包的名称和描述。

   保存该软件包。保存该软件包后，您可以查看软件包详细信息。

1. 在软件包**详细信息**页面的**组件**部分下，选择**添加组件**。  
![\[\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/images/sfmc-add-component.png)

1. 选择**组件类型**为“API 集成”，然后单击**下一步**。

1. 选择**集成类型**为“服务器到服务器”（具有客户端凭证 OAuth 授权类型），然后单击**下一步**。

1. 根据您的要求添加范围，然后单击**保存**。

# 配置 Salesforce Marketing Cloud 连接
<a name="salesforce-marketing-cloud-configuring-connections"></a>

Salesforce Marketing Cloud 支持 OAuth2 的客户端凭证授权类型。
+ 此授权类型被视为双足型 OAuth 2.0，因为客户端将其用于在用户环境之外获取访问令牌。AWS Glue 能够使用客户端 ID 和客户端密钥对由您定义的自定义服务提供的 Salesforce Marketing Cloud API 进行身份验证。
+ 每项自定义服务均归仅限 API 的用户所有，该用户拥有一组角色和权限，可授权该服务执行特定操作。访问令牌与单项自定义服务相关联。
+ 这种授权类型会生成一个短期有效的访问令牌，并且可以通过调用身份端点来续订。
+ 有关包含客户端凭证的 OAuth 2.0 的 Salesforce Marketing Cloud 公共文档，请参阅 [Set Up Your Development Environment for Enhanced Packages](https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/mc-dev-setup-enhanced.html)。

要配置 Salesforce Marketing Cloud 连接，请执行以下操作：

1. 在 AWS Secrets Manager 中，创建一个包含以下详细信息的密钥：

   1. 对于客户管理型关联应用程序，密钥应包含关联应用程序的消费者密钥，且以 `USER_MANAGED_CLIENT_APPLICATION_CLIENT_SECRET` 为键。

   1. 注意：必须在 AWS Glue 中为连接创建一个密钥。

1. 在 AWS Glue Glue Studio 中，按照以下步骤在**数据连接**下创建连接：

   1. 选择**连接类型**时，请选择 Salesforce Marketing Cloud。

   1. 提供想要连接到的 Salesforce Marketing Cloud 的 `Subdomain Endpoint`。

   1. 选择 AWS Glue 可以代入并有权执行以下操作的 AWS IAM 角色：

------
#### [ JSON ]

****  

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "secretsmanager:DescribeSecret",
              "secretsmanager:GetSecretValue",
              "secretsmanager:PutSecretValue",
              "ec2:CreateNetworkInterface",
              "ec2:DescribeNetworkInterfaces",
              "ec2:DeleteNetworkInterface"
            ],
            "Resource": "*"
          }
        ]
      }
      ```

------

   1. 在 AWS Glue 中选择您要用于此连接的 `secretName`，然后放置令牌。

   1. 如果要使用网络，请选择网络选项。

1. 向与您的 AWS Glue 作业关联的 IAM 角色授予读取 `secretName` 的权限。

# 从 Salesforce Marketing Cloud 实体中读取
<a name="salesforce-marketing-cloud-reading-from-entities"></a>

**先决条件**

您要从中读取内容的 Salesforce Marketing Cloud 对象。您将需要 `Activity` 或 `Campaigns` 等对象名称。下表显示支持的实体。

**源支持的实体**：


| 实体 | 接口 | 可以筛选 | 支持限制 | 支持排序依据 | 支持 SELECT \$1 | 支持分区 | 
| --- | --- | --- | --- | --- | --- | --- | 
| 事件通知回调 | REST | 否 | 否 | 否 | 是 | 否 | 
| 种子列表 | REST | 否 | 是 | 否 | 是 | 否 | 
| 设置 | REST | 支持 | 是 | 否 | 是 | 否 | 
| 域验证 | REST | 支持 | 是 | 是 | 是 | 否 | 
| 对象嵌套标签 | REST | 是 | 否 | 否 | 是 | 否 | 
| 联系人 | REST | 否 | 是 | 否 | 是 | 否 | 
| 事件通知订阅 | REST | 否 | 否 | 否 | 是 | 否 | 
| 消息收发 | REST | 否 | 是 | 否 | 是 | 否 | 
| 活动 | SOAP | 否 | 否 | 否 | 是 | 是 | 
| 退回事件 | SOAP | 否 | 否 | 否 | 是 | 是 | 
| 单击事件 | SOAP | 否 | 否 | 否 | 是 | 是 | 
| 内容区域 | SOAP | 否 | 否 | 否 | 是 | 是 | 
| 数据扩展 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 电子邮件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 转发的电子邮件事件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 转发电子邮件选择加入事件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 链接 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 链接发送 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 列表 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 列出订阅用户 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 未发送的事件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 公开事件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 发送 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 已发送事件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 订阅者 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 调查事件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 取消订阅事件 | SOAP | 否 | 是 | 否 | 是 | 是 | 
| 审计事件 | REST | 否 | 是 | 是 | 是 | 否 | 
| 市场活动 | REST | 否 | 是 | 是 | 是 | 否 | 
| 交互 | REST | 否 | 是 | 是 | 是 | 否 | 
| 内容素材 | REST | 否 | 是 | 是 | 是 | 否 | 

**REST 的示例**：

```
salesforcemarketingcloud_read = glueContext.create_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "Campaigns",
        "API_VERSION": "v1",
        "INSTANCE_URL": "https://**********************.rest.marketingcloudapis.com"
    }
)
```

**SOAP 的示例**：

```
salesforcemarketingcloud_read = glueContext.create_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "Activity",
        "API_VERSION": "v1",
        "INSTANCE_URL": "https://**********************.soap.marketingcloudapis.com"
    }
)
```

**Salesforce Marketing Cloud 实体和字段详细信息**：

下表描述 Salesforce Marketing Cloud 实体。REST 实体具有静态元数据，而 SOAP 实体具有动态元数据。

**具有静态元数据的 REST 实体**：

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/salesforce-marketing-cloud-reading-from-entities.html)

**具有动态元数据的 SOAP 实体**：

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/glue/latest/dg/salesforce-marketing-cloud-reading-from-entities.html)

## 对查询进行分区
<a name="salesforce-marketing-cloud-reading-partitioning-queries"></a>

在 Salesforce Marketing Cloud 中，整数和日期时间数据类型字段支持基于字段的分区。

如果您想在 Spark 中利用并发，可以提供其他 Spark 选项：`PARTITION_FIELD`、`LOWER_BOUND`、`UPPER_BOUND` 和 `NUM_PARTITIONS`。使用这些参数，原始查询将被拆分为 `NUM_PARTITIONS` 个子查询，这些子查询可以由 Spark 任务同时执行。
+ `PARTITION_FIELD`：用于对查询进行分区的字段的名称。
+ `LOWER_BOUND`：所选分区字段的**包含**下限值。

  对于时间戳字段，我们接受 Spark SQL 查询中使用的 Spark 时间戳格式。

  有效值示例：

  ```
  “2024-05-07T02:03:00.00Z"
  ```
+ `UPPER_BOUND`：所选分区字段的**排除**上限值。
+ `NUM_PARTITIONS`：分区的数量。

示例：

```
salesforcemarketingcloud_read = glueContext.create_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "ListSubscriber",
        "API_VERSION": "v1",
        "PARTITION_FIELD": "CreatedDate",
        "LOWER_BOUND": "2023-09-07T02:03:00.000Z",
        "UPPER_BOUND": "2024-05-07T02:03:00.000Z",
        "NUM_PARTITIONS": "10"
    }
)
```

# 写入 Salesforce Marketing Cloud 实体
<a name="salesforce-marketing-cloud-writing-to-entities"></a>

**先决条件**
+ 要写入数据的 Salesforce Marketing 对象。您需要指定对象的名称，例如 `List` 或 `Campaigns`，或下表中列出的任何其他实体。
+ Salesforce Marketing Cloud 连接器支持三种写入操作：
  + INSERT
  + UPSERT
  + UPDATE

  使用 `UPDATE` 和 `UPSERT` 写入操作时，必须提供 `ID_FIELD_NAMES` 选项来指定记录的外部 ID 字段。

**目的地支持的实体**：


| 实体 | 优先级 | 接口（REST、SOAP 等） | 是否可以插入 | 是否可以更新 | 是否可以更新插入 | 
| --- | --- | --- | --- | --- | --- | 
| 市场活动 | P0 | REST | 是，单条 | 是，单条 | N | 
| 内容素材 | P0 | REST | 是，单条、批量 | 是，单条 | N | 
| 联系人 | P1 | REST | 是，单条 | 是，单条 | N | 
| 域验证 | P1 | REST | 是，单条 | 是，单条、批量 | N | 
| 事件通知回调 | P1 | REST | 是，单条 | 是，单条 | N | 
| 事件通知订阅 | P1 | REST | 是，单条 | 是，单条 | N | 
| 消息收发 | P1 | REST | 是，单条 | N | N | 
| 对象嵌套标签 | P2 | REST | 是，单条 | 是，单条 | N | 
| 种子列表 | P1 | REST | 是，单条 | 是，单条 | N | 
| 设置 | P1 | REST | 是，单条 | 是，单条 | N | 
| 数据扩展 | P0 | SOAP | 是，单条 | 是，单条 | 是，单条 | 
| 电子邮件 | P0 | SOAP | 是，单条 | 是，单条 | N | 
| 列表 | P0 | SOAP | 是，单条 | 是，单条 | N | 
| 发送 | P0 | SOAP | 是，单条 | N | N | 
| 订阅者 | P0 | SOAP | 是，单条 | 是，单条 | N | 

**REST 的 INSERT 操作示例**：

```
salesforcemarketingcloud_write = glueContext.write_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "Campaigns",
        "API_VERSION": "v1",
        "writeOperation" : "INSERT",
        "INSTANCE_URL": "https://**********************.rest.marketingcloudapis.com"
    }
)
```

**SOAP 的 INSERT 操作示例**：

```
salesforcemarketingcloud_write = glueContext.write_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "List",
        "API_VERSION": "v1",
        "writeOperation" : "INSERT",
        "INSTANCE_URL": "https://**********************.rest.marketingcloudapis.com"
    }
)
```

**REST 的 UPDATE 操作示例**：

```
salesforcemarketingcloud_write = glueContext.write_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "Campaigns",
        "API_VERSION": "v1",
        "writeOperation" : "UPDATE",
         "ID_FIELD_NAMES": "id",
        "INSTANCE_URL": "https://**********************.rest.marketingcloudapis.com"
    }
)
```

**SOAP 的 UPDATE 操作示例**：

```
salesforcemarketingcloud_write = glueContext.write_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "List",
        "API_VERSION": "v1",
        "writeOperation" : "UPDATE",
         "ID_FIELD_NAMES": "id",
        "INSTANCE_URL": "https://**********************.rest.marketingcloudapis.com"
    }
)
```

**SOAP 的 UPSERT 操作示例**：

```
salesforcemarketingcloud_write = glueContext.write_dynamic_frame.from_options(
    connection_type="salesforcemarketingcloud",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "DataExtension/Insert-***E/6*******3",
        "API_VERSION": "v1",
        "writeOperation" : "UPSERT",
        "INSTANCE_URL": "https://**********************.rest.marketingcloudapis.com"
    }
)
```

# Salesforce Marketing Cloud 连接选项
<a name="salesforce-marketing-cloud-connection-options"></a>

以下是 Salesforce Marketing Cloud 的连接选项：
+ `ENTITY_NAME`（字符串）：（必填）用于读取。Salesforce Marketing Cloud 中对象的名称。
+ `API_VERSION`（字符串）：（必填）用于读取。要使用的 Salesforce Marketing Cloud Rest 和 SOAP API 版本。
+ `SELECTED_FIELDS`（列表<字符串>）–默认：empty(SELECT \$1)。用于读取。您想要为对象选择的列。
+ `FILTER_PREDICATE`（字符串）– 默认：空。用于读取。应采用 Spark SQL 格式。
+ `QUERY`（字符串）– 默认：空。用于读取。完整的 Spark SQL 查询。
+ `PARTITION_FIELD`（字符串）– 用于读取。用于分区查询的字段。
+ `LOWER_BOUND`（字符串）– 用于读取。所选分区字段的包含下限值。
+ `UPPER_BOUND`（字符串）– 用于读取。所选分区字段的排除上限值。
+ `NUM_PARTITIONS`（整数）– 默认：1。用于读取。要读取的分区数。
+ `WRITE_OPERATION`（字符串）– 默认：INSERT。用于写入。值应为 INSERT、UPDATE、UPSERT。
+ `ID_FIELD_NAMES`（字符串）– 默认：null。执行 UPDATE/UPSERT 操作需要。

# Salesforce Marketing Cloud 连接器的限制和说明
<a name="salesforce-marketing-cloud-connector-limitations"></a>

以下是 Salesforce Marketing Cloud 连接器的限制：
+ 在日期时间数据类型字段上使用筛选条件时，需要以“yyyy-mm-ddThh:MM:ssZ”格式传递值。
+ 在数据预览中，布尔数据类型值会显示为空白。
+ 对于 SOAP 实体，最多可以定义两个筛选条件；对于 REST 实体，只能定义一个筛选条件，这限制了使用筛选条件测试分区。
+ 在 SaaS 端观察到几种意想不到的行为：“linksend”实体中的 `Link.Alias` 字段不支持 CONTAINS 运算符（例如 `Link.Alias CONTAINS "ViewPrivacyPolicy"`），数据扩展实体（例如 EQUALS 和 GREATER THAN）的筛选运算符不返回预期结果。
+ SFMC ClickEvent SOAP API 在反映新创建的记录方面存在延迟，因此，最近创建的记录可能不会立即在 API 响应中可见。

  示例：如果在 **2025-01-10T14:30:00** 创建了 5 条新的 ClickEvent 记录，并立即使用 SOAP API 获取这些记录，则响应可能不会包含全部 5 条记录。新创建的记录最长可能需要 5 分钟的时间，才会显示在 API 响应中。这样的延迟也会影响数据检索和计划运行。
+ 在 AWS Glue 中执行写入操作时，支持两种不同的日期时间格式：**2025-03-11T04:46:00**（不带毫秒）和 **2025-03-11T04:46:00.000Z**（带毫秒）。
+ 对于事件通知订阅实体，只能为经过验证的回调 URL 创建订阅，且每个回调最多可以有 200 个订阅。
+ 对于事件通知回调实体，每个账户最多可以创建 50 条记录。