เปลี่ยน Signing Secret ของ UnifyPort Webhook อย่างปลอดภัย
หากต้องการเปลี่ยน signing_secret ของ UnifyPort webhook ให้เตรียมตัวรับทุกอินสแตนซ์ให้ตรวจสอบได้ทั้งคีย์ปัจจุบันและคีย์ใหม่ก่อนอัปเดต endpoint จากนั้นยืนยันว่าการส่งรายการใหม่ตรวจสอบด้วยคีย์ใหม่ได้ แล้วจึงนำคีย์เก่าออกตามเกณฑ์การเปลี่ยนผ่าน นี่เป็นกระบวนการที่แอปพลิเคชันจัดการเอง: API สาธารณะระบุ signing secret หนึ่งค่าต่อ endpoint ไม่ได้ระบุช่วงใช้สองคีย์พร้อมกันที่เซิร์ฟเวอร์จัดการให้ หรือรับประกันว่าจะไม่มีข้อมูลสูญหายระหว่างเปลี่ยนคีย์
ประเด็นสำคัญ
- เปลี่ยน webhook signing secret แยกจาก REST API key
- อย่าส่ง
signing_secretเป็นค่าว่างเพื่อใช้เป็นขั้นตอนกลาง เพราะจะปิดการลงลายเซ็น - จำกัดชุดคีย์ชั่วคราวให้ตรงกับ endpoint และสภาพแวดล้อมนั้นเท่านั้น
- อย่าใช้การส่งซ้ำเป็นช่วงผ่อนผันสำหรับการ deploy
แยกหน้าที่ของคีย์และจุดที่อาจผิดพลาด
X-Api-Key ใช้ยืนยันคำขอที่คุณส่งไปยัง UnifyPort ส่วน signing_secret ของ endpoint ใช้ตรวจสอบการส่งที่เข้ามายังแอปพลิเคชัน การเปลี่ยนค่าใดค่าหนึ่งไม่ได้เปลี่ยนอีกค่า หากกำลังจัดการฝั่งเรียก REST ให้ใช้ คู่มือเปลี่ยน API key แยกต่างหาก
เอกสารการส่ง webhook กำหนดให้ X-Device-Signature เป็น HMAC-SHA256 แบบเลขฐานสิบหก โดยนำ X-Device-Timestamp รูปแบบ RFC 3339 ตามด้วยจุดหนึ่งตัวและ request body ดิบมาเป็นข้อมูลที่ลงลายเซ็น การเปลี่ยนคีย์ไม่เปลี่ยนรูปแบบข้อมูลนี้หรือโครงสร้าง event
ตัวรับที่ใช้คีย์ไม่ตรงกันอาจปฏิเสธ event ที่ถูกต้อง ข้อกำหนดปัจจุบันระบุว่าจะลองส่งใหม่ทันทีเมื่อเกิดข้อผิดพลาดการเชื่อมต่อหรือ HTTP 408, 429 และ 5xx โดยไม่มี backoff ส่วน 4xx อื่นจะไม่ลองใหม่ ดังนั้น 401 ที่เกิดจากการเปลี่ยนคีย์เร็วเกินไปจึงไม่ใช่สิ่งที่ควรคาดหวังว่า deploy รอบถัดไปจะแก้คืนให้อัตโนมัติ การตอบ 503 ก็ไม่ได้สร้างคิวพักงานช่วงบำรุงรักษาที่เชื่อถือได้
วางแผนด้วยการตั้งค่าสามช่วง
ตารางนี้เป็นลำดับ deploy ที่แนะนำ ไม่ใช่ฟีเจอร์เปลี่ยนคีย์ในตัวของ UnifyPort
| ช่วง | การตั้งค่า endpoint | คีย์ที่ตัวรับยอมรับ |
|---|---|---|
| เตรียม | คีย์ปัจจุบัน | คีย์ปัจจุบันและคีย์ใหม่ |
| สลับ | คีย์ใหม่ | คีย์ปัจจุบันและคีย์ใหม่ |
| นำคีย์เก่าออก | คีย์ใหม่ | คีย์ใหม่เท่านั้น |
ก่อนเริ่ม ให้บันทึก endpoint ID, URL, สถานะ, event ที่สมัครรับ, นโยบาย retry, อินสแตนซ์ตัวรับ และผู้รับผิดชอบ เก็บค่าคีย์ไว้ในระบบจัดการข้อมูลลับ ไม่ใส่ในบันทึกการเปลี่ยนแปลง สร้างคีย์ใหม่ที่เป็นอิสระจากคีย์เดิมและกระจายผ่านช่องทาง deploy ที่ปลอดภัยตามปกติ
คง URL, subscriptions และค่า retry ไว้เหมือนเดิมในงานนี้ การย้ายทางเข้าข้อมูลพร้อมกับเปลี่ยนการยืนยันตัวตนทำให้หาสาเหตุความผิดพลาดยากขึ้น หากสงสัยว่าคีย์เก่ารั่วไหล อย่าใช้ช่วงซ้อนทับตามปกติ เพราะการยอมรับคีย์นั้นต่อไปทำให้ความเสี่ยงยังอยู่ ให้ใช้แผนตอบสนองเหตุการณ์ที่กำหนดเรื่องความพร้อมใช้งานและการตรวจสอบข้อมูลตกหล่นอย่างชัดเจน
เตรียมตัวรับทุกตัวก่อนเปลี่ยนฝั่งส่ง
กำหนดชุดคีย์ขนาดเล็กชั่วคราวไว้ในการตั้งค่า route ที่เชื่อถือได้ อย่าเลือกคีย์จาก provider, account_id ที่ยังไม่ผ่านการตรวจสอบ หรือ header เวอร์ชันคีย์ที่คิดขึ้นเอง header การส่งที่ระบุในเอกสารไม่มีตัวระบุ signing key
ฟังก์ชันตัวอย่างต่อไปนี้ตรวจสอบคีย์ทุกตัวโดยไม่คืนค่าทันทีเมื่อพบตัวแรกที่ตรงกัน ไม่ใช่ HTTP receiver ฉบับสมบูรณ์หรือผลการทดสอบที่รันแล้ว keys ต้องเป็นอาร์เรย์สตริงคีย์ที่ไม่ว่างและใช้เฉพาะ endpoint นี้ ส่วน maxAgeMs คือค่าความคลาดเคลื่อนเวลาที่แอปพลิเคชันเลือก ซึ่งต้องเป็นจำนวนบวกที่มีค่าจำกัด
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyDuringRotation({
rawBody, timestamp, signature, keys, maxAgeMs,
}) {
if (!Array.isArray(keys) || keys.length === 0 ||
keys.some(key => typeof key !== 'string' || key.length === 0) ||
!Number.isFinite(maxAgeMs) || maxAgeMs <= 0) {
throw new Error('Invalid webhook verification configuration');
}
if (!Buffer.isBuffer(rawBody) || typeof timestamp !== 'string' ||
typeof signature !== 'string' || !/^[0-9a-f]{64}$/i.test(signature)) {
return false;
}
const signedAt = Date.parse(timestamp);
if (!Number.isFinite(signedAt) ||
Math.abs(Date.now() - signedAt) > maxAgeMs) return false;
const supplied = Buffer.from(signature, 'hex');
let matches = 0;
for (const key of keys) {
const expected = createHmac('sha256', key)
.update(timestamp + '.').update(rawBody).digest();
matches |= Number(timingSafeEqual(supplied, expected));
}
return matches !== 0;
}
เอกสาร Node.js Crypto อธิบายฟังก์ชัน HMAC และการเปรียบเทียบเหล่านี้ เก็บไบต์ดิบไว้และปฏิเสธคำขอที่ไม่มีลายเซ็น อย่าเพิ่มทางเลือกที่ยอมรับคำขอแบบไม่ลงลายเซ็น หลังตรวจสอบผ่านแล้วจึงตรวจ payload และบันทึกอย่างถาวร คู่มือป้องกัน replay ด้วย HMAC อธิบายว่าทำไมการตรวจอายุคำขอและการจัดการข้อมูลซ้ำยังจำเป็นแม้ลายเซ็นจะตรงกัน
ทดสอบคีย์ปัจจุบัน คีย์ใหม่ คีย์ผิด body ที่ถูกแก้ไข ลายเซ็นที่หายไป และ timestamp ที่เก่าเกินไปกับทุกชุด deployment ของตัวรับ นี่คือกรณีทดสอบที่แนะนำ ไม่ใช่การอ้างว่าโค้ดได้รันในระบบของคุณแล้ว
อัปเดต endpoint โดยไม่ปิดลายเซ็น
อ่านค่าปัจจุบันด้วย Get webhook endpoint จากนั้นใช้ Update webhook endpoint เรียก PATCH /v1/webhook-endpoints/{endpoint_id} โดยยืนยันตัวตนด้วย REST API key
สร้างคำขอจาก URL, สถานะ active, subscriptions และนโยบาย retry ปัจจุบันที่ตรวจสอบแล้ว พร้อมใส่คีย์ใหม่ใน signing_secret อย่าคัดลอกคีย์ว่างหรือสถานะ inactive จากตัวอย่างในเอกสารไปใช้กับการสลับระบบจริง คีย์ว่างหมายถึงปิดลายเซ็น ไม่ใช่ขอให้เปลี่ยนคีย์อัตโนมัติ
อ่านค่ากลับมาและตรวจ signing_enabled: true รวมถึงการตั้งค่าอื่นที่ต้องไม่เปลี่ยน ธงนี้ยืนยันเพียงว่าเปิดลายเซ็นอยู่ ไม่ได้บอกว่าใช้คีย์ใด ส่งข้อความทดสอบที่ควบคุมได้ไปยังบัญชีรับส่งข้อความที่เชื่อมต่อ แล้วติดตาม message.received รายการใหม่ผ่านการตรวจด้วยคีย์ใหม่ การบันทึกถาวร และการประมวลผลภายในที่คาดไว้ ห้ามบันทึกคีย์ลง log หรือใช้เนื้อหาของลูกค้าเป็นข้อมูลทดสอบ
หากผลอัปเดตไม่ชัดเจน ให้คงตัวตรวจสองคีย์ไว้ระหว่างตรวจการตั้งค่าและทดสอบรายการใหม่ อย่านำคีย์เก่าออกเพียงเพราะส่ง PATCH แล้ว
กำหนดเกณฑ์เลิกใช้คีย์เก่า ไม่เดาระยะรอ
เอกสารสาธารณะไม่ได้ระบุว่ารายการที่อยู่ในคิวยังคงใช้การตั้งค่าลายเซ็นเดิมหรือไม่ และไม่ได้กำหนดเวลาซ้อนทับสูงสุด retry_policy.max_attempts นับจำนวน retry ไม่ใช่วินาทีของช่วงผ่อนผัน หากต้องการรับรองการเปลี่ยนแบบไม่หยุดชะงัก ควรยืนยันพฤติกรรมของงานที่กำลังส่งกับ UnifyPort ก่อน
ใช้การ deploy ครบทุกตัว รายการใหม่ที่ตรวจผ่านคีย์ใหม่ ข้อผิดพลาดที่สังเกตจากตัวรับ และแผนจัดการงานระหว่างส่งที่ตกลงไว้เป็นเกณฑ์เลิกใช้คีย์เก่า ในตัวชี้วัดการปฏิบัติงานให้เก็บเฉพาะป้ายเวอร์ชันการตรวจสอบที่ไม่เป็นความลับ ตัวรับที่เงียบไม่ได้พิสูจน์ว่ารายการที่ใช้คีย์เก่าหมดแล้ว
เมื่อผ่านเกณฑ์ ให้นำคีย์เก่าออกจากตัวรับทุกตัวและแหล่งตั้งค่า deployment ทดสอบในสภาพแวดล้อมแยกว่าคีย์เก่าถูกปฏิเสธแล้ว กำหนดจุดสิ้นสุดของช่วงซ้อนทับอย่างชัดเจน ไม่ยอมรับคีย์ในอดีตตลอดไป
หากต้อง rollback และคีย์เก่ายังเชื่อถือได้ ให้ประสานทั้งการตั้งค่า endpoint และชุดคีย์ของตัวรับ อย่าคืนตัวรับที่ยอมรับเฉพาะคีย์เก่าในขณะที่ endpoint ยังลงลายเซ็นด้วยคีย์ใหม่ หากสงสัยการรั่วไหล อย่านำคีย์ที่เปิดเผยแล้วกลับมาใช้
ขอบเขตและข้อจำกัด
อินเทอร์เฟซที่ไม่เป็นทางการของ UnifyPort ทำให้ event ของบัญชีรับส่งข้อความที่รองรับ รวมถึง LINE อยู่ในรูปแบบเดียวกัน ขั้นตอนนี้ปกป้องการส่งจาก UnifyPort ไปยังตัวรับ ไม่ได้เปลี่ยนข้อมูลรับรองดั้งเดิมของ LINE หรือ Telegram, เซสชันการเข้าสู่ระบบ หรือ API key
บันทึก event ที่ตรวจสอบแล้วอย่างถาวรก่อนตอบ 2xx event ปกติที่ส่งซ้ำสามารถตัดซ้ำด้วย event ID ได้ แต่ WhatsApp conversation.history ต้องรวมข้อมูลระดับข้อความตามข้อกำหนด ไม่ตัดทิ้งทั้งชุดจาก ID ระดับบนเพียงค่าเดียว UnifyPort ไม่มี REST API สำหรับอ่านประวัติข้อความหรือการรับประกันส่ง payload ที่พลาดย้อนหลัง จึงไม่ควรอ้างว่าข้อมูลที่หายระหว่างเปลี่ยนคีย์กู้คืนอัตโนมัติได้
คำถามที่พบบ่อย
Endpoint เดียวตั้ง signing_secret สองค่าได้หรือไม่?
ข้อกำหนดสาธารณะระบุ signing_secret หนึ่งค่า ตัวตรวจสองคีย์ชั่วคราวในบทความเป็นตรรกะของแอปพลิเคชัน ไม่ใช่การตั้งค่าสองคีย์ใน API
ปิดลายเซ็นชั่วคราวเพื่อให้เปลี่ยนง่ายขึ้นได้ไหม?
ไม่ควร ให้เปิดลายเซ็นไว้และปฏิเสธเมื่อไม่มีข้อมูลยืนยันตัวตน คีย์ว่างทำให้ header ลายเซ็นหายไป ไม่ใช่กลไกเปลี่ยนผ่าน
ควรยอมรับคีย์เก่านานเท่าไร?
ไม่มีระยะเวลาสากลที่ระบุไว้ ใช้ผลตรวจ deployment และการส่ง ยืนยันพฤติกรรมงานระหว่างส่ง และกำหนดเกณฑ์สิ้นสุดที่มีขอบเขตตามความเสี่ยงของระบบ
ขั้นตอนถัดไปและแหล่งอ้างอิง
อ่าน Update webhook endpoint และซ้อมการตั้งค่าทั้งสามช่วงในสภาพแวดล้อมแยกก่อนเปลี่ยนระบบจริง
ตรวจสอบเอกสารเมื่อ 2026-09-27:
เปลี่ยนการเชื่อมต่อข้อความให้เป็น pipeline ผลิตภัณฑ์ที่เสถียร
เริ่มจากการส่งผ่าน API เดียว แล้วส่งข้อความขาเข้าทั้งหมดกลับสู่ระบบธุรกิจของคุณด้วย event มาตรฐาน