OROVA.VN — BIZ AI AGENT

/ Hướng dẫn cho lập trình viên

Nhận bài đăng từ Orova Social qua Webhook.

Cách dựng một endpoint nhận bài Orova Social gửi sang, và xác minh chữ ký trước khi xử lý.

Orova Social đăng thẳng lên các nền tảng đã nối sẵn. Muốn đưa bài đến một nơi khác — kênh nội bộ, ứng dụng của bạn, một nền tảng Orova chưa hỗ trợ — bạn dùng kênh API: Orova gửi bài sang một địa chỉ HTTP của bạn, ký bằng khoá bí mật, và bạn tự làm phần còn lại. Trang này dành cho lập trình viên và mô tả đủ hợp đồng request.

/ Tổng quan

Cách hoạt động

Bạn khai một địa chỉ nhận bài (https://) và một khoá bí mật cho kênh API của dự án. Orova gửi tới đó một request POST với thân JSON, kèm header X-Orova-Signature — chữ ký HMAC-SHA256 tính trên đúng chuỗi byte của thân request bằng khoá bí mật đó. Endpoint của bạn kiểm chữ ký, nhận bài, rồi trả về mã 2xx.

  • Địa chỉ nhận bài phải là https. Orova từ chối lưu kênh nếu địa chỉ không phải https:// hoặc thiếu tên miền — báo mã api_url.
  • Một kênh API cho mỗi địa chỉ. Orova nhận diện kênh theo chính địa chỉ nhận bài. Lưu lại cùng một địa chỉ là ghi đè kênh cũ, không đẻ thêm kênh trùng.
  • Có nút Gửi thử. Kênh nối xong có nút Gửi thử: Orova bắn ngay một gói orova.test sang endpoint của bạn và hiện lại mã HTTP kèm thời gian trả lời tính bằng mili giây.

/ Cài đặt

Thiết lập trong Orova

Mở SocialDự án → chọn dự án → tab Kênh, rồi tìm ô API. Ô này có hai chỗ nhập và một nút.

  • 1

    URL nhận bài (webhook). Địa chỉ endpoint của bạn, bắt đầu bằng https://. Đây là nơi Orova gửi mọi request.

  • 2

    Mã bí mật. Chuỗi dùng để ký. Để trống thì Orova tự sinh một chuỗi ngẫu nhiên — nhưng màn hình không hiện lại mã đó, nên hãy tự sinh một chuỗi dài rồi dán vào, và cất bản sao ở phía bạn.

  • 3

    Bấm Save channel. Kênh hiện ngay trong danh sách kèm địa chỉ nhận bài. Mã bí mật không bao giờ hiện lại trên màn hình.

  • 4

    Bấm Gửi thử. Orova gửi một gói mẫu orova.test. Endpoint trả về mã 2xx thì Orova báo “Webhook trả về 200 sau … ms”. Trả mã khác thì báo lỗi kèm mã đó; không gọi tới được thì báo lỗi mạng.

/ Hợp đồng

Hợp đồng request

Mỗi lần gửi, Orova bắn sang một request có dạng như sau:

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"
  }

Thân request là JSON UTF-8 gọn, không xuống dòng. Hãy đọc event để biết loại sự kiện — gói của nút Gửi thử mang orova.test, và header X-Orova-Event lặp lại đúng giá trị đó. Endpoint nên bỏ qua trường lạ thay vì báo lỗi, để phần mở rộng sau này không làm hỏng phía bạn.

TrườngKiểuMô tả
eventstringLoại sự kiện. Gói của nút Gửi thử là "orova.test".
workspace_idintegerID khu làm việc gửi gói này.
project_idinteger | nullID dự án chứa kênh, hoặc null nếu kênh chưa gán dự án.
postobjectNội dung bài đăng.
post.titlestringTiêu đề bài.
post.contentstringThân bài dạng chữ.
post.mediaarrayDanh sách tệp đính kèm của bài; mảng rỗng khi bài chỉ có chữ.
post.channelsarray of stringCác loại kênh mà bài này nhắm tới, ví dụ ["api"].
sent_atstringThời điểm Orova gửi, chuẩn ISO 8601 theo giờ UTC, kết thúc bằng "Z".

/ Xác minh

Xác minh chữ ký

Header X-Orova-Signature có dạng sha256=<hex>, trong đó <hex> là HMAC-SHA256 của chuỗi byte thô của thân request, khoá là mã bí mật của kênh. Hãy tính lại chữ ký trên đúng chuỗi byte nhận được — đọc JSON ra rồi tạo chuỗi lại là sai, vì chỉ cần lệch một dấu cách là chữ ký khác.

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

So chữ ký bằng hàm so sánh hằng thời gian (crypto.timingSafeEqual, hmac.compare_digest), đừng dùng phép so bằng thường. Chữ ký không khớp thì trả 401 và dừng — đừng xử lý gói đó.

/ Trả lời

Trả lời thế nào

Orova chỉ nhìn mã trạng thái HTTP. Mọi mã trong nhóm 2xx là thành công; thân response bạn trả gì cũng được.

  • Trả lời nhanh. Nút Gửi thử chờ tối đa 10 giây. Việc nặng — tải ảnh, gọi API bên thứ ba — hãy đẩy vào hàng đợi rồi trả 2xx ngay.
  • Orova không tự thử lại. Đây là chủ ý: tự thử lại với API đăng bài dễ làm bài lên hai lần. Lần gửi hỏng thì bài bị đánh dấu failed kèm lý do, và người dùng bấm đăng lại trong Orova.
  • Nên chịu được gói trùng. Người dùng bấm đăng lại là gói cũ đi lại lần nữa. Hãy tự khử trùng lặp ở phía bạn — ví dụ nhớ lại cặp workspace_id + sent_at đã xử lý.

/ Bảo mật

Bảo mật

  • Luôn kiểm chữ ký. Endpoint của bạn là một URL công khai — ai cũng gọi được. Chữ ký là thứ duy nhất chứng minh gói tin thật sự đến từ Orova.
  • Giữ mã bí mật ngoài mã nguồn. Cất ở biến môi trường hoặc kho bí mật, đừng viết cứng vào file rồi commit.
  • Đổi mã bí mật bằng cách lưu lại. Nhập lại chính địa chỉ nhận bài đó kèm mã mới rồi bấm Save channel — Orova ghi đè kênh cũ. Đổi xong nhớ cập nhật luôn phía endpoint.
  • Ngắt kênh là xoá mã. Bấm ngắt kênh thì Orova xoá mã bí mật đã lưu, và không gửi gì sang địa chỉ đó nữa.

/ Khép lại

Hợp đồng chỉ có vậy

Một địa chỉ https, một mã bí mật, một lần kiểm chữ ký và một mã 2xx — đủ để bài từ Orova Social chảy về hệ thống của bạn. Phần còn lại là việc của bạn: đăng tiếp đi đâu, lưu ở đâu, ghi sổ thế nào.

← Về thư viện hướng dẫn

/ Cần hỗ trợ?

Nối endpoint mãi chưa được? Mở mục Hỗ trợ trong khu làm việc, hoặc gửi tin nhắn cho chúng tôi.