วิธีเชื่อมต่อ PDPA
ฝัง consent banner ในระบบของคุณด้วย <script> ตัวเดียว — รองรับทุกภาษา. เลือกแท็บตามเทคโนโลยีของระบบ
ลงทะเบียนระบบ
สร้าง app ที่หน้า ระบบที่เชื่อม → ได้ appKey + subjectSecret แล้ว publish policy v1
ฝัง loader
ฝัง <script> พร้อมเซ็น subject ด้วย HMAC (ดูโค้ดตามภาษาด้านล่าง)
เสร็จ
widget เช็ค consent เดิม → โชว์ banner เมื่อต้อง → บันทึกการตัดสินใจ → ยิง event pdpa-consent
subjectSecret เป็น server secret ห้ามขึ้น browser — จุดนี้ตัดสินว่าคำนวณ signature ตรงไหนNext.js, PHP, Laravel, Django
เซ็น sig ตอน render หน้า แล้วฝัง tag ได้เลย
ไม่ต้องเพิ่ม endpoint
Angular, React SPA, Vue, PWA
browser ถือ secret ไม่ได้ → backend อ่าน session คืน { subject, ts, sig } ให้ SPA ฝัง
เพิ่ม 1 endpoint เล็ก ๆ
SPA ไม่มี backend เลย
HMAC ทำไม่ได้ → fallback trust-origin (ส่งแค่ appKey + subject)
proof อ่อนกว่า — รับได้สำหรับ cookie consent
.env / Portainer). ไม่ต้องใส่ appSecret (สงวนไว้สำหรับ server-to-server อนาคต)PDPA_HUB_URL=https://pdpa.web.rmutsv.ac.th
PDPA_APP_KEY=app_xxxxxxxx # from the app detail page
PDPA_SUBJECT_SECRET=xxxxxxxx # server secret — never expose to the browserimport { createHmac } from "node:crypto";
// Server component — subjectSecret never reaches the browser.
export default function ConsentScript({ subject }: { subject?: string | null }) {
const hub = process.env.PDPA_HUB_URL;
const appKey = process.env.PDPA_APP_KEY;
const secret = process.env.PDPA_SUBJECT_SECRET;
if (!hub || !appKey || !secret || !subject) return null;
const ts = Math.floor(Date.now() / 1000).toString();
const sig = createHmac("sha256", secret).update(`${subject}|${ts}`).digest("hex");
return (
<script
src={`${hub}/widget/v1/loader.js`}
data-app-key={appKey}
data-api={hub}
data-subject={subject}
data-ts={ts}
data-sig={sig}
async
/>
);
}import ConsentScript from "@/components/consent-script";
// ...
const session = await getSession();
// inside <body>, render only when logged in:
<ConsentScript subject={session?.user?.username} />window.addEventListener("pdpa-consent", (e) => {
const c = e.detail; // { decision, categories: { NECESSARY, ANALYTICS, ... }, policyVersion }
if (c.categories.ANALYTICS) {
// โหลด analytics
}
});<!-- ปุ่มลอยมาเองอยู่แล้ว — ปิดเฉพาะ app นี้ด้วย data-fab="off" -->
<script src="https://pdpa.web.rmutsv.ac.th/widget/v1/loader.js" data-app-key="..." data-fab="off" ...></script>
<!-- หรือทำปุ่มเองในตำแหน่งที่ต้องการ -->
<button onclick="window.pdpa.open()">จัดการคุกกี้</button>banner ไม่ขึ้น + /api/v1/policy ตอบ 404
ยังไม่ได้ publish policy (draft ไม่นับ) → ไปที่ app → policy → publish
CORS error ตอนเรียก /api/v1/consent
origin ของระบบไม่อยู่ใน allow-list → เพิ่ม origin (dev + prod) ที่หน้า app detail
POST /consent ตอบ 401 invalid subject proof
sig ผิด หรือ ts เก่าเกิน 10 นาที (clock เพี้ยน) หรือ subjectSecret ไม่ตรงกับที่ register
env เป็น undefined / script ไม่โผล่
framework อ่าน .env ตอน start เท่านั้น → restart dev server หลังแก้ env
กลัว secret หลุด
subjectSecret ใช้ฝั่ง server เท่านั้น — ห้าม prefix NEXT_PUBLIC_ / ห้ามใส่ใน bundle ของ SPA
