TicketWave Logo
Webhooks

ภาพรวม

รับอีเวนต์ TicketWave เป็นคำขอ HTTP ที่ลงลายเซ็นแล้วในแอปพลิเคชันของคุณเอง

Webhooks

Webhook คือคำขอ HTTP ที่ TicketWave ส่งถึงคุณ ทุกครั้งที่มีบางอย่างเกิดขึ้นในเซิร์ฟเวอร์ของคุณ — เช่น มีการเปิดทิกเก็ต หรือมีสมาชิกถูกแบล็กลิสต์ — TicketWave จะ POST เนื้อหา JSON ไปยัง URL ที่คุณเป็นเจ้าของ

นี่คือความแตกต่างจาก Log Channels: log channels จะเขียน embed ลงใน Discord ให้มนุษย์อ่าน ส่วน webhooks จะส่งอีเวนต์ดิบให้โค้ดของคุณโดยตรง

Webhooks เป็นฟีเจอร์ พรีเมียม หากไม่มีพรีเมียม จะไม่สามารถสร้าง endpoint ได้ และจะไม่มีการส่งอีเวนต์ใด ๆ

สร้าง Endpoint

เปิดหน้ารายการ endpoints

แดชบอร์ดเซิร์ฟเวอร์ → WebhooksEndpoints

เพิ่ม endpoint

คลิก Add Endpoint แล้วกรอกสองช่องนี้:

FieldDescription
Endpoint URLURL https:// ที่รับคำขอ
Event Typesประเภทอีเวนต์ที่ endpoint นี้ควรรับ

endpoint จะรับเฉพาะประเภทที่คุณเลือกไว้เท่านั้น ไม่อนุญาตให้ไม่เลือกอะไรเลย — ต้องเลือกอย่างน้อยหนึ่งรายการ

คัดลอก signing secret

TicketWave จะสร้าง signing secret (whsec_…) ทันทีที่สร้าง endpoint เสร็จ เปิดรายการ endpoints แล้วกดไอคอนรูปตาเพื่อแสดงค่า จากนั้นคัดลอกไปใส่ในการตั้งค่าของแอปพลิเคชันคุณ

ให้ปฏิบัติกับ secret เหมือนรหัสผ่าน ใครก็ตามที่มีค่านี้สามารถปลอมคำขอให้ผ่านการตรวจลายเซ็นของคุณได้ เก็บไว้ใน environment variable เท่านั้น ห้ามเก็บใน repository

ส่งอีเวนต์ทดสอบ

ใช้ปุ่ม Send test event (ไอคอนเครื่องบินกระดาษ) ที่แถวของ endpoint มันจะส่งคำขอจริงที่ลงลายเซ็นครบถ้วน พร้อม "test": true ใน payload เพื่อให้คุณยืนยันได้ว่า receiver ของคุณทำงานก่อนที่ทิกเก็ตจริงจะพึ่งพามัน

ผลลัพธ์จะปรากฏในประวัติ Webhooks เหมือนกับการส่งปกติทุกประการ

ข้อกำหนดของ Endpoint

RequirementDetail
Schemeเฉพาะ https:// เท่านั้น — http:// จะถูกปฏิเสธ
Hostต้อง resolve ได้แบบสาธารณะ ที่อยู่แบบ private, loopback, link-local และ CGNAT จะถูกปฏิเสธ
Responseสถานะ 2xx ใด ๆ นับว่าสำเร็จ
Timeoutคุณมีเวลา 10 วินาที ในการตอบกลับ
Redirectsจะไม่ตามต่อ 3xx นับว่าเป็นความล้มเหลว
Limitสูงสุด 5 endpoints ต่อเซิร์ฟเวอร์

การตรวจ host จะเกิดขึ้นทั้งตอนที่คุณบันทึก endpoint และ ก่อนการส่งทุกครั้ง ดังนั้นโดเมนที่ภายหลังเริ่ม resolve ไปยังที่อยู่ภายในจะหยุดได้รับการส่งไปหา

คำขอ

การส่งทุกครั้งเป็น POST พร้อม body แบบ JSON

Headers

HeaderExampleMeaning
Content-Typeapplication/jsonเป็น JSON เสมอ
User-AgentTicketWave-Webhooks/1.0.5เวอร์ชันของบอทที่ส่งคำขอ
X-TicketWave-Eventticket.createdประเภทอีเวนต์
X-TicketWave-Deliverywh_3f2a…id เฉพาะของการส่งครั้งนี้
X-TicketWave-Timestamp1786224191Unix seconds ซึ่งเป็นส่วนหนึ่งของลายเซ็น
X-TicketWave-Signaturesha256=9f86d0…HMAC ของคำขอ

Body

payload ทุกอันใช้ envelope เดียวกัน ต่างกันแค่ data ตามประเภทอีเวนต์:

{
  "event": "ticket.created",
  "timestamp": "2026-08-26T08:23:11.000Z",
  "guild_id": "123456789012345678",
  "data": {
    "ticket_id": "ticket-1042",
    "ticket_num_id": 1042,
    "channel_id": "998877665544332211",
    "category": "🤖 Support",
    "user": { "id": "987654321098765432", "username": "Luna" },
    "created_at": "2026-08-26T08:23:11.000Z"
  }
}

ดู Event Reference สำหรับอ็อบเจ็กต์ data ของแต่ละประเภท

การตรวจสอบลายเซ็น

