跳至主要内容

Aile 平臺整合(Integration)外部對接手冊

版本: v2.2
最後更新: 2026-06-26
適用對象: 第三方系統整合開發者
服務模組: aile-service-integration
程式碼分支: release

v2.2 保留 AIFF 寫入規格、pictureUrl 主資料與 setting 級圖片、訊息傳送、服務廣播與 Simulator 聯調說明。

v2.2+ 變更摘要(2026-06-25 release):

  • Breaking: OpenAPI 路徑重構 — 從 /integration/openapi/v1/<資源> 改為 /<資源>/v1/<動作>
  • Breaking: 所有 OpenAPI 端點統一為 POST,不再支援 GET。
  • Breaking: HMAC 簽名公式修正 — integrationId + nonce + body(不含 method/path)。
  • Breaking: Authorization 頭字首從 HMAC-SHA256 改為 AILE
  • 新增: AIFF 寫入介面(create/update/delete)。
  • 新增: 訊息傳送介面(POST /messages/v1/send)。
  • 新增: 群發廣播介面(POST /messages/v1/broadcast/create)。
  • 修正: 事件資源域和事件型別列表(基於原始碼)。

目錄

  1. 概述
  2. 核心概念與模型
  3. 整合接入流程
  4. OpenAPI 安全機制(HMAC 簽名)
  5. 控制面 API(平臺管理端)
  6. OpenAPI(第三方呼叫 Aile)
  7. Webhook 事件推送(Aile → 第三方)
  8. 事件資源域與事件型別參考
  9. 接入實戰指南(第三方開發步驟)
  10. 參考實現:Simulator 模擬服務
  11. 常見問題與錯誤碼

1. 概述

Aile 平臺整合(Platform Integration)是一套標準化的第三方系統接入框架,允許外部 SaaS 平臺以租戶級別安裝 Aile 服務,並交換業務事件與資料。

1.1 架構全景

