Webhooks

ให้ระบบส่งเหตุการณ์ไปยัง URL ของคุณทันทีที่เกิด เช่น มีออเดอร์ใหม่ บิลปิด โค้ด Wi-Fi ถูกใช้ หรือกล่อง Wi-Fi ออฟไลน์

  1. ในหน้า Integrations ส่วน Webhooks กด เพิ่ม Webhook (Project ต้องมีร้าน Business Apps ในเว็บ หรือเปิด Business Apps API หรือ Wi-Fi Hotspot API และคุณเป็น Owner หรือ Admin)
  2. ใส่ URL แบบ https:// ที่เข้าถึงได้จากอินเทอร์เน็ต และเลือกเหตุการณ์ที่ต้องการ (ไม่เลือก = ทุกเหตุการณ์)
  3. คัดลอก Signing secret เก็บไว้ ระบบแสดงครั้งเดียว
  4. กด ทดสอบ เพื่อส่งเหตุการณ์ ping ไปลองที่ URL ของคุณ
เหตุการณ์เกิดเมื่อ
order.created, order.updated, bill.closed, booking.created, shift.closed ฯลฯมีการเปลี่ยนแปลงในร้าน ทั้งร้านในเว็บและร้านแบบ API ไม่ว่าจะเปลี่ยนจากหน้าจัดการ แอปพนักงาน หรือ API (มี shopId)
order.payment_claimed, booking.payment_claimed, booking.cancelledลูกค้าบนหน้าเว็บกดแจ้งว่าโอนเงินแล้ว หรือยกเลิกการจองเอง
voucher.usedโค้ด Wi-Fi ถูกใช้ครั้งแรก (ไม่ส่งตัวโค้ด มี note ที่ใส่ตอนออกโค้ด เช่น เลขห้อง)
guest.signed_inผู้ใช้กรอกอีเมลหรือเบอร์โทรที่หน้าล็อกอิน (returning บอกว่าเคยมาแล้วหรือไม่)
box.offline, box.onlineกล่อง Wi-Fi ขาดการติดต่อเกิน 2 นาที และเมื่อกลับมาออนไลน์

แต่ละเหตุการณ์ส่งเป็น POST แบบ JSON ระบบของคุณต้องตอบ 2xx ภายใน 10 วินาที ถ้าไม่ตอบ ระบบส่งซ้ำอัตโนมัติ (ห่างขึ้นเรื่อย ๆ จนถึงประมาณหนึ่งวัน) ดูประวัติการส่งได้ที่ปุ่ม ประวัติการส่ง

JSON
{"id":"evt_…","type":"order.created","createdAt":"2026-10-13T09:30:00Z","shopId":"…","data":{…}}

ตรวจว่า Webhook มาจากเราจริง

ทุกครั้งมี header X-TH-Signature: t=<เวลา>,v1=<ลายเซ็น> ลายเซ็นคือ HMAC-SHA256 ของ <เวลา>.<body> ด้วย Signing secret ของคุณ ให้คำนวณจาก body ดิบที่ได้รับ ก่อนแปลงเป็น JSON

Node.js
const crypto = require("crypto");
function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
  const mac = crypto.createHmac("sha256", secret).update(parts.t + "." + rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(parts.v1));
}
Python
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    mac = hmac.new(secret.encode(), parts["t"].encode() + b"." + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(mac, parts["v1"])

เหตุการณ์อาจมาถึงไม่ตรงลำดับ ให้เรียงตาม createdAt และใช้ id กันการประมวลผลซ้ำ เพราะเหตุการณ์เดิมอาจถูกส่งซ้ำได้

ถ้าเจอปัญหา

เพิ่ม Webhook แล้วขึ้นว่า URL ต้องเป็นที่อยู่บนอินเทอร์เน็ต

ใช้ URL แบบ https:// ที่เปิดจากภายนอกได้ ไม่ใช่ IP ภายใน หรือ localhost

ประวัติการส่งขึ้น “ส่งไม่สำเร็จ”

ดูรหัส HTTP ที่ URL ของคุณตอบ ระบบส่งซ้ำให้เองจนกว่าจะสำเร็จหรือครบรอบ แก้ฝั่งรับแล้วกด ทดสอบ เพื่อเช็ก

ยังแก้ไม่ได้? ให้ทีมงานช่วย

เปิด ticket จากหน้าจัดการ บอกชื่อเว็บหรือบริการ สิ่งที่ทำ และข้อความที่เห็นบนจอ ทีมงานจะตอบกลับในเรื่องเดียวกัน ติดตามได้ในที่เดียว