ใครก็ตามที่รู้ URL ของ endpoint คุณสามารถส่งคำขอ POST มาหาได้ ลายเซ็นคือวิธีที่คุณใช้แยกแยะว่าการส่งนั้นมาจาก TicketWave จริงหรือเป็นของปลอม

ต้องตรวจสอบเสมอ endpoint ที่ไม่ได้ตรวจสอบแล้วไปสร้างหรือปิดอะไรบางอย่างในระบบของคุณ เท่ากับเปิดประตูทิ้งไว้

ลายเซ็นถูกสร้างอย่างไร

TicketWave จะนำ timestamp กับ body ของคำขอแบบ raw มาต่อกันด้วยจุด แล้วทำ HMAC-SHA256 กับผลลัพธ์โดยใช้ secret ของ endpoint ของคุณ:

signed_payload = X-TicketWave-Timestamp + "." + raw_request_body
signature      = HMAC_SHA256(signed_payload, your_endpoint_secret)

header จะส่งค่า digest นั้นในรูปแบบ hex และมี prefix: sha256=<digest>

receiver ของคุณต้องทำอะไร

อ่าน raw body แล้วตรวจสอบกับไบต์จริงที่คุณได้รับ หาก framework ของคุณ parse JSON ก่อนแล้วคุณ serialize ใหม่ ลำดับคีย์หรือช่องว่างอาจเปลี่ยน และ digest จะไม่ตรงกัน

คำนวณ HMAC ใหม่ จาก timestamp + "." + rawBody ด้วย secret ของคุณ

เปรียบเทียบแบบ constant time (crypto.timingSafeEqual ใน Node) การใช้ === แบบธรรมดาจะทำให้รั่วไหลข้อมูลด้านเวลา

ตรวจสอบว่า timestamp ยังใหม่อยู่ — โดยทั่วไปให้เผื่อไว้ห้านาทีเป็นค่าเริ่มต้นที่ดี timestamp อยู่ใน signed payload ดังนั้นผู้โจมตีจะไม่สามารถ replay คำขอเก่าด้วย timestamp ใหม่ได้

มีตัวอย่างการใช้งานแบบครบถ้วนอยู่ที่หน้า Example Server

การลองส่งใหม่

การส่งที่ล้มเหลวจะถูกลองส่งใหม่โดยอัตโนมัติ

Attempts3 (ครั้งแรกบวกกับ retry อีก 2 ครั้ง)
Backoff1 วินาที แล้ว 5 วินาที
Retried onข้อผิดพลาดของเครือข่าย, timeout, 408, 429 และ 5xx ทุกแบบ
Not retried on4xx อื่น ๆ ทั้งหมด — หมายความว่า endpoint ของคุณปฏิเสธคำขอนั้นโดยตั้งใจ

เพราะมีการ retry endpoint ของคุณจึงอาจได้รับ อีเวนต์เดียวกันสองครั้ง ใช้ X-TicketWave-Delivery เป็น idempotency key: จดจำ id ที่คุณประมวลผลแล้วและละเว้นรายการที่ซ้ำ

การส่ง ไม่ได้ เรียงลำดับเสมอไป หากมีการสร้างทิกเก็ตสองใบในเวลาเดียวกัน คำขออาจมาถึงสลับลำดับกันได้ — ใช้ฟิลด์ timestamp ใน body หากลำดับมีความสำคัญกับคุณ

ประวัติการส่ง

หน้า Webhooks ในแดชบอร์ดจะแสดงการส่งทุกครั้งพร้อมสถานะ รหัสตอบกลับ ระยะเวลา และจำนวนครั้งที่พยายามส่ง เปิดแถวเพื่อดู payload ของคำขอที่ส่งจริงและ response ที่เซิร์ฟเวอร์ของคุณส่งกลับมา

การส่งที่ล้มเหลวสามารถส่งใหม่ได้จากหน้ารายละเอียดด้วย Retry Webhook มันจะส่ง payload เดิมไปยัง endpoint เดิมอีกครั้ง และบันทึกเป็นการส่งใหม่

ประวัติจะถูกเก็บไว้ 30 วัน จากนั้นจะถูกลบออกโดยอัตโนมัติ

การแก้ปัญหา

ProblemFix
ไม่สามารถบันทึก endpoint ได้URL ต้องเป็น https:// และ resolve ไปยังที่อยู่สาธารณะ
ทุกอย่างแสดงว่า failed โดยไม่มี response codeคำขอไม่เคยมาถึงคุณ — timeout, DNS ล้มเหลว หรือ connection refused
ลายเซ็นไม่ตรงเลยคุณกำลัง hash body ที่ parse แล้วแทนไบต์ดิบ หรือไม่ได้ใส่ prefix timestamp + "."
การส่งหยุดไปหลังจากสักพักตรวจดูว่า host ของคุณเริ่มส่งกลับ 4xx หรือไม่ — แบบนั้นจะไม่ถูก retry
อีเวนต์ไม่เคยเข้ามาendpoint ไม่ได้ subscribe กับประเภทนั้น หรือเซิร์ฟเวอร์สูญเสียพรีเมียม
อีเวนต์ซ้ำเป็นเรื่องปกติเมื่อมี retry — ให้ deduplicate ด้วย X-TicketWave-Delivery

ขั้นตอนถัดไป

  • Event Reference (ทุกอีเวนต์และ payload ของมัน)
  • Example Server (receiver แบบ Express ที่รันได้จริง)
  • Log Channels (อีเวนต์เดียวกัน แต่โพสต์เข้า Discord)

How is this guide?