Webhooks
รับ event แบบ HMAC-signed · retry อัตโนมัติ 5 ครั้ง · delivery log + auto-disable endpoint ที่ล่ม
ตั้ง endpoint ของคุณที่ Settings → Webhooks — SlipBolt จะ POST event ทุกครั้งที่มีผลตรวจสลิปใหม่
Event types
มี 3 event · เลือก subscribe ได้ต่อ endpoint (ไม่เลือกเลย = ได้ slip.verified อย่างเดียว)
| Event | เมื่อไร | data.status ที่มากับ event |
|---|---|---|
slip.verified | สลิปผ่านการตรวจ | SUCCESS |
slip.duplicate | สลิปใบนี้เคยส่งมาแล้ว | DUPLICATE |
slip.failed | ตรวจไม่ผ่าน | INVALID · FRAUD · AMOUNT_MISMATCH · RECEIVER_MISMATCH · PROVIDER_ERROR |
ยังไม่มี event ฝั่งบัญชี/แพ็ก (เช่น subscription หรือโควตาใกล้เต็ม) — การแจ้งเตือนโควตา 80% ส่งทางอีเมล/LINE ไม่ใช่ webhook
Payload
Body เป็น JSON ตามนี้เสมอ — created เป็น unix seconds ไม่ใช่ ISO string
{
"event": "slip.verified",
"id": "evt_9f3c1a7b2d4e6f8a0b1c2d3e",
"created": 1781107927,
"data": {
"transactionId": "8f3c…",
"transRef": "015170106978META…",
"amount": 250.0,
"status": "SUCCESS",
"bankCode": "002",
"bankName": "ธนาคารกรุงเทพ",
"sender": "นาย ก. …",
"receiver": "ร้าน ข.",
"verifiedAt": "2026-06-17T03:21:06.412Z",
"latencyMs": 480
}
}
sender / receiver เป็น string ชื่อ ไม่ใช่ object · ค่าที่อ่านไม่ได้จากสลิปจะเป็น null
Header ที่มากับทุก delivery:
| Header | ค่า |
|---|---|
X-Slipbolt-Event | ชื่อ event เช่น slip.verified |
X-Slipbolt-Delivery | id ของ endpoint ที่ยิงมา |
X-Slipbolt-Signature | t=<unix>,v1=<hex> — ดูหัวข้อถัดไป |
User-Agent | Slipbolt-Webhooks/1.0 |
Verify signature
X-Slipbolt-Signature: t=1781107927,v1=<hex>
v1 = HMAC-SHA256(secret, "<ts>." + raw_body)
สตริงที่เซ็นคือ <ts>.<body> — ไม่มี t= นำหน้า · ใส่ t= เข้าไปด้วยจะได้ signature คนละค่า
แล้ว verify ไม่ผ่านทุกใบ · และต้องใช้ raw body ไม่ใช่ JSON ที่ parse แล้ว re-serialize
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody: string, header: string, secret: string): boolean {
const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
const ts = parts.t;
const sig = parts.v1;
if (!ts || !sig) return false;
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // กัน replay 5 นาที
const expected = createHmac('sha256', secret)
.update(`${ts}.${rawBody}`) // ← จุดที่พลาดกันบ่อย
.digest('hex');
const a = Buffer.from(sig, 'hex');
const b = Buffer.from(expected, 'hex');
return a.length === b.length && timingSafeEqual(a, b);
}
ดู secret ของแต่ละ endpoint ได้ที่ Settings → Webhooks (กดเปิดดูทีละอัน)
Retry policy
- 2xx = สำเร็จ · อย่างอื่นทั้งหมดถือว่าล้มเหลว
- 4xx ก็ retry — ไม่ได้ยกเว้นเหมือนบางเจ้า · ถ้าไม่อยากโดนยิงซ้ำ ตอบ 2xx แล้วค่อยไปคัดทิ้งฝั่งคุณ
- timeout 10 วินาที ต่อครั้ง
- ลองทั้งหมด 5 ครั้ง · backoff แบบ exponential เริ่มที่ 2 วินาที (≈ 2s → 4s → 8s → 16s)
- ทุกครั้งที่ยิงถูกบันทึกเป็นแถวใน delivery log — ดูได้ที่ Settings → Webhooks
endpoint ที่ล้มเหลวสะสมครบ 25 ครั้งจะถูกปิดอัตโนมัติ (enabled = false) และหยุดรับ event
จนกว่าจะเปิดใหม่เอง · ตัวนับรีเซ็ตทันทีที่มี delivery สำเร็จหนึ่งครั้ง
ทดสอบ endpoint
กด ส่ง event ตัวอย่าง ที่ Settings → Webhooks — ระบบยิง slip.verified ปลอมหนึ่งใบไปที่ endpoint นั้น
โดยไม่สนว่า subscribe อะไรไว้และไม่แตะโควตา · ใช้ตรวจว่า signature ฝั่งคุณ verify ผ่านจริงก่อนขึ้น production
ถัดไป
- API Reference — endpoint + error code ทั้งหมด
- Security & PDPA — การเก็บ secret + สิทธิ์เจ้าของข้อมูล

