Instagram · Facebook · Threads
一個 Meta 真的會收的 webhook 網址。
Meta 存檔前會先檢查 callback URL,之後若沒人接收,36 小時就不再試。AnyHook 替你回那個檢查、把每個事件存下來,並且在 Meta 放棄之後繼續重試你的 handler。
時序問題
Meta 會對你的 callback URL 打一個 GET,帶著 hub.mode=subscribe 和一個 challenge,你必須原封不動把 challenge 當成整個回應內容送回去,它才願意存檔。用 tunnel 可以蔑混過一次,但 ngrok 下次給你新網址時,你又得回 App Dashboard 重做一次,而且已經建好的訂閱正指著一個不存在的網址。
事件開始進來之後,期限不是每次請求算,是 36 小時。Meta 在這個窗口內以遞減的頻率重試,之後把沒人接收的丟掉。對自動回覆機器人來說,這個窗口就是「回了留言」跟「根本不知道有這則留言」的差別。
36h
Meta 丟掉未接收通知的期限
1 個網址
同時涵蓋 IG、FB、Threads
GET
AnyHook 替你回的握手
0
tunnel 重啟後要重驗證的次數
把 callback 指到 AnyHook,只驗一個標頭
inbound 網址永遠不變,所以 App Dashboard 只要設一次。AnyHook 在 edge 驗 Meta 的 X-Hub-Signature-256、把事件存下來,再重新簽過 forward 給你的 handler。
// 1. AnyHook 這邊:把 app 的 source 設成 Meta,貼上 App Secret。
// Verify Token 選填。那串字是你自己編的,不是從 Meta 複製來的。
//
// 2. Meta App Dashboard -> Webhooks:
// Callback URL: https://in.anyhook.net/{user-slug}/{app-slug}
// Verify Token: 你剛剛選的同一串
//
// AnyHook 會回 GET 握手,所以網址第一次就存得進去。
import { verifyWebhook } from "anyhook-verify";
export async function POST(req: Request) {
const ok = await verifyWebhook(req, process.env.ANYHOOK_SIGNING_SECRET!);
if (!ok) return new Response("invalid signature", { status: 401 });
const event = await req.json();
const change = event.payload.entry?.[0]?.changes?.[0];
// Meta 已經拿到回應了。這裡要跑多久都行。
if (change?.field === "comments") {
await replyToComment(change.value); // LLM 呼叫,幾秒
}
return new Response("ok", { status: 200 });
}工程團隊常問的問題
- Meta 說我的 callback URL 驗證失敗,為什麼?
- 那個驗證是一個帶著 hub.mode=subscribe 跟 hub.challenge 的 GET,你的網址必須把 challenge 原封不動當成整個 body 送回去,不能包成 JSON、也不能多一個換行。AnyHook 會替你回,所以 inbound 網址第一次就存得進去。如果你在 AnyHook 設了 Verify Token,App Dashboard 那邊要填同一串。
- IG、FB、Threads 要分開設三次嗎?
- 不用。三個走的是同一套 Graph API webhook 契約、同一個 X-Hub-Signature-256 簽章,所以一個 AnyHook app 就涵蓋完。要訂閱哪些事件在 App Dashboard 選。
- 機器人重新部署的時候,留言和私訊會怎樣?
- AnyHook 在事件進來的當下就存起來,再以遞增間隔重試你的端點,所以部署或崩潰不會讓你損失那則訊息。Meta 只看到一次接收成功,就不再管了。
- Verify Token 跟 App Secret 是同一個東西嗎?
- 不是,而且不該填成同一串。App Secret 負責簽每一個 payload,永遠不會出現在網址裡。Verify Token 是你自己編的,它從設定握手的查詢字串進來,而且只用那一次。把 App Secret 放進查詢字串,等於洒進沿途每一份日誌。
改一個 URL,保留你的 Instagram handler。
Free tier 每月含 3,000 events。沒有 SDK、沒有 code 變更,把 Instagram 指到你的 AnyHook inbound URL 就好。