/ คู่มือสำหรับนักพัฒนา
รับโพสต์จาก Orova Social ผ่าน Webhook
วิธีสร้าง endpoint สำหรับรับโพสต์ที่ Orova Social ส่งมา และตรวจลายเซ็นก่อนนำไปใช้
Orova Social เผยแพร่ตรงไปยังแพลตฟอร์มที่เชื่อมไว้แล้ว หากต้องการให้โพสต์ไปถึงที่อื่น — ช่องทางภายในองค์กร แอปของคุณเอง หรือแพลตฟอร์มที่ Orova ยังไม่รองรับ — ให้ใช้ช่องทาง API: Orova จะส่งโพสต์ไปยังที่อยู่ HTTP ของคุณ พร้อมลงลายเซ็นด้วยคีย์ลับ แล้วที่เหลือเป็นหน้าที่ของคุณ หน้านี้สำหรับนักพัฒนา และอธิบายข้อตกลงของ request ครบถ้วน
/ ภาพรวม
หลักการทำงาน
คุณระบุที่อยู่รับข้อมูล (https://) และคีย์ลับไว้ที่ช่องทาง API ของโครงการ Orova จะส่ง request POST พร้อมเนื้อหาเป็น JSON ไปที่นั่น และแนบส่วนหัว X-Orova-Signature ซึ่งคือ HMAC-SHA256 ของไบต์ดิบของเนื้อหานั้น โดยใช้คีย์ลับของคุณ endpoint ของคุณตรวจลายเซ็น รับโพสต์ แล้วตอบกลับด้วยรหัส 2xx
- ที่อยู่รับข้อมูลต้องเป็น https. ถ้าที่อยู่ไม่ใช่
https://หรือไม่มีชื่อโฮสต์ Orova จะไม่บันทึกช่องทาง และแจ้งรหัสapi_url - หนึ่งที่อยู่ หนึ่งช่องทาง. Orova ใช้ที่อยู่รับข้อมูลเป็นตัวระบุช่องทาง บันทึกที่อยู่เดิมซ้ำคือการเขียนทับช่องทางเดิม ไม่สร้างช่องทางซ้ำ
- มีปุ่มส่งทดสอบ. เมื่อเชื่อมแล้ว ช่องทางจะมีปุ่ม Send test: Orova ยิงข้อมูล
orova.testไปที่ endpoint ของคุณทันที แล้วแสดงรหัส HTTP ที่ได้รับ พร้อมเวลาไป-กลับเป็นมิลลิวินาที
/ ตั้งค่า
ตั้งค่าใน Orova
เปิด Social → โครงการ → เลือกโครงการ → แท็บ ช่องทาง แล้วหากล่อง API ในนั้นมีช่องกรอกสองช่องและปุ่มหนึ่งปุ่ม
- 1
URL รับข้อมูล (webhook). ที่อยู่ endpoint ของคุณ ขึ้นต้นด้วย
https://ทุก request จะถูกส่งมาที่นี่ - 2
คีย์ลับ. สตริงที่ใช้ลงลายเซ็น ถ้าเว้นว่าง Orova จะสุ่มให้ แต่หน้าจอจะไม่แสดงซ้ำ จึงควรสร้างสตริงยาว ๆ เองแล้ววางลงไป และเก็บสำเนาไว้ฝั่งคุณ
- 3
กด Save channel. ช่องทางจะปรากฏในรายการพร้อมที่อยู่รับข้อมูล ส่วนคีย์ลับจะไม่แสดงอีก
- 4
กด Send test. Orova จะส่งข้อมูลตัวอย่าง
orova.testถ้า endpoint ตอบ 2xx Orova จะแจ้งว่า “Webhook ตอบ 200 ใน … ms” รหัสอื่นจะแจ้งพร้อมรหัสนั้น ส่วนกรณีติดต่อไม่ได้จะแจ้งเป็นข้อผิดพลาดเครือข่าย
/ ข้อตกลง
ข้อตกลงของ request
ทุกครั้งที่ส่ง request จะมีหน้าตาแบบนี้:
POST <your receiving URL>
Headers:
Content-Type: application/json
X-Orova-Signature: sha256=<hex HMAC-SHA256 of the raw body>
X-Orova-Event: orova.test
User-Agent: Orova-Social/1.0
Body (JSON):
{
"event": "orova.test",
"workspace_id": 12,
"project_id": 34,
"post": {
"title": "...",
"content": "...",
"media": [],
"channels": ["api"]
},
"sent_at": "2026-08-23T01:25:00Z"
}เนื้อหาเป็น JSON UTF-8 แบบกระชับ บรรทัดเดียว ให้อ่านค่า event เพื่อแยกประเภท — ข้อมูลจากปุ่มส่งทดสอบมีค่า orova.test และส่วนหัว X-Orova-Event ก็เป็นค่าเดียวกัน endpoint ของคุณควรข้ามฟิลด์ที่ไม่รู้จักแทนที่จะปฏิเสธ เพื่อให้การเพิ่มฟิลด์ในอนาคตไม่ทำให้ระบบคุณพัง
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
| event | string | ประเภทเหตุการณ์ ข้อมูลจากปุ่มส่งทดสอบคือ "orova.test" |
| workspace_id | integer | ไอดีพื้นที่ทำงานที่ส่งข้อมูลนี้ |
| project_id | integer | null | ไอดีโครงการที่ช่องทางสังกัด หรือ null ถ้ายังไม่ได้กำหนด |
| post | object | ตัวโพสต์ |
| post.title | string | หัวเรื่องของโพสต์ |
| post.content | string | เนื้อหาโพสต์ในรูปข้อความ |
| post.media | array | ไฟล์แนบของโพสต์ เป็นอาร์เรย์ว่างเมื่อมีแต่ข้อความ |
| post.channels | array of string | ประเภทช่องทางที่โพสต์นี้มุ่งไป เช่น ["api"] |
| sent_at | string | เวลาที่ Orova ส่ง รูปแบบ ISO 8601 เวลา UTC ลงท้ายด้วย "Z" |
/ การตรวจสอบ
ตรวจลายเซ็น
ส่วนหัว X-Orova-Signature อยู่ในรูป sha256=<hex> โดย <hex> คือ HMAC-SHA256 ของไบต์ดิบของเนื้อหา request ใช้คีย์ลับของช่องทาง ให้คำนวณซ้ำจากไบต์ที่ได้รับตรง ๆ — ถ้าแปลง JSON แล้วสร้างสตริงใหม่จะไม่ตรง เพราะต่างกันแค่ช่องว่างเดียวลายเซ็นก็เปลี่ยน
Node.js
// Node.js / Express — verify X-Orova-Signature, then answer fast
import express from "express";
import crypto from "node:crypto";
const app = express();
const OROVA_SECRET = process.env.OROVA_SECRET; // the key you saved in Orova
// Keep the RAW bytes: the signature covers them, not re-serialized JSON.
app.post(
"/orova/social",
express.raw({ type: "application/json", limit: "5mb" }),
(req, res) => {
const sent = req.get("x-orova-signature") || "";
const mine =
"sha256=" +
crypto.createHmac("sha256", OROVA_SECRET).update(req.body).digest("hex");
// Constant-time compare — never use ===.
const a = Buffer.from(sent);
const b = Buffer.from(mine);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).json({ error: "bad signature" });
}
const payload = JSON.parse(req.body.toString("utf8"));
if (payload.event === "orova.test") {
return res.status(200).json({ ok: true }); // the Send test button
}
// Real post: hand the work to a queue and reply straight away.
queuePost(payload).catch(console.error);
return res.status(200).json({ ok: true });
},
);
app.listen(3000);Python
# Python / Flask — same check, same rules
import hashlib
import hmac
import json
import os
from flask import Flask, request
app = Flask(__name__)
OROVA_SECRET = os.environ["OROVA_SECRET"].encode("utf-8")
@app.post("/orova/social")
def orova_social():
raw = request.get_data() # bytes, exactly as sent
mine = "sha256=" + hmac.new(OROVA_SECRET, raw, hashlib.sha256).hexdigest()
sent = request.headers.get("X-Orova-Signature", "")
if not hmac.compare_digest(mine, sent): # constant-time compare
return {"error": "bad signature"}, 401
payload = json.loads(raw)
if payload.get("event") == "orova.test":
return {"ok": True}, 200
queue_post(payload) # do the slow work later
return {"ok": True}, 200เปรียบเทียบด้วยฟังก์ชันแบบเวลาคงที่ (crypto.timingSafeEqual, hmac.compare_digest) อย่าใช้การเทียบเท่าธรรมดา ถ้าลายเซ็นไม่ตรงให้ตอบ 401 แล้วหยุด อย่าประมวลผลข้อมูลนั้น
/ การตอบกลับ
ตอบกลับอย่างไร
Orova ดูเฉพาะรหัสสถานะ HTTP รหัสในกลุ่ม 2xx ถือว่าสำเร็จ ส่วนเนื้อหาที่ตอบกลับจะเป็นอะไรก็ได้
- ตอบให้เร็ว. ปุ่มส่งทดสอบรอไม่เกิน
10 วินาทีงานหนัก เช่น ดาวน์โหลดไฟล์สื่อ หรือเรียก API ภายนอก ให้โยนเข้าคิวแล้วตอบ 2xx ทันที - Orova ไม่ลองส่งซ้ำเอง. เป็นความตั้งใจ เพราะการลองส่งซ้ำอัตโนมัติกับ API เผยแพร่คือต้นเหตุของการโพสต์ซ้ำสองครั้ง เมื่อส่งไม่สำเร็จ โพสต์จะถูกทำเครื่องหมาย
failedพร้อมเหตุผล แล้วผู้ใช้กดเผยแพร่ใหม่ใน Orova - รองรับข้อมูลซ้ำได้. เมื่อผู้ใช้กดเผยแพร่ใหม่ ข้อมูลชุดเดิมจะมาอีกครั้ง ให้กรองซ้ำที่ฝั่งคุณ เช่น จำคู่
workspace_idกับsent_atที่จัดการไปแล้ว
/ ความปลอดภัย
ความปลอดภัย
- ตรวจลายเซ็นเสมอ. endpoint ของคุณเป็น URL สาธารณะ ใครก็เรียกได้ ลายเซ็นคือสิ่งเดียวที่ยืนยันว่าข้อมูลมาจาก Orova จริง
- อย่าเก็บคีย์ลับไว้ในโค้ด. เก็บไว้ในตัวแปรสภาพแวดล้อมหรือระบบจัดการความลับ อย่าเขียนตายตัวลงไฟล์ที่คุณ commit
- เปลี่ยนคีย์ด้วยการบันทึกซ้ำ. กรอกที่อยู่รับข้อมูลเดิมพร้อมคีย์ใหม่แล้วกด Save channel — Orova จะเขียนทับช่องทางเดิม อย่าลืมอัปเดตฝั่ง endpoint ไปพร้อมกัน
- ตัดการเชื่อมต่อคือลบคีย์. เมื่อคุณตัดการเชื่อมต่อช่องทาง Orova จะลบคีย์ลับที่เก็บไว้ และหยุดส่งข้อมูลไปที่อยู่นั้น
/ สรุป
ข้อตกลงมีเท่านี้
ที่อยู่ https หนึ่งที่ คีย์ลับหนึ่งอัน ตรวจลายเซ็นหนึ่งครั้ง และรหัส 2xx หนึ่งรหัส เท่านี้โพสต์จาก Orova Social ก็ไหลเข้าระบบของคุณ ส่วนที่เหลือ — จะเผยแพร่ต่อที่ไหน เก็บไว้ที่ใด บันทึกอย่างไร — คุณเป็นคนกำหนด
/ ต้องการความช่วยเหลือ
ติดขัดตอนต่อ endpoint ใช่ไหม เปิดส่วนสนับสนุนในพื้นที่ทำงานของคุณ หรือ ส่งข้อความถึงเรา
