Webhook
Nhận sự kiện tin đã gửi, đã tới máy, thất bại, mẫu được duyệt… Địa chỉ gốc: https://app.zapro.vn/v1.
ZaPro nhận webhook của Zalo thay bạn (Zalo bắt trả lời trong 2 giây), lưu lại và gửi tới máy chủ của bạn, tự gửi lại trong khoảng 24 giờ nếu chưa nhận được 2xx.
Sự kiện
Quản lý địa chỉ nhận
GET/v1/webhooks
POST/v1/webhooks Body { "url": "https://…", "events": ["message.failed"] }. Trả về secret, chỉ hiện một lần. URL phải là địa chỉ https công khai; ZaPro không gửi tới localhost hay mạng nội bộ, và không đi theo chuyển hướng.
DELETE/v1/webhooks/{id}
Kiểm chữ ký
Mỗi lần gửi có header ZaPro-Signature: t=…,v1=…, trong đó v1 là HMAC-SHA256 của t + "." + body với secret của địa chỉ nhận. Luôn kiểm chữ ký trên body gốc, chưa parse JSON.
import { createHmac, timingSafeEqual } from "node:crypto"; export function verify(rawBody, header, secret) { const parts = Object.fromEntries(header.split(",").map((p) => p.split("="))); const expected = Buffer.from(createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex")); const got = Buffer.from(parts.v1 ?? ""); const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= 300; if (got.length !== expected.length || !timingSafeEqual(got, expected) || !fresh) throw new Error("Chữ ký không hợp lệ"); return JSON.parse(rawBody); }
Thử nhận webhook ngay trên máy: thêm địa chỉ ở trang Webhooks, rồi gửi tin thử tới sandbox. API gốc: https://app.zapro.vn/v1/webhooks.