Webhook 簡介說明
概述
透過 Webhook 將可以接收來自 KKTIX 的訂單資訊,並依此設定相關自動化操作進行個別行為觸發。例如:當有新的訂單成立並付款時,Webhook 可以自動通知你的系統進行更新、發送通知或執行其他流程。
因應可能出現的高峰使用情境,Webhook 並不會針對每筆訂單即時傳送通知。KKTIX 會定期批次發送 POST Request,頻率與批次大小將依訂單的成立或取消的速度與數量動態調整。此設計旨在降低對串接服務的請求頻率,避免對系統造成過高負載,同時確保資料傳輸的效率與穩定性。
資料傳輸規範
為確保資料傳輸的安全性,Webhook 僅支援透過 HTTPS 協定進行,並實施以下限制與檢查:
- 僅支援 HTTPS:所有串接請求必須使用 HTTPS 協定,以確保傳輸資料的加密性與完整性
- 憑證驗證:系統將檢查傳輸過程中的憑證,以確保使用有效的 SSL/TLS 憑證
- 最低版本限制:傳輸協定要求使用 TLS 1.2 或以上版本,以滿足安全標準
請確保串接系統已符合上述規範,以避免影響 Webhook 功能的正常使用。
權限管理
當活動成員的角色具備「編輯活動」權限,則可針對 Webhook 進行設定,包括新增、編輯與刪除。
重試與自動停用機制
重試機制
- 當 Webhook 發送失敗時,系統將每 5 分鐘自動重試一次
- 系統最多重試 3 次,若重試 3 次仍然失敗,則:
- 該筆請求將標記為「失敗請求」
- 系統將發送 Webhook 傳送失敗通知信予活動管理者(Admin)
- 失敗請求將記錄於 「活動主控台 > 系統串接設定 > 發送失敗紀錄」 頁面
- 當活動管理者(Admin)收到通知信後,請盡快檢查相關串接服務設定,以避免發生更多錯誤
自動停用機制
- 當 Webhook request 第一次發送失敗時,系統開始計算 20 分鐘的觀察期
- 若 20 分鐘內所有 request 都失敗,則記錄「1 次失敗」
- 當 20 分鐘後有新的 Webhook request 失敗時,才會重新開始計算 20 分鐘的觀察期
- 當累計 3 次失敗(亦即連續 3 個 20 分鐘都沒有成功請求),則系統將:
- 自動停用 Webhook,避免影響後續發送
- 發送 Webhook 暫時停用通知信予活動管理者(Admin)
- 只要有一次成功發送,或是使用者手動關閉再開啟 Webhook,則累計的失敗次數歸零重計
- 當活動管理者(Admin)收到通知信後,請盡快檢查相關串接服務設定,並至「活動主控台 > 系統串接設定」頁面重新啟用 Webhook 服務,以確保資料傳送的完整性
Webhook 設定說明
建立 Webhook
你可以依據需求為特定活動建立 Webhook,且一個活動僅可設定一組 Webhook URL。
於「活動主控台 > 系統串接設定」點擊「建立 Webhook」,設定資料詳述如下
1. Auth header name, Auth header value
當系統發送 Webhook 請求時,為確保接收方能驗證這個請求是來自於可信任的系統,我們會在 HTTP Header 中加入一組認證資訊。[*註 1]
- Auth header name 限制
- 不得為空值,且長度不得大於 128 字元
- 不得包含 header 保留字,保留字包括:cookie, authorization, content-type, content-length, user-agent, x-forwarded-for
- 不得包含 non-ascii 字元,例如:é, ç, ü, ñ
- Auth header value 限制
- 不得為空值,且長度不得大於 512 字元
- 不得包含 non-ascii 字元,例如:é, ç, ü, ñ
*註 1:若無需使用 Auth header 進行驗證者,可選擇不填寫相關欄位
2. Webhook URL
用來接收 KKTIX 傳送的 POST request 的 URL 位置。
3. Event Type
KKTIX 目前具備以下事件類型供使用者選擇,系統將於特定訂單狀態時觸發 Webhook 傳送事件:
| 事件類型 | 觸發時機 |
| 訂單成立(order_activated_paid) | 訂單成立並完成付款時 |
| 訂單取消(order_cancelled) | 訂單被取消時 |
測試 Webhook
以上資訊填寫完成後,即可點擊「測試 Webhook URL」進行 Webhook URL 測試。
進行 Webhook URL 測試時,系統將固定發送以下測試用 payload body:
{
"notifications": [
{
"type": "order_activated_paid",
"event": {
"name": "Event Name",
"slug": "event-slug"
},
"order": {
"id": 123,
"status": "activated",
"created_at": "2024-12-25 12:00:00",
"payment_status": "paid",
"paid_at": "2024-12-25 12:30:00",
"total_amount": 4000,
"currency": "TWD"
},
"contact": {
"name": "User_1",
"email": "user_1@example.com"
},
"tickets": [
{
"price": 1000,
"name": "normal",
"id": 12,
"attendee": {
"name": "User_1",
"email": "user_1@example.com"
}
},
{
"price": 1500,
"name": "normal",
"id": 13,
"attendee": {
"name": "User_2",
"email": "user_2@example.com"
}
},
{
"price": 1500,
"name": "normal",
"id": 14,
"attendee": {
"name": "User_3",
"email": "user_3@example.com"
}
}
]
},
{
"type": "order_cancelled",
"event": {
"name": "Event Name",
"slug": "event-slug"
},
"order": {
"id": 123,
"status": "cancelled",
"cancelled_at": "2024-12-25 13:00:00"
}
}
]
}
發送測試 request 後,回傳結果將顯示於 Console Message 中,並以 "status code 200" 作為是否
成功的判別依據:
- 當 status code 為 200 時,即可儲存並啟用 Webhook
- 當 status code 為非 200 時,則無法儲存並啟用 Webhook
Webhook 資料欄位說明
範例
系統每隔 1 分鐘將在此期間產生的多筆訂單資料進行彙整後以 HTTP POST 的方式傳送至指定 Webhook URL,其中 notifications[].contact 及 notifications[].tickets[].attendee 中的欄位項目將依據活動報名表單設定欄位顯示 [*註 2]。payload body 範例如下
{
"notifications": [
{
"type": "order_activated_paid",
"event": {
"name": "Event Name",
"slug": "event-slug"
},
"order": {
"id": 123,
"status": "activated",
"created_at": "2024-12-25 12:00:00",
"payment_status": "paid",
"paid_at": "2024-12-25 12:30:00",
"total_amount": 4000,
"currency": "TWD"
},
"contact": {
"name": "User_1",
"email": "user_1@example.com"
},
"tickets": [
{
"price": 1000,
"name": "normal",
"id": 12,
"attendee": {
"name": "User_1",
"email": "user_1@example.com"
}
},
{
"price": 1500,
"name": "normal",
"id": 13,
"attendee": {
"name": "User_2",
"email": "user_2@example.com"
}
},
{
"price": 1500,
"name": "normal",
"id": 14,
"attendee": {
"name": "User_3",
"email": "user_3@example.com"
}
}
]
},
{
"type": "order_cancelled",
"event": {
"name": "Event Name",
"slug": "event-slug"
},
"order": {
"id": 123,
"status": "cancelled",
"cancelled_at": "2024-12-25 13:00:00"
}
}
]
}
*註 2:欄位類型「多行文字」、「說明文字」、「檔案上傳」不會透過 Webhook 傳送
參數說明
type
| 屬性 | 型別 | 說明 |
| type | string |
Webhook Event Type |
event
| 屬性 | 型別 |
說明 |
| name | string |
活動名稱 |
| slug | string |
活動 slug |
order
| 屬性 | 型別 |
說明 |
| id | number |
訂單編號 |
| status |
string |
訂單狀態 |
| created_at | string |
訂單建立時間 |
| payment_status | string |
付款狀態 |
| paid_at | string |
訂單付款時間 |
| cancelled_at | string |
訂單取消時間 |
| total_amount | number |
訂單金額 |
| currency | string |
幣別 |
contact
| 屬性 | 型別 |
說明 |
| name | string |
聯絡人姓名 |
| string |
聯絡人 Email |
|
| idnumber | string |
聯絡人身分證字號 |
| mobile | string |
聯絡人手機 |
| phone | string |
聯絡人聯絡電話 |
| zipcode | string |
聯絡人郵遞區號 |
| address | string |
聯絡人地址 |
tickets
| 屬性 | 型別 |
說明 |
| price | number |
票券金額 |
| name | string |
票券名稱 |
| id | string |
票券編號(票號) |
attendee
| 屬性 | 型別 |
說明 |
| name | string |
報名人姓名 |
| string |
報名人 Email |
|
| idnumber | string |
報名人身分證字號 |
| mobile | string |
報名人手機 |
| phone | string |
報名人聯絡電話 |
| zipcode | string |
報名人郵遞區號 |
| address | string |
報名人地址 |
| nickname | string |
報名人暱稱 |
| company_name | string |
報名人公司 / 組織名稱 |
| company_title | string |
報名人職稱 |
| company_address | string |
報名人公司地址 |
| company_phone | string |
報名人公司電話 |
報名表單 Webhook Key Name
Webhook 傳送活動報名資料時,每個欄位都會對應一個 Key Name,用於識別該欄位的內容。
依據欄位類型,Webhook Key Name 的設定方式如下
1. 固定欄位
對於非自訂的預設欄位(例如:姓名、email 等既有欄位),系統會使用固定的 Webhook Key Name:
| 欄位名稱 | Webhook Key Name |
| 姓名 / Name | name |
| Email / Email | |
| 身分證字號 / ID Number | idnumber |
| 手機 / Mobile | mobile |
| 聯絡電話 / Phone | phone |
| 郵遞區號 / Zip Code | zipcode |
| 地址 / Address | address |
| 暱稱 / Nickname | nickname |
| 公司 / 組織名稱 / Company / Organization Name | company_name |
| 職稱 / Job Title | position_title |
| 公司地址 / Company Address | company_address |
| 公司電話 / Company Phone | company_phone |
2. 自訂欄位
對於使用者自訂的欄位,Key Name 則可由使用者至「活動主控台 > 報名表單」自行設定。
使用者可以在建立或編輯自訂欄位時,輸入合適的 Webhook Key Name,且必須符合以下限制
- 字元限制:僅可使用英文字母(大小寫不限)、數字以及底線(_),不支援其他特殊符號或空格
- 長度限制:最多 32 個字元
若自訂欄位未自行設定 Webhook Key Name,則將以系統預設進行傳送。
範例如下:
{
"notifications": [
{
"type": "order_activated_paid",
"event": {
"name": "Event Name",
"slug": "event-slug"
},
"order": {
"id": 123,
"status": "activated",
"created_at": "2024-12-25 12:00:00",
"payment_status": "paid",
"paid_at": "2024-12-25 12:30:00",
"total_amount": 4000,
"currency": "TWD"
},
"contact": {
"name": "User_1",
"email": "user_1@example.com",
"field_radio_23488": "KKTIX" // 自訂欄位|未設定 Webhook Key Name
},
"tickets": [
{
"price": 1000,
"name": "normal",
"id": 12,
"attendee": {
"name": "User_1",
"email": "user_1@example.com",
"gender": "female" // 自訂欄位|已設定 Webhook Key Name
}
},
{
"price": 1500,
"name": "normal",
"id": 13,
"attendee": {
"name": "User_2",
"email": "user_2@example.com",
"gender": "female" // 自訂欄位|已設定 Webhook Key Name
}
},
{
"price": 1500,
"name": "normal",
"id": 14,
"attendee": {
"name": "User_3",
"email": "user_3@example.com",
"gender": "female" // 自訂欄位|已設定 Webhook Key Name
}
}
]
},
{
"type": "order_cancelled",
"event": {
"name": "Event Name",
"slug": "event-slug"
},
"order": {
"id": 123,
"status": "cancelled",
"cancelled_at": "2024-12-25 13:00:00"
}
}
]
}