
# 自定义渠道

使用自定义渠道将任何消息平台或通信工具连接到本平台。这使您可以将来自网站实时聊天小部件、电子邮件系统、CRM 或任何其他服务的消息引入收件箱，并使用您的 AI 智能体进行回复。


---

## 什么是自定义渠道？

自定义渠道将平台的功能扩展到其内置消息平台（[WhatsApp](whatsapp-business.md)、[SMS](sms.md)、[Instagram](instagram-dms.md)、[Messenger](facebook-messenger.md)）之外。通过自定义渠道，您可以：

- **接收消息**：将任何外部平台的消息接收到本平台的统一收件箱中。
- **发送回复**：自动从本应用将回复发送回您的外部平台。
- **使用 AI 智能体**：响应来自任何来源的消息。
- **跟踪所有对话**：在单个收件箱中与您的其他渠道一起管理所有对话。

这非常适合使用专业通信工具、拥有自建平台或希望将所有客户消息集中在一处的企业。

::: note
**注意：** 自定义渠道需要一定的技术设置。如果您或您的团队不熟悉技术集成，建议咨询您的 Web 开发人员或 IT 团队以获取帮助。
:::


---

## 工作原理

自定义渠道通过在您的外部平台与本平台之间使用 **Webhook**（在互联网上系统之间发送的自动化消息）来回传递消息。流程如下：

```
Your Platform  ──(sends message to)──>  The App
                                           |
                                       AI Agent responds
                                       Contact saved
                                       Message stored
                                           |
The App  ──(sends reply to)──>  Your Platform
```

1. **传入消息：** 您的外部平台将消息发送到一个网址 (URL)。可以将其视为您的平台向本平台的“邮箱”发送消息。
2. **处理：** 本平台创建或更新联系人、存储消息，并让 AI 智能体生成回复（如果已启用）。
3. **传出消息：** 当本平台发送回复时（无论是来自 AI 还是您手动输入），它会将消息发送到您平台上的一个 URL，您的系统可以在该 URL 将消息传递给最终用户。

---

## 设置传入消息（从您的平台到本应用）

要将消息从您的外部平台发送到本应用，您的平台需要向以下 URL 发送数据。您的开发人员会将其识别为标准的 POST 请求（一种系统在互联网上向另一个系统发送数据的常用方式）。

### 发送消息的位置

```
POST https://api.youraiconnector.com/v1/incoming_custom_channel_message?apiKey=YOUR_API_KEY
```

将 `YOUR_API_KEY` 替换为您的 API 密钥（这是一个私有代码，用于向本平台证明您的平台被允许向其发送消息）。您可以在 **设置 → 集成 → API 密钥** 下找到或生成它。

### 消息格式

请按以下格式（JSON）发送消息数据：

```json
{
  "customData": {
    "messageSid": "unique-message-id-123",
    "fromId": "user-456",
    "toId": "your-business-id",
    "body": "Hello, I have a question about your service.",
    "status": "received",
    "channel": "my-live-chat",
    "campaignId": "optional-campaign-id",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@example.com",
    "mediaUrl": null,
    "mediaContentType": null
  },
  "messageType": "text"
}
```

**各部分含义：**
- `messageSid` - 此特定消息的唯一 ID（由您的系统创建）。用于防止同一消息被处理两次。
- `fromId` - 消息发送者（可以是您系统中的用户 ID、电子邮件或电话号码）。
- `toId` - 您的业务标识符（可以是您选择的任何标签）。
- `body` - 实际的消息文本。
- `channel` - 您选择的用于标识消息来源的标签（例如 "website-chat"、"email"）。

### 完整字段参考

| 字段 | 是否必填 | 作用 |
|---|---|---|
| `customData.messageSid` 或 `customData.id` | 是 | 此消息的唯一 ID（防止重复） |
| `customData.fromId` | 是 | 标识消息发送者（例如，您系统中的用户 ID、电子邮件或电话号码） |
| `customData.toId` | 是 | 标识接收方（您的业务）。可以是您选择的任何文本。 |
| `customData.body` | 是 | 实际的消息文本。不能为空。 |
| `customData.status` | 否 | 消息状态。留空以使用默认值 (`"received"`)。 |
| `customData.channel` | 否 | 来源标签（例如 `"live-chat"`、`"email"`、`"my-crm"`）。帮助您在收件箱中识别消息来源。 |
| `customData.campaignId` | 否 | 营销活动/代理 ID。使用此 ID 将消息路由到特定的 AI 配置。 |
| `customData.firstName` | 否 | 联系人名字。在创建新联系人记录时包含。 |
| `customData.lastName` | 否 | 联系人姓氏。在创建新联系人记录时包含。 |
| `customData.email` | 否 | 联系人电子邮件地址。在创建新联系人记录时包含。 |
| `customData.mediaUrl` | 否 | 附件链接（图片、视频、音频或文档）。也可以是 base64 编码的文件（见下文）。 |
| `customData.mediaContentType` | 否 | 文件类型（例如 `"image/jpeg"`、`"video/mp4"`、`"audio/ogg"`、`"application/pdf"`）。如果您包含 `mediaUrl`，则此项为必填。 |
| `messageType` | 否 | 消息类型。普通文本请留空。设置为 `"reaction"` 以表示表情符号反应。 |