┌─────────────────────────────────────────────────┐
│ Aile 平臺 │
│ │
│ aile-service-integration │
│ ├── /integration/app/* 應用定義管理 │
│ ├── /integration/tenant/* 安裝生命週期管理 │
│ ├── /messages/* 訊息傳送 / 廣播 │
│ ├── /openapi/* 第三方 API(HMAC簽名)│
│ └── InternalEvent → Webhook → 第三方回撥 │
│ │
│ aile-service-tenant (事件釋出) │
│ └── InternalEventTrigger → 業務事件發布 │
└─────────────────────────────────────────────────┘
│ 控制面 (HTTP) │ OpenAPI (HMAC) │ Webhook (HMAC)
▼ ▼ ▼
┌─────────────────────────────────────────────────┐
│ 第三方整合平臺(你) │
│ ├── 安裝介面 (接收 Aile 安裝請求) │
│ ├── OpenAPI 呼叫 (查詢/傳送訊息/群發廣播) │
│ └── Webhook 接收 (接收 Aile 業務事件) │
└─────────────────────────────────────────────────┘

1.2 與舊版 TenantAppModel 的關係

注意: aile-service-job 模組中有一個舊的 TenantAppModel / TenantAppController 體系,以 /tenantapp/webhook 為路徑字首。本手冊描述的是新的 Integration Platform 體系(基於 IntegrationAppModel / TenantIntegrationModel),路徑字首為 /integration/。新體系相較舊體繫有以下增強:

特性舊 TenantAppModel新 Integration Platform
應用定義無全域性應用定義IntegrationApp(獨立於租戶)
安裝生命週期簡單 CRUD完整狀態機 Pending→Active→Suspended→Deleted
金鑰管理固定 secretKeyHMAC appSecret + rotate-secret
事件訂閱webHookTypessubscribedEvents(事件資源域粒度)
第三方回撥install/update/rotateSecret/uninstall
OpenAPI 目錄catalog 端點自動發現
安全隔離簽名+租戶繫結integrationId + body 一致性校驗 + nonce

2. 核心概念與模型

2.1 IntegrationApp(平臺應用定義)

這是由 Aile 管理員建立的全域性應用註冊,描述一個第三方平臺的身份和能力。

{
"appId": "your-app-id", // 全域性唯一應用 ID
"appName": "Your Platform Name", // 應用名稱
"provider": "your-company", // 提供方
"supportedEvents": [ // 支援的事件資源域(*. 為通配)
"contact.*",
"service_number.*"
],
"authType": "HMAC_SHA256", // 鑑權型別
"secret": "platform-secret", // 平臺級金鑰(Aile 呼叫第三方時使用)
"installUrl": "https://your-platform.com/api/aile/install", // 第三方安裝 URL
"updateUrl": "https://your-platform.com/api/aile/update", // 第三方更新 URL
"rotateSecretUrl": "https://your-platform.com/api/aile/rotate", // 第三方輪換金鑰 URL
"uninstallUrl": "https://your-platform.com/api/aile/uninstall", // 第三方解除安裝 URL
"installAckMode": "Sync", // Sync(同步完成)或 Async(非同步受理)
"status": "Active" // Draft → Active → Suspended → Deleted
}

──→ 狀態機:Draft → Active → Suspended → Active → Deleted

2.2 TenantIntegration(租戶安裝例項)

當一個 Aile 租戶安裝你的平臺應用時,會在 Aile 端建立一個安裝例項:

{
"integrationId": "ti_xxxxx", // 安裝例項唯一 ID(Aile 生成)
"appId": "your-app-id", // 關聯的應用 ID
"tenantId": "T001", // Aile 租戶 ID
"tenantType": "enterprise", // 租戶型別
"externalTenantId": "EXT-12345", // 第三方系統對應租戶 ID(由你指定)
"appSecret": "generated-secret", // 安裝級金鑰(用於 HMAC 簽名,由 Aile 生成)
"webhookUrl": "https://your-platform.com/webhook/events", // 事件接收地址
"subscribedEvents": [ // 實際訂閱的事件資源域
"contact.*",
"service_number.*"
],
"installAckMode": "Sync", // 受理模式
"status": "Active" // 安裝狀態
}

──→ 安裝狀態機:Pending → Active → Suspended/Disabled → Active → Deleted
InstallFailed 狀態表示安裝失敗。

2.3 租戶隔離模型

  • 一個 IntegrationApp 可以被多個租戶安裝(多個 TenantIntegration
  • 每個 TenantIntegration 擁有獨立的 appSecretwebhookUrl
  • OpenAPI 呼叫時,第三方只能訪問該安裝例項所屬租戶的資料
  • 跨系統租戶對映透過 externalTenantId 欄位管理(不存在獨立的 TenantMapping 模型

3. 整合接入流程

3.1 整體流程圖

Step 0: Aile 管理員註冊 IntegrationApp(後臺操作)

Step 1: Aile 租戶發起安裝
POST /integration/tenant/system/v1/install
{ appId, tenantId, tenantType }

├── Aile 建立 TenantIntegration(狀態=Pending)
├── Aile 呼叫第三方 installUrl(傳遞 integrationId、appSecret 等)

Step 2: 第三方處理安裝
├── 驗證請求合法性
├── 建立外部租戶關聯
├── 確認 webhookUrl 和 subscribedEvents

├── Sync 模式:直接返回 { status: "Active", externalTenantId, webhookUrl, subscribedEvents }
│ → Aile 更新狀態為 Active

└── Async 模式:先返回 { accepted: true, status: "Pending" }
→ 後續回撥 Aile
POST /integration/tenant/open/v1/install/callback
{ integrationId, status: "Active", externalTenantId, webhookUrl, subscribedEvents }
→ Aile 更新狀態為 Active

Step 3: 日常執行
├── 第三方呼叫 Aile OpenAPI(HMAC 簽名,查詢/同步資料)
└── Aile 推送業務事件到第三方 webhookUrl(HMAC 簽名)

Step 4: 解除安裝
POST /integration/tenant/system/v1/uninstall?integrationId=xxx
├── Aile 呼叫第三方 uninstallUrl
└── TenantIntegration 狀態 = Deleted

3.2 Aile 傳送給第三方的安裝請求

當租戶發起安裝後,Aile 會呼叫 IntegrationApp.installUrl,傳送的請求體:

{
"integrationId": "ti_xxxxx",
"appId": "your-app-id",
"tenantId": "T001",
"tenantType": "enterprise",
"operatorId": "emp_001",
"appSecret": "generated-secret-for-this-instance",
"installationCallbackUrl": "https://aile-api.com/integration/tenant/open/v1/install/callback",
"installAckMode": "Sync",
"subscribedEvents": ["contact.*", "service_number.*"]
}

3.3 第三方應返回的安裝響應

Sync 模式(installAckMode=Sync):

{
"status": "Active",
"externalTenantId": "EXT-12345",
"webhookUrl": "https://your-platform.com/webhook/events",
"subscribedEvents": ["contact.*", "service_number.*"]
}

Async 模式(installAckMode=Async):

{
"accepted": true,
"status": "Pending"
}

之後非同步回撥 Aile:

curl -X POST https://aile-api.com/integration/tenant/open/v1/install/callback \
-H "Content-Type: application/json" \
-d '{
"integrationId": "ti_xxxxx",
"status": "Active",
"externalTenantId": "EXT-12345",
"webhookUrl": "https://your-platform.com/webhook/events",
"subscribedEvents": ["contact.*", "service_number.*"]
}'

3.4 第三方更新 / 輪換金鑰 / 解除安裝介面

Aile 在以下場景會呼叫第三方對應 URL(定義在 IntegrationApp 中):

操作Aile 呼叫傳遞引數
更新配置updateUrl{ integrationId, webhookUrl, subscribedEvents }
輪換金鑰rotateSecretUrl{ integrationId, operatorId }
解除安裝uninstallUrl{ integrationId }

4. OpenAPI 安全機制(HMAC 簽名)

所有第三方呼叫 Aile OpenAPI 的請求都必須攜帶 HMAC 簽名。Aile 推送的 Webhook 事件也會使用相同簽名機制。

4.1 簽名演算法

演演算法:  HMAC-SHA256
金鑰: appSecret(來自 TenantIntegration 安裝例項)
簽名內容: integrationId + nonce + requestBody
簽名結果: Base64( HMAC-SHA256(appSecret, 簽名內容) )

4.2 請求頭規範

Header說明
AuthorizationAILE {integrationId}:{signature}簽名身份與結果
X-Aile-Noncenonce_1718256000123每次請求唯一的隨機字串
Content-Typeapplication/json請求體格式

4.3 簽名示例(Python)

import hmac
import hashlib
import base64
import time
import requests

def build_signature(integration_id: str, app_secret: str, nonce: str, body: str) -> str:
"""
計算 HMAC-SHA256 簽名。
簽名內容 = integrationId + nonce + body
"""
raw = integration_id + nonce + body
mac = hmac.new(
app_secret.encode('utf-8'),
raw.encode('utf-8'),
hashlib.sha256
)
return base64.b64encode(mac.digest()).decode('utf-8')

def build_auth_header(integration_id: str, signature: str) -> str:
return f"AILE {integration_id}:{signature}"

def call_aile_openapi(integration_id: str, app_secret: str,
method: str, path: str, body: dict = None) -> dict:
"""
呼叫 Aile OpenAPI。
path 格式: /tenants/v1/me
"""
base_url = "https://aile-api.com" # 替換為實際環境地址
body_str = json.dumps(body) if body else ""
nonce = f"nonce_{int(time.time() * 1000)}"

signature = build_signature(integration_id, app_secret, nonce, body_str)
authorization = build_auth_header(integration_id, signature)

response = requests.request(
method=method,
url=f"{base_url}{path}",
headers={
"Authorization": authorization,
"X-Aile-Nonce": nonce,
"Content-Type": "application/json"
},
data=body_str if body_str else None
)
return response.json()

4.4 簽名示例(JavaScript / Node.js)

import crypto from "crypto";

function buildSignature(integrationId, appSecret, nonce, bodyString) {
const raw = integrationId + nonce + (bodyString ?? "");
return crypto.createHmac("sha256", appSecret).update(raw).digest("base64");
}

function buildAuthHeader(integrationId, signature) {
return `AILE ${integrationId}:${signature}`;
}

async function callAileOpenApi(integrationId, appSecret, method, path, body) {
const bodyStr = body ? JSON.stringify(body) : "";
const nonce = `nonce_${Date.now()}`;
const signature = buildSignature(integrationId, appSecret, nonce, bodyStr);

const response = await fetch(`https://aile-api.com${path}`, {
method,
headers: {
"Authorization": buildAuthHeader(integrationId, signature),
"X-Aile-Nonce": nonce,
"Content-Type": "application/json"
},
body: bodyStr || undefined
});
return response.json();
}

4.5 簽名示例(Java)

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AileHmacSigner {
public static String buildSignature(String integrationId, String appSecret,
String nonce, String body) {
String raw = integrationId + nonce + (body != null ? body : "");
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
return Base64.getEncoder().encodeToString(mac.doFinal(raw.getBytes(StandardCharsets.UTF_8)));
} catch (Exception e) {
throw new RuntimeException("HMAC signing failed", e);
}
}

public static String buildAuthHeader(String integrationId, String signature) {
return "AILE " + integrationId + ":" + signature;
}
}

4.6 簽名驗證流程(服務端)

Aile 服務端驗證流程:

  1. 過濾器攔截所有 OpenAPI 資源路徑(例如 /tenants/v1/me/contacts/v1/list/aiffs/v1/create
  2. Authorization 頭解析 integrationIdrequestSignature
  3. 從請求體中解析 integrationId 欄位,與簽名中的身份一致性校驗(防止冒用)
  4. 根據 integrationId 查詢 TenantIntegrationModel,取得 appSecret
  5. 使用 appSecretintegrationId + nonce + body 計算 HMAC-SHA256
  6. 使用 MessageDigest.isEqual() 時間恆定比對簽名
  7. 校驗安裝例項狀態為 Active、所屬應用狀態為 Active

5. 控制面 API(平臺管理端)

以下 API 供 Aile 內部管理面使用,第三方不需要呼叫這些介面。列於此處供理解完整流程。

5.1 IntegrationApp(應用定義)

方法路徑說明
POST/integration/app/system/v1/create建立應用定義
POST/integration/app/system/v1/update更新應用定義
GET/integration/app/system/v1/detail?appId=查詢應用詳情
POST/integration/app/system/v1/items分頁查詢應用列表
POST/integration/app/system/v1/enable上架應用
POST/integration/app/system/v1/disable下架應用
POST/integration/app/system/v1/delete刪除應用
GET/integration/app/system/v1/statistics/usage?appId=使用統計

5.2 TenantIntegration(安裝管理)

方法路徑說明
POST/integration/tenant/system/v1/install發起安裝
POST/integration/tenant/system/v1/update更新安裝配置
POST/integration/tenant/system/v1/suspend?integrationId=暫停安裝
POST/integration/tenant/system/v1/resume?integrationId=恢復安裝
POST/integration/tenant/system/v1/uninstall?integrationId=解除安裝
POST/integration/tenant/system/v1/rotate-secret?integrationId=輪換金鑰
GET/integration/tenant/system/v1/detail?integrationId=查詢安裝詳情
GET/integration/tenant/system/v1/items?tenantId=依租戶查詢列表
GET/integration/tenant/system/v1/items/by-app?appId=依應用查詢列表
POST/integration/tenant/open/v1/install/callback第三方安裝回撥(公開介面)

5.3 安裝請求引數詳情

發起安裝:

{
"appId": "your-app-id", // 必填
"tenantId": "T001", // 必填
"tenantType": "enterprise" // 必填
}

安裝回撥(第三方 → Aile):

{
"integrationId": "ti_xxxxx", // 必填
"status": "Active", // 必填(Active 或 InstallFailed)
"externalTenantId": "EXT-12345", // 可選但不建議為空
"webhookUrl": "https://...", // 可選
"subscribedEvents": ["contact.*"], // 可選
"message": "安裝完成" // 可選
}

更新配置:

{
"integrationId": "ti_xxxxx",
"webhookUrl": "https://new-url.com/webhook",
"subscribedEvents": ["tenant.*", "contact.*"]
}

6. OpenAPI(第三方呼叫 Aile)

所有 OpenAPI 端點採用 /<資源>/v1/<動作> 路徑結構(例如 /contacts/v1/list),所有請求均為 POST 方法(含查詢請求),且必須攜帶 HMAC 簽名。舊版 /integration/openapi/v1/<資源> 路徑不再作為對外穩定契約。

6.1 通用請求格式

所有 OpenAPI 請求體都必須包含 integrationId

{
"integrationId": "ti_xxxxx"
}

其餘欄位因 API 而異。詳見各端點說明。

6.2 通用響應格式

{
"code": 200,
"message": "success",
"data": { ... }
}

6.3 API 端點一覽

6.3.1 租戶資訊

方法路徑說明
POST/tenants/v1/me查詢當前安裝例項的租戶資訊

請求:

{
"integrationId": "ti_xxxxx"
}

響應 data

{
"tenantId": "T001",
"tenantName": "某某公司",
"tenantType": "enterprise",
"status": "Active"
}

6.3.2 服務號

方法路徑說明
POST/service-numbers/v1/list查詢服務號列表
POST/service-numbers/v1/detail查詢服務號詳情
POST/service-numbers/v1/sync查詢服務號差異同步列表

列表請求:

{
"integrationId": "ti_xxxxx",
"current": 1,
"size": 20
}

詳情請求:

{
"integrationId": "ti_xxxxx",
"serviceNumberId": "SN001"
}

同步請求:

{
"integrationId": "ti_xxxxx"
}

6.3.3 員工

方法路徑說明
POST/employees/v1/list查詢租戶員工列表
{
"integrationId": "ti_xxxxx",
"current": 1,
"size": 20
}

6.3.4 聯絡人(客戶)

方法路徑說明
POST/contacts/v1/list查詢聯絡人列表
POST/contacts/v1/detail查詢聯絡人詳情
POST/contacts/v1/interactions查詢近期互動記錄

列表請求:

{
"integrationId": "ti_xxxxx",
"serviceNumberId": "SN001",
"current": 1,
"size": 20
}

詳情請求:

{
"integrationId": "ti_xxxxx",
"contactId": "C001",
"serviceNumberId": "SN001"
}

互動記錄請求:

{
"integrationId": "ti_xxxxx",
"serviceNumberId": "SN001",
"days": 30,
"current": 1,
"size": 20
}

6.3.5 群組(LineGroup)

方法路徑說明
POST/groups/v1/list查詢群組列表
{
"integrationId": "ti_xxxxx",
"current": 1,
"size": 20
}

6.3.6 會話統計

方法路徑說明
POST/sessions/v1/statistics查詢會話月統計
POST/sessions/v1/statistics/detail查詢會話月統計詳情
{
"integrationId": "ti_xxxxx",
"serviceNumberId": "SN001",
"month": "2026-06"
}

6.3.7 AIFF 配置(應用內浮動框架)

v2.2 更新。 新增 create / update / delete 寫介面,支援主資料圖片 (pictureUrl) 和 setting 級別配置。

方法路徑說明
POST/aiffs/v1/list查詢 AIFF 列表(分頁)
POST/aiffs/v1/detail查詢 AIFF 詳情(含 settings)
POST/aiffs/v1/create建立 AIFF 主資料與設定
POST/aiffs/v1/update更新 AIFF 主資料與設定
POST/aiffs/v1/delete刪除 AIFF 主資料與全部設定

列表請求:

{
"integrationId": "ti_xxxxx"
}

詳情請求:

{
"integrationId": "ti_xxxxx",
"extraId": "your-app-id"
}

建立請求 OpenApiAiffCreateRequestDto

欄位型別必填說明
integrationIdString租戶安裝例項 ID
extraIdString外部應用唯一識別(外部系統中的 AIFF ID)
nameStringAIFF 應用名稱
descriptionStringAIFF 應用描述
pictureUrlStringAIFF 主資料圖片地址,直接儲存外部傳入的 URL(不下載、不上傳)
settingsObject[]建立時同步寫入的 AIFF 設定列表(可選)

更新請求 OpenApiAiffUpdateRequestDto

欄位型別必填說明
integrationIdString租戶安裝例項 ID
extraIdString外部應用唯一識別
nameStringAIFF 應用名稱
descriptionStringAIFF 應用描述
pictureUrlStringAIFF 主資料圖片地址
settingsObject[]更新時同步維護的 AIFF 設定列表(可選)

刪除請求:

{
"integrationId": "ti_xxxxx",
"extraId": "your-app-id"
}

刪除主資料時會連帶刪除該 AIFF 下的所有設定。

Setting 子結構 OpenApiAiffSettingRequestDto

每個 setting 對應一組前端展示配置,可在建立/更新 AIFF 時一併提交。

欄位型別必填說明
idString既有設定 ID(更新既有設定時使用)
extraKeyString外部設定唯一識別
displayNameString前端展示名稱
pictureUrlString設定級別圖片地址。未傳時查詢返回回退外層主資料 pictureUrl
serviceNumberIdsString[]設定生效的服務號 ID 列表
displayTypeString顯示型別,見下表
roomTypeString[]聊天室型別列表(僅 displayType=Room 時生效),見下表
displayLocationString嵌入位置(僅 displayType=Room 時生效),見下表
endPointUrlStringAIFF 跳轉目標地址
supportDeviceString支援裝置型別,見下表
popupSizeString彈窗尺寸,見下表

displayType 列舉值:

說明
Frame主框架
AppList應用列表
Room聊天室內嵌(此時需設定 roomType + displayLocation
ContactIndex客戶主頁

roomType 列舉值(可多選):

說明
One單人聊天室
Person個人聊天室
Friend好友聊天室
System系統聊天室
Discuss多人聊天室
Group社團聊天室
GroupOwner社團聊天室(擁有者)
BusinessCustomer商務號聊天室(客戶角度)
BusinessEmployee商務號聊天室(員工角度)
BusinessSecretary商務號秘書群聊天室
ServiceNumberCustomer服務號聊天室(客戶角度)
ServiceNumberEmployee服務號聊天室(員工角度)
ServiceNumberAgent服務號聊天室(服務人員角度)
ServiceNumberGroup服務號群內聊天室
Object物件聊天室

displayLocation 列舉值:

說明
Toolbar工具列
Extend擴充套件欄位
Embed下沉式(內嵌)
MessageMenu訊息選單

supportDevice 列舉值:

說明
Desktop桌面端
Mobile手機端

popupSize 列舉值:

說明
Full全螢幕
Half半螢幕

詳情響應 data 結構 OpenApiAiffVO

{
"id": "aiff-xxx",
"extraId": "your-app-id",
"tenantId": "T001",
"name": "外部應用名稱",
"description": "應用描述",
"pictureUrl": "https://example.com/image.png",
"settings": [
{
"id": "setting-001",
"extraId": "your-app-id",
"extraKey": "setting-key-1",
"displayName": "設定顯示名稱",
"pictureUrl": "https://example.com/setting-icon.png",
"endPointUrl": "https://example.com/aiff",
"serviceNumberIds": ["SN001", "SN002"],
"aiffId": "aiff-xxx"
}
]
}

重要說明:

  1. 圖片處理pictureUrl 僅做字串透傳與儲存,不下載圖片、不上傳附件。setting 未傳 pictureUrl 時,寫入階段不自動補外層值,僅查詢返回時回退外層主資料圖片
  2. icon 檔案上傳:OpenAPI 僅承接結構化資料,不承接 icon 檔案上傳(內部 job 服務的 multipart/form-data icon 欄位在 OpenAPI 鏈路中固定為空)
  3. setting 定位:更新時依 extraKey 定位既有 setting;若未傳可識別的標識,更新行為依賴既有業務約束
  4. 刪除級聯:刪除 AIFF 主資料時會一併刪除該 extraId 下所有 setting

6.3.8 API 目錄(自動發現)

方法路徑說明
POST/catalog/v1/business-objects查詢業務物件清單
POST/catalog/v1/sync-resources查詢支援同步的資源清單
POST/catalog/v1/event-types查詢支援的事件型別清單
POST/catalog/v1/event-scopes查詢支援的事件資源域清單

所有目錄端點請求格式相同:

{
"integrationId": "ti_xxxxx"
}

6.3.9 傳送訊息

v2.1 新增功能。 供外部整合應用向指定聊天室傳送訊息。

方法路徑說明
POST/messages/v1/send傳送訊息到指定聊天室

功能範圍:

  • 當前穩定支援的訊息型別:Text(文字訊息)、Template(模板訊息 / 卡片訊息)
  • 不支援 ImageFileVideoAudioVoiceSticker 等需附件契約的型別(會返回請求非法)
  • 支援 5 種接收目標路由:RoomSystemUserServiceNumberServiceMember
  • 支援 3 種傳送者身份:System(系統訊息)、User(以使用者身份傳送)、ServiceNumber(以服務號身份傳送)
  • 可透過 sourceType 控制單條訊息的顯示方式(System / User / Assistant

請求 DTO 結構:

頂層請求 OpenApiMessageSendRequestDto

欄位型別必填說明
integrationIdString租戶安裝例項 ID
senderObject傳送者資料,見下表
toObject接收者資料,見下表
messagesObject[]訊息列表(至少 1 條),見下表

傳送者 OpenApiMessageSenderDto

欄位型別必填說明
typeString傳送者型別:System / User / ServiceNumber
userTypeString使用者型別:Employee / Contact(type=User 時使用,預設為 Employee)
codeStringopenId 或服務號代號(type 非 System 時必填)
incomingString進線標記(可選)

接收者 OpenApiMessageReceiverDto

欄位型別必填說明
typeString接收目標型別:Room / System / User / ServiceNumber / ServiceMember
userTypeString使用者型別:Employee / Contact / Visitor(type=User 時使用)
codeString接收者代號(openId 或 roomId)
serviceNumberIdString服務號 ID(type=ServiceNumber/ServiceMember 時使用)
channelTypeString指定渠道:Line / Facebook / Webchat / Aiwow

單條訊息 OpenApiMessageItemDto

欄位型別必填說明
typeString訊息型別:Text / Template
altTextString替代文字(渠道不支援時的降級顯示)
sourceTypeString訊息來源型別:User / System / Assistant / Broadcast。未傳時按 sender.type 推導:System→System,其餘→User
contentObject訊息內容,見下表

訊息內容 OpenApiMessageContentDto

欄位型別必填說明
typeString模板型別(訊息為 Template 時使用):Buttons / Confirm / Process / Carousel
titleString標題
textString文字內容(Text 訊息的主體;Template 訊息的內文)
imageUrlString圖片網址(Template 訊息使用)
orientationString內容方向:Vertical(垂直)/ Horizontal(水平)
defaultActionObject預設動作(點選整張卡片的行為),結構:{ type, label, url }
actionsObject[]互動動作列表(按鈕等),每項結構同上

動作型別(defaultAction / actions[].type):

說明
Action前端本地行為
Postback提交到後端的回傳行為
Url前端開啟外部連結
Aiff前端開啟 Aiff 容器

響應格式:

{
"code": 200,
"message": "success",
"data": [
{
"id": "message-xxx",
"roomId": "room-001",
"tenantId": "T001",
"type": "Text",
"content": { "text": "Hello" },
"senderId": "U001",
"createdAt": "2026-06-23T10:30:00Z"
}
]
}

訊息路由規則說明:

傳送訊息時,系統根據 to.typesender.type 的組合決定最終的目標聊天室:

to.typesender.type路由邏輯
Room任意直接使用 to.code 作為 roomId
System任意透過 to.code(員工 openId)定位員工的系統聊天室
UserSystem以接收者 openId 定位其系統聊天室(系統通知場景)
UserUser(同一個 openId)查詢該使用者的個人聊天室
UserUser(不同 openId)查詢傳送者的好友聊天室(非好友則報錯)
UserServiceNumber查詢服務號擁有者與目標使用者的好友聊天室
ServiceNumber任意查詢指定服務號與指定客戶的服務號聊天室
ServiceMember任意查詢指定服務號的服務成員聊天室

6.3.10 建立並傳送服務廣播

v2.1 新增功能。 供外部整合應用建立並傳送服務號廣播(群發),內部走 tenant 服務既有廣播建立流程。

方法路徑說明
POST/messages/v1/broadcast/create建立並傳送服務廣播

請求 DTO 結構 OpenApiBroadcastCreateRequestDto

欄位型別必填說明
integrationIdString租戶安裝例項 ID
openIdString本次建立廣播的員工 OpenID(用以解析建立者身份)
serviceNumberIdString目標服務號 ID
nameString廣播任務標題
remarkString廣播備註
channelString廣播頻道:Line / Facebook / Webchat / Aiwow
contentObject[]廣播內容列表,每個元素為 BroadcastBody
broadcastTimeLong預約廣播時間(Unix 毫秒時間戳),不填則立即傳送
labelIdsString[]標籤匹配範圍(以標籤篩選目標客戶)
customerIdsString[]指定廣播目標客戶 ID 列表
matchLogicString標籤匹配邏輯:OR(滿足任一)/ AND(全部滿足)

廣播內容 BroadcastBody

欄位型別必填說明
indexInteger順序編號
typeString訊息型別(廣播支援:Text / Image / File / Template
contentString訊息內容(與既有服務號廣播格式一致)

響應格式:

{
"code": 200,
"message": "success",
"data": {
"id": "broadcast-xxx",
"serviceNumberId": "SN001",
"name": "節日推廣",
"status": "Doing",
"createdAt": "2026-06-23T10:30:00Z"
}
}

重要說明:

  1. 建立者身份校驗openId 必須對應一個存在於當前安裝例項租戶中的員工,否則請求失敗
  2. 標籤與客戶篩選labelIdscustomerIds 都可選;若均不填,廣播目標將為空
  3. 立即 vs 預約:不填 broadcastTime 則立即嘗試傳送;填寫未來時間則排程傳送
  4. 廣播狀態:建立成功後狀態為 Doing,由 tenant 既有流程觸發下游廣播傳送;傳送完成後狀態變更為 Done
  5. 許可權控制integration 服務會臨時建立 AileContext(含 tenantId + accountId + employeeId),完成後恢復原上下文,保證執行緒池安全

7. Webhook 事件推送(Aile → 第三方)

7.1 推送機制

  • 方向: Aile → 第三方平臺
  • 協議: HTTP POST
  • 目標地址: TenantIntegration.webhookUrl
  • 內容型別: application/json
  • 簽名: HMAC-SHA256(使用 appSecret,簽名規則同 OpenAPI)
  • 冪等性: 透過 eventId 保證,重複推送同一 eventId 應返回成功

7.2 事件信封格式 (EventEnvelope)

{
"eventId": "evt_abc123",
"eventType": "contact.created",
"eventVersion": "v1",
"occurredAt": "2026-06-16T10:30:00Z",
"source": "aile-tenant",
"integration": {
"appId": "your-app-id",
"integrationId": "ti_xxxxx"
},
"tenant": {
"tenantId": "T001",
"externalTenantId": "EXT-12345",
"tenantType": "enterprise"
},
"scope": {
"serviceNumberId": "SN001",
"entrySourceId": "line_channel_123"
},
"data": {
"contactId": "C001",
"name": "張三",
"channel": "Line",
"scopeId": "Uxxx_line_id"
},
"metadata": {
"traceId": "trace_001",
"retryCount": 0
}
}

7.3 事件分發規則

  1. 狀態過濾: 僅向 status=Active 的安裝例項推送
  2. 事件過濾: 僅推送安裝例項 subscribedEvents 中訂閱的事件資源域
  3. 安裝隔離: 一個安裝例項推送失敗不影響其他安裝例項
  4. 重試機制: 推送失敗時進行重試,透過 metadata.retryCount 記錄

8. 事件資源域與事件型別參考

8.1 事件資源域(subscription scope codes)

用於 supportedEventssubscribedEvents 的訂閱值:

資源域程式碼說明
tenant.*租戶事件
user.*使用者事件
service_number.*服務號事件
contact.*聯絡人(客戶)事件
visitor.*訪客事件
group.*群組事件
addressbook.*通訊錄事件
notice.*通知事件
session.*會話事件

8.2 目前已實現的事件型別

以下事件型別在 aile-service-tenant 中已實作並自動釋出:

事件型別資源域說明
service_number.createdservice_number.*服務號建立
service_number.updatedservice_number.*服務號更新
service_number.deletedservice_number.*服務號刪除
contact.createdcontact.*聯絡人建立
contact.updatedcontact.*聯絡人更新
contact.deletedcontact.*聯絡人刪除
contact.service_number_unfollowedcontact.*聯絡人取消追蹤服務號
visitor.mergedvisitor.*匿名訪客合併為實名
employee.disabledemployee.disabled員工停用
tenant.disabledtenant.*租戶停用

注意: 當前事件推送機制(InternalEvent → Pub/Sub → Webhook HTTP)中,Pub/Sub 釋出已實現,但 Webhook HTTP 投遞層目前正在規劃中。具體可用性請與 Aile 團隊確認。


9. 接入實戰指南(第三方開發步驟)

9.1 前置準備

  1. 聯絡 Aile 管理員,取得:
    • appId(你的應用識別碼)
    • Aile API Base URL(例如 https://api.aile.com
  2. 準備你的伺服器端點:
    • 安裝介面:POST /your-platform/api/aile/install
    • 更新介面:POST /your-platform/api/aile/update
    • 輪換金鑰介面:POST /your-platform/api/aile/rotate
    • 解除安裝介面:POST /your-platform/api/aile/uninstall
    • Webhook 接收介面:POST /your-platform/webhook/events

9.2 第一步:實現安裝介面

Aile 呼叫 installUrl 時,你的介面需要:

  1. 接收引數並儲存關鍵資訊(特別是 appSecretintegrationId
  2. 為這個安裝建立 externalTenantId(你的系統中對應的租戶 ID)
  3. 確定你的 Webhook 接收地址
  4. 決定訂閱哪些事件資源域

示例(Node.js / Express):

app.post('/api/aile/install', (req, res) => {
const { integrationId, appId, tenantId, tenantType, appSecret,
installationCallbackUrl, subscribedEvents } = req.body;

// 儲存安裝資訊到你的資料庫
db.installations.save({
integrationId,
appId,
tenantId,
tenantType,
appSecret, // 重要:後續所有 OpenAPI 呼叫都需要
installationCallbackUrl,
subscribedEvents,
externalTenantId: `ext_${tenantId}`,
webhookUrl: 'https://your-platform.com/webhook/events',
status: 'Active'
});

// 同步模式直接返回成功
res.json({
status: 'Active',
externalTenantId: `ext_${tenantId}`,
webhookUrl: 'https://your-platform.com/webhook/events',
subscribedEvents: ['contact.*', 'service_number.*']
});
});

9.3 第二步:實現 OpenAPI 呼叫

使用儲存的 appSecretintegrationId,透過 HMAC 簽名呼叫 Aile API。

// 查詢租戶資訊
const result = await callAileOpenApi(
integrationId, appSecret,
'POST',
'/tenants/v1/me',
{ integrationId }
);

// 查詢服務號列表
const services = await callAileOpenApi(
integrationId, appSecret,
'POST',
'/service-numbers/v1/list',
{ integrationId, current: 1, size: 20 }
);

// 查詢聯絡人列表
const contacts = await callAileOpenApi(
integrationId, appSecret,
'POST',
'/contacts/v1/list',
{ integrationId, serviceNumberId: 'SN001', current: 1, size: 20 }
);

9.4 第三步:實現 Webhook 接收

接收 Aile 推送的業務事件:

app.post('/webhook/events', (req, res) => {
const event = req.body;

// 冪等檢查:避免重複處理同一事件
if (alreadyProcessed(event.eventId)) {
return res.json({ success: true, duplicated: true });
}

// 根據事件型別進行業務處理
switch (event.eventType) {
case 'contact.created':
handleContactCreated(event.data);
break;
case 'contact.updated':
handleContactUpdated(event.data);
break;
case 'service_number.created':
handleServiceNumberCreated(event.data);
break;
// ... 更多事件型別
}

markAsProcessed(event.eventId);
res.json({ success: true, duplicated: false });
});

9.5 第四步:實現更新 / 輪換 / 解除安裝

app.post('/api/aile/update', (req, res) => {
const { integrationId, webhookUrl, subscribedEvents } = req.body;
db.installations.update(integrationId, { webhookUrl, subscribedEvents });
res.json({ status: 'Active' });
});

app.post('/api/aile/rotate', (req, res) => {
const { integrationId, operatorId } = req.body;
// 更新 appSecret(Aile 端會生成新金鑰,這裡接收通知)
res.json({ status: 'Active' });
});

app.post('/api/aile/uninstall', (req, res) => {
const { integrationId } = req.body;
db.installations.update(integrationId, { status: 'Deleted' });
res.json({ status: 'Deleted' });
});

9.6 重要注意事項

  1. 所有 OpenAPI 請求都是 POST: 包括查詢請求也使用 POST 方法
  2. 請求體必須包含 integrationId: 且必須與簽名中的 integrationId 一致
  3. Nonce 必須唯一: 建議使用 nonce_{timestamp} 格式
  4. empty body 處理: 無請求體時,bodyString 為空字串 "",簽名使用 integrationId + nonce + ""
  5. 響應格式: Aile 統一返回 { code: 200, message: "success", data: {...} }
  6. HTTPS 強制: 所有 API 通訊必須使用 HTTPS

10. 參考實現:Simulator 模擬服務

integration-third-party-simulator 是一個完整的第三方模擬服務,可用於本地開發聯調。

10.1 啟動方式

cd integration-third-party-simulator
cp .env.example .env
npm install
npm start

預設埠:3301

10.2 關鍵配置(.env)

PORT=3301
INSTALL_MODE=sync # sync 或 async
ASYNC_CALLBACK_DELAY_MS=200 # 非同步回撥延遲
ASYNC_FINAL_STATUS=Active # 非同步最終狀態
DEFAULT_WEBHOOK_BASE_URL=http://localhost:3301
AILE_OPENAPI_BASE_URL=http://localhost:8080 # Aile 服務地址

10.3 模擬服務介面

控制面(第三方平臺端,接收 Aile 請求):

# 安裝
curl -X POST http://localhost:3301/control-plane/install \
-H "Content-Type: application/json" \
-d '{
"integrationId": "ti_001",
"appId": "aipower",
"tenantId": "tenant_001",
"tenantType": "PERSONAL",
"appSecret": "secret_001",
"installationCallbackUrl": "http://localhost:8080/integration/tenant/open/v1/install/callback",
"subscribedEvents": ["contact.*"]
}'

# 更新
curl -X POST http://localhost:3301/control-plane/update \
-H "Content-Type: application/json" \
-d '{"integrationId": "ti_001", "webhookUrl": "https://new.example.com/webhook"}'

# 解除安裝
curl -X POST http://localhost:3301/control-plane/uninstall \
-H "Content-Type: application/json" \
-d '{"integrationId": "ti_001"}'

除錯介面:

# 檢視所有安裝
curl http://localhost:3301/debug/installations

# 檢視所有 Webhook 事件
curl http://localhost:3301/debug/webhooks

# 以安裝例項身份觸發 OpenAPI 呼叫
curl -X POST http://localhost:3301/debug/installations/ti_001/openapi/invoke \
-H "Content-Type: application/json" \
-d '{"method": "POST", "path": "/tenants/v1/me"}'

10.4 聯調建議

  1. IntegrationApp.installUrl 指向 http://localhost:3301/control-plane/install
  2. 先用 INSTALL_MODE=sync 打通主鏈路
  3. 再切 async 驗證回撥分支
  4. 確保 AILE_OPENAPI_BASE_URL 指向可訪問的 Aile 環境

11. 常見問題與錯誤碼

11.1 常見錯誤碼

錯誤碼說明解決建議
FAIL_OPENAPI_AUTH_HEADER_REQUIRED缺少 Authorization 或 X-Aile-Nonce 頭檢查請求頭是否正確傳遞
FAIL_OPENAPI_SIGNATURE_INVALID簽名驗證失敗檢查簽名演算法(integrationId+nonce+body),確認 appSecret 正確
FAIL_OPENAPI_INTEGRATION_NOT_FOUND安裝例項不存在或未啟用檢查 integrationId 是否正確,安裝狀態是否為 Active
FAIL_OPENAPI_INTEGRATION_DISABLED安裝例項已停用聯絡 Aile 管理員確認安裝狀態
FAIL_TENANT_INTEGRATION_NOT_FOUND資料許可權校驗失敗確認查詢的服務號或聯絡人是否屬於當前租戶
FAIL_INTEGRATION_APP_NOT_FOUND應用定義不存在或已下架聯絡 Aile 管理員確認應用狀態

11.2 FAQ

Q: 簽名驗證一直失敗?

A: 請確認簽名內容為 integrationId + nonce + bodyString注意不是 method + path + nonce + body)。bodyString 為原始 JSON 字串,無 body 時為空字串。

Q: Authorization 頭格式?

A: 格式為 AILE {integrationId}:{signature},例如 AILE ti_001:abc123...

Q: 查詢請求使用 GET 還是 POST?

A: 所有 OpenAPI 端點均使用 POST 方法(含查詢請求),請求體為 JSON。

Q: 如何判斷安裝是否為 Async 模式?

A: 檢視請求中的 installAckMode 欄位。Sync 表示同步完成(直接返回狀態),Async 表示先受理再回撥。

Q: 第三方需要實現哪些介面?

A: 至少需要實現 installUrl(安裝),建議也實現 updateUrluninstallUrl;Webhook 接收介面用於接收事件。


附錄 A:關鍵檔案索引

層級檔案路徑說明
應用定義模型aile-api/aile-integration-api/.../model/IntegrationAppModel.javaIntegrationApp 持久化模型
安裝例項模型aile-api/aile-integration-api/.../model/TenantIntegrationModel.javaTenantIntegration 持久化模型
事件信封 DTOaile-api/aile-integration-api/.../dto/event/EventEnvelopeDto.java對外事件格式
安裝請求 DTOaile-api/aile-integration-api/.../dto/control/InstallationRequestDto.java安裝請求引數
安裝響應 DTOaile-api/aile-integration-api/.../dto/control/InstallationResponse.java第三方安裝響應
回撥請求 DTOaile-api/aile-integration-api/.../dto/control/InstallationCallbackRequestDto.java非同步回撥引數
事件資源域列舉aile-api/aile-integration-api/.../enums/IntegrationEventScopeType.java9 個事件資源域定義
安裝狀態列舉aile-api/aile-integration-api/.../enums/TenantIntegrationStatus.java6 種安裝狀態
HMAC 簽名校驗器aile-service/aile-service-integration/.../service/impl/IntegrationOpenApiSignatureVerifier.java入站簽名校驗實現
OpenAPI 過濾器aile-service/aile-service-integration/.../config/IntegrationOpenApiSignatureFilter.java請求攔截過濾器
訪問驗證器aile-service/aile-service-integration/.../service/impl/IntegrationOpenApiAccessValidator.java安裝狀態與資料許可權校驗
OpenAPI 服務aile-service/aile-service-integration/.../service/impl/IntegrationOpenApiServiceImpl.javaOpenAPI 業務邏輯
安裝控制器aile-service/aile-service-integration/.../controller/TenantIntegrationController.java安裝 API 端點
應用控制器aile-service/aile-service-integration/.../controller/IntegrationAppController.java應用管理 API 端點
事件型別常量aile-service/aile-service-tenant/.../constants/TenantIntegrationEventTypes.java已實現的業務事件型別
Simulator 簽名integration-third-party-simulator/src/utils/signature.js簽名實現參考
Simulator 安裝integration-third-party-simulator/src/services/installationService.js安裝流程參考
訊息傳送 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiMessageSendRequestDto.java訊息傳送請求
訊息接收者 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiMessageReceiverDto.java接收目標定義
訊息傳送者 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiMessageSenderDto.java傳送者身份定義
訊息內容 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiMessageContentDto.java訊息內容結構
訊息條目 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiMessageItemDto.java單條訊息結構
廣播請求 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiBroadcastCreateRequestDto.java廣播建立請求
廣播內容 DTOaile-api/aile-tenant-api/.../model/servicenumber/BroadcastBody.java廣播訊息體
訊息控制器aile-service/aile-service-integration/.../controller/IntegrationOpenApiMessageController.java訊息與廣播 API 端點
訊息服務實現aile-service/aile-service-integration/.../service/impl/IntegrationOpenApiMessageServiceImpl.java訊息傳送與廣播業務邏輯
AIFF 建立 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiAiffCreateRequestDto.javaAIFF 建立請求
AIFF 更新 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiAiffUpdateRequestDto.javaAIFF 更新請求
AIFF 刪除 DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiAiffDeleteRequestDto.javaAIFF 刪除請求
AIFF Setting DTOaile-api/aile-integration-api/.../dto/openapi/OpenApiAiffSettingRequestDto.javaAIFF 設定請求
AIFF 控制器aile-service/aile-service-integration/.../controller/IntegrationOpenApiAiffController.javaAIFF CRUD API 端點
RoomTypeEnumaile-api/aile-job-api/.../aiff/enums/RoomTypeEnum.java15 種聊天室型別
DisplayTypeEnumaile-api/aile-job-api/.../aiff/enums/DisplayTypeEnum.java4 種顯示型別
AiffModelaile-api/aile-job-api/.../aiff/model/AiffModel.javaAIFF 主資料模型(含 pictureUrl)

附錄 B:版本變更記錄

版本日期變更
v2.2+2026-06-25在 v2.2 AIFF 規格基礎上補充 release 變更:OpenAPI 路徑由 /integration/openapi/v1/<資源> 重構為 /<資源>/v1/<動作>;所有端點統一 POST;HMAC 簽名公式確認為 integrationId + nonce + body;Authorization 字首改為 AILE;同步更新 AIFF 寫入、訊息傳送、群發廣播與事件資源域/事件型別說明。
v2.22026-06-24AIFF 章節全面重寫:新增 create / update / delete 寫介面完整規格;補充 pictureUrl 圖片支援說明(主資料級 + setting 級);補齊 5 組列舉表(displayType / roomType 15 種 / displayLocation / supportDevice / popupSize);新增 setting 子結構 DTO 與詳情響應;更新附錄 A
v2.12026-06-23新增 6.3.9 傳送訊息 API 完整規格 + 6.3.10 廣播 API 完整規格;更新架構全景圖;更新附錄 A 檔案索引
v2.02026-06-16基於 release 分支最新程式碼重寫;修正 HMAC 簽名演算法文件;補充 10 個 OpenAPI 控制器細節;增加目錄章節
v1.02026-06-13初版