การตั้งค่าและทดสอบ
คู่มือนี้พาคุณผ่านการสร้าง Webhook Endpoint ใน Dashboard ของ Ocriva การยืนยันลายเซ็นใน Application Code ของคุณ การทดสอบ Delivery แบบ Local และการอ่าน Webhook Logs เพื่อ Debug ความล้มเหลว
การสร้าง Webhook Endpoint
ขั้นตอนที่ 1 — ไปที่ Webhooks
ไปที่ Organization Settings และเลือกแท็บ Webhooks คลิก Add Endpoint ที่มุมบนขวา
ขั้นตอนที่ 2 — กำหนดค่า Endpoint
กรอกข้อมูลในฟอร์ม Endpoint:
| Field | จำเป็น | คำอธิบาย |
|---|---|---|
| Name | ใช่ | Label ที่อ่านได้ เช่น Production ERP Receiver |
| URL | ใช่ | URL เต็มที่ Ocriva จะ POST ไป เช่น https://api.yourapp.com/webhooks/ocriva |
| Events | ใช่ | เลือก Event Type หนึ่งรายการหรือมากกว่าที่ต้องการ Subscribe |
| Secret | ไม่ | String สุ่มที่ใช้เซ็นชื่อ Delivery (แนะนำอย่างยิ่ง) |
| Custom Headers | ไม่ | HTTP Header เพิ่มเติมที่ต้องการใส่ใน Delivery ทุกครั้ง |
| Description | ไม่ | หมายเหตุสำหรับทีมของคุณ |
ขั้นตอนที่ 3 — เลือก Events
เลือก Event ที่ Endpoint นี้ควรรับ คุณสามารถ Subscribe ได้ทุกรูปแบบ:
document.uploaded— ได้รับไฟล์แล้ว ก่อนประมวลผลdocument.processed— ประมวลผลสำเร็จพร้อมข้อมูลที่ดึงออกมาdocument.failed— ประมวลผลล้มเหลวbatch.uploaded— ได้รับ Batch ของไฟล์แล้วbatch.completed— ทุกไฟล์ใน Batch เสร็จสิ้นtemplate.created/template.updated/template.deleted— Template Lifecycle
ขั้นตอนที่ 4 — บันทึกและยืนยัน
คลิก Save Status ของ Endpoint จะเริ่มเป็น active Ocriva จะเริ่ม Deliver Event ทันที คุณสามารถหยุดชั่วคราวหรือปิดการใช้งาน Endpoint ได้ตลอดเวลาจากการตั้งค่า Endpoint
IMPORTANT
ยืนยันลายเซ็น Webhook เสมอใน Production โดยไม่มีการยืนยันลายเซ็น Server ใด ๆ ที่รู้ URL ของ Endpoint ของคุณสามารถส่ง Webhook Payload ปลอมเข้ามาในระบบของคุณได้ การเพิ่ม Secret ใช้เวลา 30 วินาที แต่ขจัดความเสี่ยงนี้ได้อย่างสมบูรณ์
การยืนยันลายเซ็น
เมื่อคุณตั้งค่า Secret บน Endpoint Ocriva จะคำนวณ HMAC-SHA256 Digest ของ Request Body ดิบโดยใช้ Secret ของคุณเป็น Key และใส่ค่านั้นใน Header X-Webhook-Signature เป็น sha256={hex_digest}
Server ของคุณควร:
- อ่าน Request Body ดิบเป็น Bytes — อย่า Parse JSON ก่อน
- คำนวณ
HMAC-SHA256(body, secret)โดยใช้ Secret เดียวกัน - เปรียบเทียบ Digest ที่คำนวณได้กับค่าใน
X-Webhook-Signature - ปฏิเสธ Request (ส่งคืน
401) หากไม่ตรงกัน
ตัวอย่างการยืนยันใน Node.js
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(body))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}ตัวอย่าง Express.js Middleware
const crypto = require('crypto');
const express = require('express');
const app = express();
// ใช้ Raw Body Parser สำหรับ Route ของ Webhook — ห้ามใช้ express.json() ที่นี่
app.post('/webhooks/ocriva', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const secret = process.env.OCRIVA_WEBHOOK_SECRET;
if (!signature || !secret) {
return res.status(401).json({ error: 'Missing signature or secret' });
}
const expectedSig = crypto
.createHmac('sha256', secret)
.update(req.body)
.digest('hex');
const sigBuffer = Buffer.from(signature.replace('sha256=', ''));
const expectedBuffer = Buffer.from(expectedSig);
if (sigBuffer.length !== expectedBuffer.length ||
!crypto.timingSafeEqual(sigBuffer, expectedBuffer)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// ลายเซ็นถูกต้อง — Parse และจัดการ Event
const event = JSON.parse(req.body.toString());
switch (event.eventType) {
case 'document.processed':
// จัดการข้อมูลที่ดึงออกมา
break;
case 'document.failed':
// จัดการความล้มเหลว
break;
default:
// ไม่สนใจ Event ที่ไม่รู้จัก
}
// ตอบกลับด้วย 2xx เสมอและอย่างรวดเร็ว
res.status(200).json({ received: true });
});WARNING
Endpoint ของคุณต้องตอบกลับด้วย Status Code 2xx ภายใน Timeout ที่กำหนด (ค่าเริ่มต้น 30 วินาที) ถ้า Logic การประมวลผลของคุณใช้เวลานานกว่านั้น เช่น การเขียนลงฐานข้อมูล การเรียก External API หรือการคำนวณหนัก ๆ ให้ส่งคืน 200 ทันทีแล้วส่งงานไปยัง Background Queue แทน Response ที่ช้าทำให้เกิด Delivery Failure และ Retry โดยไม่จำเป็น
นโยบาย Retry
ถ้า Ocriva ไม่ได้รับ Response 2xx — หรือ Request Timeout — จะ Retry อัตโนมัติ:
| ครั้ง | Delay |
|---|---|
| ครั้งแรก | ทันที |
| ครั้งที่ 2 | ประมาณ 30 วินาทีหลังจาก Failure ครั้งแรก |
| ครั้งที่ 3 | ประมาณ 5 นาทีหลังจาก Failure ครั้งที่สอง |
หลังจากพยายาม 3 ครั้งแล้วล้มเหลว Delivery จะถูกทำเครื่องหมายว่า failed ใน Log และไม่มีการ Retry อีก คุณสามารถตรวจสอบ Delivery ที่ล้มเหลวใน Webhook Logs และ Trigger ซ้ำด้วยตนเองหากจำเป็น
นับว่าสำเร็จเมื่อ: Response HTTP มี Status Code 2xx (200–299)
นับว่าล้มเหลวเมื่อ: Status ที่ไม่ใช่ 2xx, Connection Refused, DNS Error หรือ Timeout
การทดสอบ Webhook
Manual Trigger ผ่าน API
คุณสามารถส่ง Test Event ไปยัง Endpoint ใด ๆ โดยไม่ต้องรอ Activity จริง โดยใช้ Trigger Endpoint:
curl -X POST https://api.ocriva.com/webhooks/{organizationId}/trigger \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"endpointId": "wh_endpoint_id",
"eventType": "document.processed"
}'คำสั่งนี้ส่ง Sample Payload สำหรับ Event Type ที่ระบุไปยัง Endpoint ของคุณและบันทึกผลการ Delivery
Local Development ด้วย ngrok
เมื่อพัฒนาแบบ Local Server localhost ของคุณไม่สามารถเข้าถึงได้จาก Ocriva ใช้ ngrok (หรือ Tunnel Tool อื่นที่คล้ายกัน) เพื่อ Expose Port Local ของคุณไปยัง Internet:
# ติดตั้ง ngrok จาก https://ngrok.com แล้วรัน:
ngrok http 3000ngrok ให้ URL HTTPS สาธารณะเช่น https://abc123.ngrok.io ใช้ URL นั้นเป็น Webhook Endpoint URL ใน Ocriva ระหว่างการพัฒนา
TIP
Web Inspector ของ ngrok (เปิดได้ที่ http://localhost:4040 ขณะที่ ngrok กำลังทำงาน) แสดง Request และ Response ทุกรายการแบบ Real-time คุณสามารถ Replay Request ใด ๆ ได้ด้วยคลิกเดียว มีประโยชน์มากเมื่อต้องปรับปรุง Handler Logic โดยไม่ต้อง Re-trigger Event
ตรวจสอบ Test Delivery
หลังจาก Trigger Test:
- ตรวจสอบ Log ของ Application ของคุณ — ยืนยันว่า Request มาถึงและจัดการอย่างถูกต้อง
- เปิดแท็บ Webhook Logs ใน Ocriva Dashboard — ค้นหา Delivery และยืนยันว่าแสดง Status
200 - ถ้า Delivery ล้มเหลว ให้ขยาย Log Entry เพื่อดู Error และ Response Body ทั้งหมด
Webhook Logs
ทุก Delivery Attempt ถูกเก็บไว้ใน Webhook Logs วิธีดู:
- ไปที่ Organization Settings → Webhooks
- คลิกที่ Endpoint
- เลือกแท็บ Logs
แต่ละ Log Entry แสดง:
| คอลัมน์ | คำอธิบาย |
|---|---|
| Timestamp | เวลาที่พยายาม Deliver |
| Event Type | Event ที่ทำให้เกิด Delivery |
| Status | success หรือ failed |
| HTTP Status | Response Code ที่ Server ของคุณส่งคืน |
| Response Time | เวลาที่ Server ของคุณใช้ตอบสนอง (ms) |
| Error | ข้อความ Error ถ้า Delivery ล้มเหลว |
คุณยังดึง Log ผ่าน API ได้:
GET /webhooks/{organizationId}/logsและสถิติระดับ Endpoint (จำนวน Request ทั้งหมด อัตราความสำเร็จ เวลาตอบสนองเฉลี่ย):
GET /webhooks/{organizationId}/statsBest Practices
ตอบกลับทันที ประมวลผลทีหลัง
Endpoint ของคุณควรส่งคืน 200 OK ให้เร็วที่สุด — ควรน้อยกว่า 1 วินาที อย่าเรียก Database Write, External API หรือการคำนวณหนัก ๆ แบบ Synchronous ใน Webhook Handler ให้ Push Event ไปยัง Queue (BullMQ, SQS, Redis ฯลฯ) แทนแล้วประมวลผลแบบ Asynchronous
app.post('/webhooks/ocriva', express.raw({ type: 'application/json' }), async (req, res) => {
// ยืนยันลายเซ็นก่อน (เร็ว)
if (!verifySignature(req)) return res.status(401).end();
const event = JSON.parse(req.body.toString());
// เพิ่มเข้า Queue สำหรับ Background Processing (เร็ว)
await queue.add('webhook-event', event);
// ตอบกลับทันที
res.status(200).json({ received: true });
});จัดการ Duplicate Events
เนื่องจาก Retry และสภาพของเครือข่าย Endpoint ของคุณอาจได้รับ Event เดิมมากกว่าหนึ่งครั้ง ควร Implement Handler ที่เป็น Idempotent โดยตรวจสอบว่าคุณได้ประมวลผล eventId นั้นแล้วหรือยังก่อนดำเนินการ
async function handleDocumentProcessed(event) {
const alreadyProcessed = await db.events.findOne({ eventId: event.eventId });
if (alreadyProcessed) return; // ข้าม Duplicate
await db.events.insert({ eventId: event.eventId, processedAt: new Date() });
// ... ส่วนที่เหลือของ Handler
}ยืนยันลายเซ็นเสมอใน Production
อย่าข้ามการยืนยันลายเซ็นใน Production Middleware เพียงบรรทัดเดียวปกป้องระบบของคุณจาก Event ปลอมและผลข้างเคียงที่ไม่ต้องการ
ตั้งชื่อ Endpoint ให้สื่อความหมาย
ตั้งชื่อ Endpoint ตามวัตถุประสงค์และสภาพแวดล้อม: Production — ERP Invoice Receiver, Staging — Slack Notifier ทำให้อ่าน Log ได้ง่ายขึ้นมากเมื่อมีปัญหาเกิดขึ้น
ติดตามอัตราการล้มเหลว
ตรวจสอบ Webhook Stats เป็นประจำ อัตราการล้มเหลวที่สูงขึ้นบน Endpoint มักบ่งบอกถึงปัญหาของ Server ก่อนที่จะกลายเป็นเหตุการณ์ใหญ่