### Emoji 表情反应

如果您的平台支持 emoji 表情反应（例如对消息点赞），请将其作为反应而非文本消息发送：将 `messageType` 设置为 `"reaction"`，并将 emoji 放入 `customData.body` 中。

```json
{
  "messageType": "reaction",
  "customData": {
    "messageSid": "reaction-123",
    "fromId": "user-42",
    "toId": "my-business",
    "body": "👍"
  }
}
```

助手随后会按您的预期方式处理它：

- 对助手提出的问题（例如“周四方便吗？”）做出的反应会被视为回答，助手会进行回复。
- 对结束语（例如“回聊！”）做出的反应会安静地结束对话。不会发送任何回复。

如果您的平台将反应转换为文本（例如“Reacted with: 👍”），助手会将其视为普通文本消息，并自行决定是否回复。发送反应类型可以避免这种情况。

### 您将获得的回应

请求成功时返回：

```json
{
  "success": true,
  "messageId": "1234567890"
}
```

如果出现问题，您将收到一条解释问题的错误消息：

```json
{
  "error": "Message body cannot be empty"
}
```

### 状态码

| 代码 | 含义 |
|---|---|
| `200` | 成功 - 消息已接收并正在处理 |
| `400` | 请求有误 - 请检查是否缺少必填字段或消息主体是否为空 |
| `401` | API 密钥无效 - 请在 **设置 → 集成 → API 密钥** 中核对密钥 |
| `405` | 请求方法错误 - 确保您使用的是 POST 而不是 GET |
| `500` | 平台端出现问题 - 请稍后再试 |

> 如果您设置了 `customData.status`，唯一可接受的值是 `"received"` —— 请直接留空以使用默认值，不要发送其他任何内容，否则会收到 `400` 错误。

---

## 发送媒体附件（图片、视频、文件）

您可以在消息中包含文件附件（图片、视频、音频、文档）。有两种实现方式：

### 选项 1：文件链接

如果文件已托管在网上，请提供平台可以下载该文件的 URL（网址）：

```json
{
  "customData": {
    "messageSid": "msg-789",
    "fromId": "user-456",
    "toId": "business-1",
    "body": "Here is a photo of the issue.",
    "channel": "support-portal",
    "mediaUrl": "https://example.com/uploads/photo.jpg",
    "mediaContentType": "image/jpeg"
  },
  "messageType": "text"
}
```

### 选项 2：直接嵌入文件（Base64）

如果文件未托管在在线服务器上，您可以将其作为编码文本（base64 格式）直接嵌入到消息中。这在您的系统动态生成文件的技术集成中很常见。平台将自动解码并存储该文件：

```json
{
  "customData": {
    "messageSid": "msg-790",
    "fromId": "user-456",
    "toId": "business-1",
    "body": "Screenshot attached.",
    "channel": "support-portal",
    "mediaUrl": "data:image/png;base64,iVBORw0KGgo...",
    "mediaContentType": "image/png"
  },
  "messageType": "text"
}
```

::: note
**注意：** 直接嵌入文件会使消息数据变得非常大。对于大文件，最好将其托管在在线服务器上并发送链接（选项 1）。
:::


---

## 设置外发消息（平台到您的平台）

当平台在自定义渠道上发送回复时（无论是来自 AI 还是您手动输入），它会自动将该回复发送到您平台上的一个 URL，以便您的系统将其传递给最终用户。

> **请先设置 Webhook URL。** 在任何回复能够被发送之前，您必须先保存自定义渠道的 Webhook URL。如果未保存 URL，回复仍会被生成和存储，但永远不会被发送出去——而且它们**不会**显示“失败”状态，因此您的收件箱中没有任何内容会标记此问题。请务必在上线前配置好 Webhook URL。

### 告诉应用程序发送回复的位置

