Webhooks
รับ event tip.created ตรวจสอบ timestamp และลายเซ็น HMAC-SHA256 จาก raw request body
รับ event
แอปต้องมี HTTPS Webhook URL และ grant ต้องมี scope events.subscribe เมื่อครีเอเตอร์ได้รับทิปสำเร็จ Furipay จะ POST payload นี้:
{
"event": "tip.created",
"name": "Ploy",
"amount": 50,
"message": "สู้ ๆ นะ!",
"createdAt": "2026-08-14T09:12:00.000Z"
}
ตรวจสอบลายเซ็น
ทุก request มี header X-Furipay-Signature รูปแบบ t=UNIX_SECONDS,v1=HEX_SIGNATURE โดยลายเซ็นคือ HMAC-SHA256 ของ t.rawBody ด้วย webhook secret
เก็บ raw body เดิมก่อน parse JSON อย่า stringify object กลับเพื่อยืนยันลายเซ็น:
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyFuripayWebhook(
rawBody: Buffer,
header: string,
webhookSecret: string,
): boolean {
const fields = Object.fromEntries(
header.split(",").map((part) => part.split("=", 2)),
);
const timestamp = Number(fields.t);
const provided = Buffer.from(fields.v1 ?? "", "hex");
if (
!Number.isInteger(timestamp) ||
Math.abs(Date.now() / 1000 - timestamp) > 300 ||
provided.length !== 32
) {
return false;
}
const expected = createHmac("sha256", webhookSecret)
.update(String(timestamp) + ".")
.update(rawBody)
.digest();
return timingSafeEqual(expected, provided);
}
การจำกัด timestamp ไม่เกิน 5 นาทีช่วยลดความเสี่ยงจาก replay จากนั้นตอบ HTTP 2xx ให้เร็วและค่อยทำงานหนักใน queue
การส่งซ้ำและการทดสอบ
- Furipay ให้เวลาแต่ละ request 10 วินาที
- เมื่อเกิด network error, timeout หรือ non-2xx ระบบพยายามส่งสูงสุด 4 ครั้ง โดยรอ 0, 5, 60 และ 600 วินาทีก่อนแต่ละครั้ง
- ปุ่มส่ง event ทดสอบใน Developer Portal ส่งเพียงครั้งเดียวและบันทึกผลใน Delivery log
- Endpoint ต้องรองรับ event ซ้ำได้ เพราะการ retry อาจทำให้ request ที่ประมวลผลสำเร็จแล้วถูกส่งอีกครั้ง