我將 Webhook 文件掉俾 AI 編碼助手,佢直接整咗個跑得起嘅自動回覆機械人 — UnifyPort
你一定熟悉呢套流程。待辦清單上擺住一個訊息整合嘅工作,你冇將文件由頭讀到尾,而係直接打開 Cursor——或者 Claude Code、Windsurf——開始打提示詞。2026 年,大多數人就係咁樣起一個專案。真正嘅問題唔係你識唔識用 AI「氛圍編程」(vibe-coding),而係你對接嗰個 API,有冇俾足夠嘅嘢個助手去將件事做得乾淨。
呢份係開發實錄。睇完你會得到一個跑得起嘅自動回覆機械人:一個 webhook 接收端,對每一條入站訊息驗證簽章,再透過單一嘅傳送端點回覆——大約一個下晝嘅工作量,而且大部分係助手做嘅。佢之所以快,係因為 UnifyPort 嘅 webhook 係正規化嘅:得一種事件結構要學,得一個端點要回呼,助手冇乜好估。
準備:先將文件餵俾助手
最關鍵嗰一步,偏偏係大家最鍾意跳過嘅——喺你開口要程式碼之前,先將 API 文件塞入助手嘅脈絡度。今日有三種行得通嘅做法:
- 直接貼上文件頁。 將
message.received嘅事件結構同POST /v1/messages傳送嗰段原樣貼入對話框。 - 掛載文件。 Cursor 嘅
@Docs、Claude Code 嘅檔案脈絡、Windsurf 嘅文件面板——指向 UnifyPort 嘅介面文件,等助手按需讀取。 - 用文件/MCP 連接器(如果你嘅軟件支援),等助手自己去攞文件。
回報好實在。一個真係讀過事件名嘅助手,唔會憑空整個 onMessage() 處理函式,或者一個根本唔存在嘅 sendText() SDK。佢會照住 message.received 同 POST /v1/messages 嚟寫,因為呢樣就係擺喺佢面前嘅嘢。餵入去嘅係垃圾脈絡,嘔出嚟嘅就係幻覺端點——所以花嗰兩分鐘,將真嘢放入去。
逐條提示詞,將機械人整起嚟
第一條提示詞——接收端:
用我俾你嘅 UnifyPort webhook 文件,寫一個 Express 伺服器,帶一個
POST /webhook路由接收標準事件。先做到:當event係message.received嗰陣,印出from同text。
因為事件結構係固定嘅,處理邏輯就係對一個欄位做分支判斷:
import express from "express";
const app = express();
app.use(express.json());
app.post("/webhook", (req, res) => {
const evt = req.body;
if (evt.event === "message.received") {
console.log(`${evt.provider} ${evt.from}: ${evt.text}`);
}
res.sendStatus(200);
});
app.listen(3000, () => console.log("listening on :3000"));
第二條提示詞——驗證簽章。 呢一步,求其嘅實作會跳過,而讀過文件嘅助手唔會:
每次投遞都用 webhook 嘅
signing_secret做咗 HMAC-SHA256 簽章。喺信任請求主體之前先驗證。要用原始請求主體,並做時間恆定嘅比較。
呢度助手必須做啱嗰一點:HMAC 要計喺原始位元組上,而唔係重新序列化之後嘅 JSON。只要提示寫咗「用原始請求主體」,好嘅助手會接上 express.json 嘅 verify 鉤子嚟捕捉 rawBody。如果佢漏咗,呢個就係你唯一要盯嘅複查點——而且第一次真實投遞回 401 嗰陣你就會發現。
第三條提示詞——透過傳送端點回覆:
當
message.received到達嗰陣,用事件入面嘅account_id同from,透過POST /v1/messages回覆傳送者。驗證用環境變數入面嘅 Bearer API key。
機械人就齊喇。助手最終落定嘅完整檔案:
import express from "express";
import crypto from "crypto";
const { UNIFYPORT_API_KEY, UNIFYPORT_SIGNING_SECRET } = process.env;
const app = express();
app.use(express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } }));
function isValid(req) {
const sig = req.get("x-unifyport-signature") || "";
const expected = crypto
.createHmac("sha256", UNIFYPORT_SIGNING_SECRET)
.update(req.rawBody)
.digest("hex");
return sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
app.post("/webhook", async (req, res) => {
if (!isValid(req)) return res.sendStatus(401);
const evt = req.body;
if (evt.event === "message.received") {
await fetch("https://api.unifyport.ai/v1/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${UNIFYPORT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
account_id: evt.account_id,
to: evt.from,
text: "收到喇!你嘅訊息我哋已經收到,稍後會有專人跟進。",
}),
});
}
res.sendStatus(200);
});
app.listen(3000, () => console.log("listening on :3000"));
跑起嚟,睇一條訊息入嚟
連一個帳號(Telegram 最快上手),註冊一個指向你伺服器嘅 webhook 端點,帶埋 signing_secret 同 subscribed_events: ["message.received"],然後俾你嘅機械人傳一條私訊。事件到達嗰陣係咁樣:
{
"event": "message.received",
"account_id": "acct_8Q2vK",
"provider": "telegram",
"from": "user_3f9c1a",
"text": "請問週末有冇營業?",
"timestamp": 1749427200,
"message_id": "tg_msg_5d2b7e"
}
你嘅伺服器驗證簽章,呼叫 POST /v1/messages,回覆就出現喺對話入面。如果簽章驗證失敗,你會攞到 401——嗰個就係上面講嘅 rawBody 坑。修一次,呢個迴圈就穩。
再擴充
正規化 webhook 嘅價值就係喺度兌現。加第二個平台,唔係再做一次整合——而係零新增處理程式碼。連一個 WhatsApp、LINE 或者 Zalo 帳號,訂閱同一個 webhook,完全一樣嘅 message.received 分支照樣跑,因為事件結構喺唔同平台之間唔會變。provider 欄位話你知訊息邊度嚟,而你程式碼嘅其餘部分根本唔使睇。
想機械人真係去答問題,而唔淨係回一句「收到」?再加一條提示詞就得:「回覆之前,將 text 傳俾一個大型語言模型,用佢嘅回覆做回覆內容。」 傳送呼叫助手已經寫好,你只係將一個字串換成模型嘅輸出。
呢個下晝嘅啟示,唔係「AI 幫你將機械人寫埋」。而係:AI 助手嘅上限,取決於你俾佢對接嗰個介面。一個事件名穩定、得一個傳送端點嘅正規化 webhook,正正係助手可以乾淨收尾嗰種介面——一種結構要學,冇嘢要亂作。將你嘅軟件指向 UnifyPort v1 API,貼入 message.received 嘅結構,你會喺呢個下晝完之前攞到一個識驗證、識回覆嘅機械人——然後將佢放去其餘五個渠道上面。