1. 在左侧边栏中，点击底部的 **Settings**（设置）。
2. 在“设置”左侧导航栏中，在 **Channels**（渠道）下，点击 **Channels**（渠道）。
3. 在页面最底部找到 **Custom channel**（自定义渠道）卡片（位于 Android SMS Gateway、iMessage、网站聊天小部件、Twilio 账户和合规性之后）。
4. 输入 **Webhook URL** — 即您平台上 AI 应发送外发消息的 URL（由您的开发人员设置以接收和处理回复）。它必须是一个 **公共 HTTPS URL** — `http://` 地址和非公共主机将被拒绝。
5. 点击 **Save**（保存）。



### 平台发送给您平台的内容

当平台发送回复时，您的平台将收到以下数据：

```json
{
  "contactId": "abc123",
  "messageId": "msg-456",
  "userId": "your-user-id",
  "body": "Thank you for your message! Here is the information you requested...",
  "toId": "user-456",
  "channel": "my-live-chat"
}
```

### 每个字段的含义

| 字段 | 内容 |
|---|---|
| `contactId` | 平台为此联系人生成的内部 ID |
| `messageId` | 此消息在应用程序中的唯一 ID |
| `userId` | 您的用户 ID |
| `body` | 回复文本 |
| `toId` | 联系人在您平台上的 ID（这与您在传入消息中发送的 `fromId` 相匹配） |
| `channel` | 您分配的自定义渠道标签 |

您的平台接收此数据，并使用它通过您自己的系统将回复传递给最终用户。

### 平台如何跟踪投递状态

在向您的平台发送回复后，平台会更新消息状态：

- **已发送** - 您的平台已成功接收消息。
- **失败** - 您的平台返回了错误或无法访问。平台会将错误详情与消息一起存储，以便您进行故障排查。

---

## 从您的系统向应用发送消息

除了接收消息外，您还可以直接通过自定义渠道从您自己的系统发送出站消息。当您想要发起对话或发送主动消息时，此功能非常有用。

> **套餐要求。** 通过 API 发送和同步消息需要包含 API 访问权限和至少一个消息渠道的套餐。如果您收到 `403` “权限被拒绝 / 功能未启用”错误，说明您当前的套餐不包含此功能 — 请升级您的套餐或联系支持团队。

### 发送位置

```
POST https://api.youraiconnector.com/v1/send_custom_channel_message?apiKey=YOUR_API_KEY
```

### 消息格式

```json
{
  "customData": {
    "fromId": "user-456",
    "customChannel": "my-live-chat",
    "body": "Hello! How can I help you today?",
    "campaignId": "optional-campaign-id",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@example.com"
  }
}
```

### 必填字段

| 字段 | 作用 |
|---|---|
| `customData.fromId` | 联系人在您平台上的 ID |
| `customData.customChannel` | 您的自定义渠道名称（例如 "my-live-chat"） |
| `customData.body` | 要发送的消息文本 |

可选字段（`campaignId`、`firstName`、`lastName`、`email`）的作用与传入消息中的相同 — 它们有助于平台创建或更新联系人记录。

### 您将获得的回应

```json
{
  "success": true,
  "messageId": "generated-message-id",
  "contactId": "contact-id",
  "message": "Message sent successfully"
}
```

---

## 记录从其他系统发送的消息

有时您已经通过其他工具（例如，另一个平台中的工作流）向联系人发送了消息，而您只是希望平台了解该消息，以便 AI 拥有完整的上下文。这与发送不同：平台会记录该消息，但**不会**将其重新发送给联系人。

### 发送位置

```
POST https://api.youraiconnector.com/v1/sync_custom_channel_message?apiKey=YOUR_API_KEY
```

包含 `customData.fromId`（联系人在您平台上的 ID）和 `customData.body`（已发送的消息文本）。

### 行为方式

- **消息仅被记录，不会被重新发送。** 平台仅将其存储在对话中以供参考。
- **默认情况下，该联系人的 AI 会处于暂停状态。** 这可以避免机器人在人工已处理的消息上进行回复。若要保持机器人处于活跃状态，请传递 `customData.pauseAi: false`。
- **可以自动创建新联系人。** 包含 `customData.customChannel`，如果联系人尚不存在，系统将自动创建。
- **重复项会被忽略。** 如果您重复使用相同的 `messageSid`，平台会识别出该消息已被记录，因此不会进行任何更改。

> **套餐要求。** 与发送消息一样，通过 API 记录消息需要包含 API 访问权限和至少一个消息渠道的套餐。如果出现 `403` “权限被拒绝 / 功能未启用”错误，则意味着您当前的套餐不包含此功能。

---

## 实际应用示例

### 网站实时聊天

将您网站上的实时聊天小部件连接到平台，以便您的 AI 智能体可以回答访客的问题：

1. 访客在您网站的聊天小部件中输入消息。
2. 您的聊天小部件将消息发送到平台。
3. AI 智能体生成回复。
4. 回复被发送回您的聊天小部件，并显示给访客。

