

# 连接到 HubSpot
<a name="connecting-to-data-hubspot"></a>

HubSpot 的 CRM 平台提供了营销、销售、内容管理和客户服务所需的各种工具和集成。
+ Marketing Hub：一种营销软件，可帮助您增加流量，转化更多访客，并大规模进行全面的集客营销活动。
+ Sales Hub：一种销售 CRM 软件，可帮助您更深入地了解潜在客户，自动完成各种任务，更快地促成更多交易。
+ Service Hub：一种客户服务软件，可帮助您与客户沟通互动，超越客户预期，并将客户变为您业务增长的推动者。
+ Operations Hub：一种运营软件，可同步您的各种应用程序，清理和创建客户数据，自动化执行相关流程，从而让您的各种系统和团队能够更好地协同工作。

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

# AWS Glue 支持 HubSpot
<a name="hubspot-support"></a>

AWS Glue 对 HubSpot 的支持如下：

**是否支持作为来源？**  
是，支持同步和异步。可以使用 AWS Glue ETL 作业查询 HubSpot 中的数据。

**是否支持作为目标？**  
是。您可以使用 AWS Glue ETL 作业将数据写入 HubSpot。

**支持的 HubSpot API 版本**  
支持以下 HubSpot API 版本：
+ v1
+ v2
+ v3
+ v4