**为什么这很有用：** 您的网站访客无需您在线即可获得 AI 驱动的即时问题解答。

### 电子邮件

通过平台路由电子邮件对话，以便您的 AI 智能体可以回复电子邮件：

1. 设置一个系统，将收到的电子邮件转发到平台（使用电子邮件发送者的地址作为 `fromId`，电子邮件主题和正文作为 `body`，并将 `"email"` 作为 `channel`）。
2. AI 智能体读取电子邮件并生成回复。
3. 回复被发送回您的电子邮件系统，该系统将其作为正常的电子邮件回复发送出去。

**为什么这很有用：** 常见的电子邮件问题（如定价、营业时间、可用性）可以由您的 AI 智能体即时回答。

> 如果您的电子邮件系统支持 IMAP/SMTP 或 OAuth，内置的 [电子邮件渠道](email.md) 可能比自定义集成更简单。

### CRM 集成

将您现有的 CRM（客户关系管理）系统连接到平台：

1. 当潜在客户通过您的 CRM 发送消息时，将其转发到该平台。
2. AI 代理会做出响应并跟踪对话。
3. AI 的回复会被发送回您的 CRM 以进行投递。
4. 完整的对话历史记录在平台和您的 CRM 中均可查看。

**为什么这很有用：** 您的销售团队无需离开 CRM 即可获得 AI 辅助的潜在客户回复。

### 支持工单系统

将该平台用作客户支持的 AI 驱动型第一响应者：

1. 您的工单系统将新支持工单转发到该平台。
2. AI 代理发送初步回复（例如，确认收到工单并询问澄清问题）。
3. 回复会被附加到您支持系统中的工单上。
4. 您的支持团队可以查看 AI 的回复，并在需要时接管对话。

**为什么这很有用：** 即使在工作时间之外，客户也能获得即时的确认和初步帮助。

---

## 故障排除

### 平台未收到消息

- 验证您的 API 密钥是否正确且处于激活状态（检查 **设置 → 集成 → API 密钥**）。
- 确保您发送的是 POST 请求（而非 GET）。您的开发人员会知道其中的区别。
- 检查 `customData.body` 字段是否为空或仅包含空格。
- 验证是否包含了 `customData.fromId` 字段。
- 阅读响应消息以获取具体的错误详情。

### 回复未到达您的平台

- 确保您已在“渠道”页面的 **自定义渠道** 卡片中输入了您平台的 URL。如果未保存 URL，回复会被生成并存储但永远不会发送出去——而且它们**不会**被标记为“失败”，所以请首先检查这一点。
- 验证该 URL 是否可公开访问（不在登录页面或防火墙之后）并返回成功响应。
- 只有回复（外发消息）会被发送到您的 URL——传入消息不会触发此操作。
- 在您的收件箱中检查消息的错误详情。

### 联系人未创建

- 确保 `fromId` 值对于同一用户在所有消息中保持一致。平台使用此值来识别联系人——如果它在不同消息之间发生变化，平台每次都会创建一个新的联系人。
- 在新联系人的第一条消息中包含 `firstName`、`lastName` 和 `email`，以创建完整的联系人记录。

### 媒体附件无法正常工作

- 对于文件链接 (URL)，请确保文件可公开访问（无需登录即可访问）。
- 在包含 `mediaUrl` 时，请务必包含 `mediaContentType`。
- 对于嵌入式文件 (base64)，请验证格式是否为 `data:MIME_TYPE;base64,ENCODED_DATA`。
- 确保您指定的文件类型与实际文件内容匹配。

---

## 最佳实践

- **使用一致的 `fromId` 值。** 您平台上的每个用户都应始终拥有相同的 `fromId`。这可确保平台将其所有消息归入同一个对话中，而不是创建重复的联系人。
- **选择清晰的 `channel` 名称。** 选择像 `"website-chat"`、`"email"` 或 `"zendesk"` 这样具有描述性的名称，以便在查看收件箱时可以轻松分辨消息的来源。
- **包含联系方式**（`firstName`、`lastName`、`email`）在新联系人的第一条消息中。这可以立即创建一个完整且有用的联系人记录。
- **构建重试逻辑。** 如果平台在第一次尝试时没有响应，请让您的平台重试发送消息（网络波动时有发生）。
- **为每条消息使用唯一的 `messageSid` 值。** 如果您的系统多次发送同一条消息，这可以防止其被处理两次。
- **使用 `campaignId`** 在拥有多个用例（例如，销售咨询与支持问题）时，将消息路由到不同的 AI 代理。
- **上线前进行测试。** 在双向发送测试消息，并验证联系人、对话和 AI 响应是否都能正常工作，然后再向真实用户发布。