有关每个版本的相应实体支持，请参阅[同步源支持的实体](hubspot-reading-from-entities.md#sync-table)与[异步源支持的实体](hubspot-reading-from-entities.md#async-table)。

# 包含创建和使用连接的 API 操作的策略
<a name="hubspot-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 控制台的用户。

# 配置 HubSpot
<a name="hubspot-configuring"></a>

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

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

以下是最低要求：
+ 有 HubSpot 账户。有关更多信息，请参阅 [创建 HubSpot 账户](#hubspot-configuring-creating-hubspot-account)。
+ HubSpot 账户已启用 API 访问权限。
+ 在 HubSpot 开发者账户下有应用程序，提供 AWS Glue 在对账户进行经身份验证的调用时用于安全访问数据的客户端凭证。有关更多信息，请参阅 [创建 HubSpot 开发者应用程序](#hubspot-configuring-creating-hubspot-developer-app)。

如果满足这些要求，就可以将 AWS Glue 连接到 HubSpot 账户。对于常见连接，无需在 HubSpot 中执行其他操作。

## 创建 HubSpot 账户
<a name="hubspot-configuring-creating-hubspot-account"></a>

要创建 HubSpot 账户：

1. 前往 [HubSpot CRM 注册网址](https://app.hubspot.com/login)。

1. 输入电子邮件地址，选择**验证电子邮件**（也可以选择使用 Google、Microsoft 或 Apple 账户登录）。

1. 在收件箱中查看来自 HubSpot 的验证码。

1. 输入 6 位数的验证码，点击**下一步**。

1. 输入密码，点击**下一步**。

1. 输入名字和姓氏，点击**下一步**；或者通过**使用 Google 登录**链接登录。

1. 输入行业，点击**下一步**。

1. 输入职位，点击**下一步**。

1. 输入公司名称，点击**下一步**。

1. 选择公司规模（员工人数），点击**下一步**。

1. 进入公司网站，点击**下一步**。

1. 选择数据托管地点（美国或欧洲），点击**创建账户**。

1. 选择创建账户的目的，点击**下一步**。

1. 选择**关联 Google 账户**或选择自行添加联系人，将联系人与 HubSpot 账户关联起来。

1. 如果选择**关联 Google 账户**选项来关联联系人并开始使用 HubSpot 账户，则请登录 Google 账户。

## 创建 HubSpot 开发者应用程序
<a name="hubspot-configuring-creating-hubspot-developer-app"></a>

应用程序开发者账户用于创建和管理应用程序、集成及开发者测试账户。您也可以在其中创建和管理 App Marketplace 上架信息。不过，应用程序开发者账户及其关联的测试账户并未关联到标准的 HubSpot 账户。这些账户无法与另一个 HubSpot 账户同步彼此的数据或资产。要获取客户端 ID 和客户端密钥，必须创建一个开发者账户。

1. 前往 https://developers.hubspot.com/

1. 选择**创建开发者账户**，再向下滚动。

1. 系统会询问是要创建应用程序开发者账户、私人应用程序账户还是 CMS 开发者沙盒账户。选择**创建应用程序开发者账户**。

1. 由于您已经创建了一个 HubSpot 账户，您可以选择**继续使用此用户**。

1. 点击**开始注册**。

1. 输入职位，点击**下一步**。

1. 为开发者账户命名，点击**下一步**，再点击**跳过**。

1. 选择 **Create App (创建应用程序)**。

1. 创建应用程序后，选择**身份验证**。

1. 记下身份验证下的客户端 ID 和 客户端密钥。

1. 添加所在地区特定的**重定向 URL**：https:*//<aws-region>*.console.aws.amazon.com/gluestudio/oauth。例如，如果是 us-east-1 区域，则添加 https://us-east-1.console.aws.amazon.com/gluestudio/oauth。

1. 向下滚动，找到作用域。必须在“CRM”和“标准”标题下选择两种类型的作用域。

1. 添加以下作用域：

   ```
   content
   automation
   oauth
   crm.objects.owners.read
   forms
   tickets
   crm.objects.contacts.write
   e-commerce
   crm.schemas.custom.read
   crm.objects.custom.read
   sales-email-read
   crm.objects.custom.write
   crm.objects.companies.write
   crm.lists.write
   crm.objects.companies.read
   crm.lists.read
   crm.objects.deals.read
   crm.objects.deals.write
   crm.objects.contacts.read
   ```

1. 点击**保存**，开发者账户现在就可以使用了。

1. 向上滚动，找到**客户端 ID**。

1. 在同一页面上，点击**显示**，获取**客户端密钥**。

## 创建 HubSpot 开发者测试账户
<a name="hubspot-configuring-creating-hubspot-developer-test-account"></a>

在应用程序开发者账户中，可以创建开发者测试账户来测试应用程序和集成，这不会对任何真实的 HubSpot 数据造成影响。开发者测试账户不能镜像生产账户，但可以使用营销、销售、服务、CMS 和运营中心企业版的 90 天试用版，这样可以测试大多数 HubSpot 工具和 API。

1. 点击**主页**。

1. 点击**创建测试账户**。

1. 点击**创建应用程序测试账户**。

1. 此时会显示一个新窗口。输入应用程序测试账户名称，点击**创建**。

   此时，应用程序测试账户就创建好了。

**注意**  
开发者账户用于 API 集成等开发活动，应用程序测试账户用于查看开发者账户创建或拉取的数据。

# 配置 HubSpot 连接
<a name="hubspot-configuring-connections"></a>

HubSpot 支持 OAuth2 的 AUTHORIZATION\$1CODE 授权类型。
+ 此授权类型被视为“三足型”OAuth，因为它依赖于将用户重定向到第三方授权服务器来对用户进行身份验证。它用于通过 AWS Glue 控制台创建连接。用户要创建连接，则需为 HubSpot 客户端应用程序提供与 OAuth 相关的信息，例如客户端 ID 和客户端密钥。AWS Glue 控制台会将用户重定向到 HubSpot，用户必须登录并向 AWS Glue 授予所请求的权限，以便访问其 HubSpot 实例。
+ 用户仍然可以选择在 HubSpot 中创建自己的关联应用程序，并在通过 AWS Glue 控制台创建连接时，提供自己的客户端 ID 和客户端密钥。在这种情况下，他们仍会重定向到 HubSpot，以便登录并授权 AWS Glue 访问其资源。
+ 此授权类型会生成刷新令牌和访问令牌。访问令牌的有效期很短，可以通过刷新令牌在不需要用户干预的情况下自动刷新。
+ 有关为授权码 OAuth 流创建关联应用程序的 HubSpot 公共文档，请参阅 [Public apps](https://developers.hubspot.com/docs/api/creating-an-app)。

要配置 HubSpot 连接，请执行以下操作：

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

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

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

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

   1. 选择**连接类型**时，请选择 HubSpot。

   1. 提供 HubSpot 环境。

   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` 的权限。

1. 在 AWS Glue 作业配置中，提供 `connectionName` 作为**附加网络连接**。

# 从 HubSpot 实体中读取
<a name="hubspot-reading-from-entities"></a>

**先决条件**

您要从中读取内容的 HubSpot 对象。您将需要联系人或任务等对象名称。下表显示了同步源支持的实体。

## 同步源支持的实体
<a name="sync-table"></a>


| 实体 | API 版本 | 可以筛选 | 支持限制 | 支持排序依据 | 支持选择\$1 | 支持分区 | 
| --- | --- | --- | --- | --- | --- | --- | 
| 市场活动 | v1 | 否 | 是 | 否 | 是 | 否 | 
| 公司 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 联系人 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 联系人列表 | v1 | 否 | 是 | 否 | 是 | 否 | 
| 交易 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| CRM 管道（交易管道） | v1 | 否 | 否 | 否 | 是 | 否 | 
| 电子邮件事件 | v1 | 否 | 是 | 否 | 是 | 否 | 
| Calls | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 备注 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 电子邮件 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 会议 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 任务 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 邮政邮件 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 自定义对象 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 表单 | v2 | 否 | 否 | 否 | 是 | 否 | 
| 所有者 | v3 | 否 | 是 | 否 | 是 | 否 | 
| 产品 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 工单 | v3 | 支持 | 是 | 是 | 是 | 是 | 
| 工作流 | v3 | 否 | 否 | 否 | 是 | 否 | 
| Associations | v4 | 是 | 否 | 否 | 是 | 否 | 
| 关联标签 | v4 | 否 | 否 | 否 | 是 | 否 | 

**示例：**

```
hubspot_read = glueContext.create_dynamic_frame.from_options(
    connection_type="hubspot",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "contact",
        "API_VERSION": "v3"
    }
```

## 异步源支持的实体
<a name="async-table"></a>


| 实体 | API 版本 | 可以筛选 | 支持限制 | 支持排序依据 | 支持选择\$1 | 支持分区 | 
| --- | --- | --- | --- | --- | --- | --- | 
| 公司 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 联系人 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 交易 | v3 | 是 | 否 | 是 | 是 | 否 | 
| Calls | v3 | 是 | 否 | 是 | 是 | 否 | 
| 备注 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 电子邮件 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 会议 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 任务 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 邮政邮件 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 自定义对象 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 产品 | v3 | 是 | 否 | 是 | 是 | 否 | 
| 工单 | v3 | 是 | 否 | 是 | 是 | 否 | 

**示例：**

```
hubspot_read = glueContext.create_dynamic_frame.from_options(
    connection_type="hubspot",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "contact",
        "API_VERSION": "v3",
        "TRANSFER_MODE": "ASYNC"
    }
```

**HubSpot 实体和字段详细信息**：

**HubSpot API v4**：

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

**注意**  
对于 `Associations` 对象，要获取两个对象之间的关联，您需要在创建 AWS Glue 作业时通过强制筛选器提供“from Id”（第一个对象的 ID）。在这种情况下，如果要获取多个 from ID 的关联，则必须在 `where` 子句中提供多个 ID。例如：要获取联系人 ID“1”和“151”的 `Associations`，您需要提供筛选器 `where id=1 AND id=151`。

**HubSpot API v3**：

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

对于以下实体，HubSpot 提供用于动态获取元数据的端点，以便在每个实体的数据类型级别捕获运算符支持。

**注意**  
`DML_STATUS` 是在运行时添加到每条记录上的虚拟字段，用于在同步模式下确定字段状态（CREATED/UPDATED）。异步模式下不支持 `CONTAINS/LIKE` 运算符。

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

**HubSpot API v2**：

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

**HubSpot API v1**：

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

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

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

  对于日期时间字段，我们接受 ISO 格式的值。

  有效值示例：

  ```
  “2024-01-01T10:00:00.115Z" 
  ```
+ `UPPER_BOUND`：所选分区字段的**排除**上限值。
+ `NUM_PARTITIONS`：分区的数量。

下表描述实体分区字段支持详细信息：

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

示例：

```
hubspot_read = glueContext.create_dynamic_frame.from_options(
    connection_type="hubspot",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "company",
        "API_VERSION": "v3",
        "PARTITION_FIELD": "hs_object_id"
        "LOWER_BOUND": "50"
        "UPPER_BOUND": "16726619290"
        "NUM_PARTITIONS": "10"
    }
```

# 写入 HubSpot 实体
<a name="hubspot-writing-to-entities"></a>

## 先决条件
<a name="hubspot-writing-prerequisites"></a>
+ 您要写入的 HubSpot 对象。您将需要联系人或工单等对象名称。
+ HubSpot 连接器支持以下写入操作：
  + INSERT
  + UPDATE
+ 使用 `UPDATE` 写入操作时，必须提供 `ID_FIELD_NAMES` 选项以指定记录的 ID 字段。

## Sync 目标支持的实体
<a name="hubspot-supported-entities"></a>


| 实体 | API 版本 | 是否支持作为目的地连接器 | 是否可以插入 | 是否可以更新 | 
| --- | --- | --- | --- | --- | 
| 公司 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 联系人 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 交易 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 产品 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| Calls | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 会议 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 备注 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 电子邮件 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 任务 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 邮政邮件 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 自定义对象 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 工单 | v3 | 是 | 是（单条、批量） | 是（单条、批量） | 
| 关联 | v4 | 是 | 是（单条、批量） | 否 | 
| 关联标签 | v4 | 是 | 是（单条、批量） | 是（单条、批量） | 

**示例：**

**INSERT 操作**

```
hubspot_write = glueContext.write_dynamic_frame.from_options(
    frame=frameToWrite,
    connection_type="hubspot",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "contact",
        "API_VERSION": "v3",
        "WRITE_OPERATION": "INSERT"
    }
)
```

**UPDATE 操作**

```
hubspot_write = glueContext.write_dynamic_frame.from_options(
    frame=frameToWrite,
    connection_type="hubspot",
    connection_options={
        "connectionName": "connectionName",
        "ENTITY_NAME": "deal",
        "API_VERSION": "v3",
        "WRITE_OPERATION": "UPDATE",
        "ID_FIELD_NAMES": "hs_object_id"
    }
)
```

# HubSpot 连接选项
<a name="hubspot-connection-options"></a>

以下是 HubSpot 的连接选项：
+ `ENTITY_NAME`（字符串）：（必填）用于读取。HubSpot 中对象的名称。
+ `API_VERSION`（字符串）：（必填）用于读取。要使用的 HubSpot Rest API 版本。例如：v1、v2、v3、v4。
+ `SELECTED_FIELDS`（列表<字符串>）–默认：empty(SELECT \$1)。用于读取。您想要为对象选择的列。
+ `FILTER_PREDICATE`（字符串）– 默认：空。用于读取。应采用 Spark SQL 格式。
+ `QUERY`（字符串）– 默认：空。用于读取。完整的 Spark SQL 查询。
+ `PARTITION_FIELD`（字符串）– 用于读取。用于分区查询的字段。
+ `LOWER_BOUND`（字符串）– 用于读取。所选分区字段的包含下限值。
+ `UPPER_BOUND`（字符串）– 用于读取。所选分区字段的排除上限值。
+ `NUM_PARTITIONS`（整数）– 默认：1。用于读取。要读取的分区数。
+ `TRANSFER_MODE`（字符串）– 用于指示是否应在异步模式下运行查询。
+ `WRITE_OPERATION`（字符串）– 默认：INSERT。用于写入。值应为 INSERT 或 UPDATE。
+ `ID_FIELD_NAMES`（字符串）– 默认：null。UPDATE 操作所必须。

# HubSpot 连接器的限制和说明
<a name="hubspot-connector-limitations"></a>

以下是 HubSpot 连接器的限制或说明：
+ 对于任何给定查询，搜索端点的结果总数限制为 1 万条。任何包含超过 1 万条记录的分区都会导致 400 错误。
+ [限制](https://developers.hubspot.com/docs/api/crm/search#limitations)中描述了连接器的其他重要限制。
+ HubSpot 最多接受三个筛选语句。
+ 目前，HubSpot 支持标准 HubSpot 对象（例如联系人、公司、交易或工单）与自定义对象之间的关联。
  + 对于免费账户：在每个对象配对（例如联系人和公司）之间，最多只能创建 10 种关联类型。
  + 对于超级管理员账户：每个对象配对之间最多只能创建 50 种关联类型。
  + 有关更多信息，请参阅 [Associations v4](https://developers.hubspot.com/docs/api/crm/) 和 [Create and use association labels](https://knowledge.hubspot.com/object-settings/create-and-use-association-labels)。
+ “报价”和“通信”对象目前不支持关联，因为连接器中暂不支持这些对象。
+ 对于异步模式，SaaS 仅按升序对值进行排序。
+ 对于 `Ticket` 实体，SaaS 不会在异步模式下返回 `hs_object_id` 字段。