Skip to main content

ตั้งค่ายืนยัน OTP (OTP Verification Config)

ภาพรวม

หน้าตั้งค่ายืนยัน OTP (/otp-config) คือที่เก็บข้อมูลรับรอง (credential) และเทมเพลตข้อความสำหรับส่งรหัส OTP ในระดับ LINE OA หนึ่งบัญชี หน้านี้ไม่ได้กำหนดว่าฟอร์มใดต้องยืนยันตัวตน (การตั้งค่านั้นอยู่ในแท็บการยืนยันตัวตนของ Form Builder) แต่เป็นชั้นล่างที่ตอบคำถามว่า LINE OA นี้ "ส่ง OTP ออกไปได้ทางช่องทางใดบ้าง"

หน้าจอนี้เหมาะกับผู้ดูแลระบบที่ตั้งค่าครั้งเดียวให้ทั้งบัญชี เมื่อกำหนดเสร็จแล้วทีมที่สร้างฟอร์มจึงจะเปิดการยืนยันตัวตนในฟอร์มของตนได้

ระบบรองรับ 2 ช่องทาง

ช่องทางผู้ให้บริการข้อมูลที่ต้องกรอก
SMSThaiBulkSMSAPI Key และ Secret
อีเมลSMTP ที่ตั้งไว้ระดับ channelหัวข้ออีเมล และเนื้อหาอีเมลที่ต้องมีตัวแปร {otp}

ลักษณะเฉพาะของฟีเจอร์ที่ควรทราบ

  • เป็นการตั้งค่าชุดเดียวต่อ 1 LINE OA จึงไม่มีหน้ารายการ ไม่มีการสร้างใหม่ และไม่มีการลบ มีเพียงการอ่านค่าปัจจุบันและบันทึกทับ
  • ระบบจะแสดงฟอร์มได้เสมอแม้ยังไม่เคยตั้งค่ามาก่อน โดยเติมค่าเริ่มต้นของหัวข้อและเนื้อหาอีเมลไว้ให้
  • ค่า Secret ของ SMS ถูกอ่านกลับมาแบบปิดบังบางส่วนเท่านั้น (เช่น ab****yz) และแสดงเป็นข้อความแนะนำในช่องกรอก การบันทึกโดยเว้นช่อง Secret ว่างไว้หมายถึง "คงค่าเดิมที่บันทึกไว้" ไม่ใช่การล้างค่า
  • ระบบสรุปสถานะความพร้อมของแต่ละช่องทางเป็นป้ายกำกับบนการ์ด คือ กำหนดค่าแล้ว หรือ ยังไม่ได้กำหนดค่า สถานะนี้เป็นตัวเดียวกับที่ Form Builder ใช้ตัดสินว่าช่องทางนั้นเลือกได้หรือไม่
  • เมนูอยู่ใต้กลุ่ม Settings ของเมนูด้านข้าง และเข้าถึงได้จาก Quick Access

เงื่อนไขที่ทำให้แต่ละช่องทางถือว่าพร้อมใช้งาน

ช่องทางถือว่าพร้อมเมื่อ
SMSเปิดสวิตช์ SMS มี API Key และมี Secret บันทึกไว้ในระบบแล้ว
อีเมลเปิดสวิตช์อีเมล มีหัวข้ออีเมล และเนื้อหาอีเมลมีตัวแปร {otp}

ตัวแปรที่ใช้ในเทมเพลตอีเมล

ตัวแปรบังคับความหมาย
{otp}ใช่รหัส OTP ที่ระบบสร้างขึ้น ระบบตรวจสอบทั้งฝั่งหน้าจอและฝั่งเซิร์ฟเวอร์
{ref}ไม่รหัสอ้างอิงของการส่งครั้งนั้น

ระบบเตรียมหัวข้อและเนื้อหาอีเมลเริ่มต้นไว้ให้ตามภาษาที่ผู้ใช้งานเลือกอยู่ เพื่อให้เริ่มใช้งานได้ทันทีโดยไม่ต้องเขียนเทมเพลตเอง ตัวอย่างเนื้อหาเริ่มต้นภาษาไทย

รหัส OTP ของคุณคือ <b>{otp}</b> จะหมดอายุใน 3 นาที

ค่าเริ่มต้นเหล่านี้ถูกเติมลงฟอร์มเฉพาะตอนโหลดข้อมูล หากเปลี่ยนภาษาของระบบระหว่างอยู่ในหน้านี้ ควรโหลดหน้าใหม่เพื่อให้ได้ข้อความเริ่มต้นตามภาษาที่เลือก

ส่วนข้อความที่ปรากฏบนหน้ายืนยันตัวตนของผู้กรอกฟอร์ม เช่น หัวข้อ คำอธิบาย ปุ่มยืนยัน และปุ่มขอรหัสใหม่ ไม่ได้ตั้งที่หน้านี้ แต่ตั้งแยกรายฟอร์มในแท็บการยืนยันตัวตนของ Form Builder

Business Flow

ตั้งค่าข้อมูลรับรอง

  1. เข้าหน้า /otp-config ระบบตรวจสิทธิ์ VIEW ของโมดูล OTP Config ก่อนแสดงผล พร้อมตั้ง breadcrumb และไฮไลต์เมนู Settings
  2. ระบบอ่านค่าการตั้งค่าปัจจุบันของ LINE OA และแสดงตัวหมุนรอโหลดจนกว่าข้อมูลจะพร้อม จึงจะ render ฟอร์ม
  3. เมื่อข้อมูลมาถึง ระบบเติมค่าลงฟอร์ม ได้แก่ สถานะเปิด/ปิดของทั้งสองช่องทาง API Key ของ SMS หัวข้ออีเมล และเนื้อหาอีเมล หากยังไม่เคยตั้งหัวข้อหรือเนื้อหา ระบบใช้ข้อความมาตรฐานที่เตรียมไว้ตามภาษาของผู้ใช้
  4. ช่อง Secret ของ SMS จะถูกล้างเป็นค่าว่างเสมอ ค่าที่ปิดบังบางส่วนจะไปแสดงเป็นข้อความแนะนำในช่องแทน เพื่อสื่อว่าเว้นว่างไว้ได้หากไม่ต้องการเปลี่ยน
  5. การ์ด SMS ประกอบด้วยสวิตช์เปิดใช้งาน ช่อง API Key และช่อง Secret แบบซ่อนข้อความ ส่วนการ์ดอีเมลประกอบด้วยสวิตช์เปิดใช้งาน ช่องหัวข้อ และช่องเนื้อหาแบบหลายบรรทัด พร้อมคำอธิบายตัวแปรที่ใช้ได้
  6. ระบบตรวจสอบความถูกต้องฝั่งหน้าจอเฉพาะช่องทางอีเมล และเฉพาะเมื่อเปิดสวิตช์อีเมลไว้ โดยหัวข้อต้องไม่ว่าง และเนื้อหาต้องไม่ว่างและต้องมีตัวแปร {otp} อยู่ในข้อความ
  7. ฝั่ง SMS ไม่มีการตรวจสอบก่อนส่ง หากเปิดสวิตช์แล้วไม่กรอก Key หรือ Secret ระบบจะปล่อยให้กดบันทึกได้ และเซิร์ฟเวอร์จะเป็นผู้ปฏิเสธพร้อมส่งข้อความอธิบายกลับมาแสดง
  8. กดปุ่มบันทึกการตั้งค่า ระบบประกอบข้อมูลแล้วส่งไปบันทึกทับค่าเดิม พร้อมแสดงสถานะกำลังโหลดระหว่างดำเนินการ
  9. เมื่อบันทึกสำเร็จ ระบบแจ้งผลและอ่านค่าใหม่กลับมาทันที ป้ายสถานะบนการ์ดและค่า Secret ที่ปิดบังจะอัปเดตตามค่าล่าสุด ส่วนช่อง Secret กลับไปเป็นค่าว่างอีกครั้ง
  10. หากบันทึกไม่สำเร็จ ระบบนำข้อความจาก API มาแสดงตรง ๆ เช่น กรณีเปิด SMS แต่ไม่มี Key หรือ Secret หรือกรณีเนื้อหาอีเมลไม่มีตัวแปร {otp} หากไม่มีข้อความจาก API จะแสดงข้อความผิดพลาดมาตรฐานแทน

ข้อควรระวังในการใช้งาน

  • หน้านี้ไม่มีการเตือนเมื่อออกจากหน้าโดยยังไม่บันทึก ค่าที่แก้ไว้จะหายไปทั้งหมด
  • ไม่มีปุ่มทดสอบส่ง OTP และไม่มีหน้าดูประวัติการส่งในโมดูลนี้ การตรวจสอบความพร้อมทำได้จากป้ายสถานะบนการ์ดเท่านั้น
  • ไม่มีทางอ่านค่า Secret เดิมกลับมาจากหน้าจอ หากจำค่าเดิมไม่ได้ต้องออก Key และ Secret ชุดใหม่จากผู้ให้บริการแล้วกรอกใหม่ทั้งคู่
  • การปิดสวิตช์ช่องทางใดช่องทางหนึ่งมีผลทันทีกับทุกฟอร์มที่ใช้ช่องทางนั้น จึงควรตรวจสอบก่อนว่ามีฟอร์มที่กำลังเปิดใช้งานอยู่หรือไม่

ลำดับการใช้งานร่วมกับ Form Builder

  1. ผู้ดูแลระบบตั้งค่าข้อมูลรับรองที่หน้านี้ กรอก Key และ Secret ของ SMS และ/หรือหัวข้อกับเนื้อหาอีเมล แล้วเปิดสวิตช์ช่องทางที่ต้องการ จากนั้นบันทึก
  2. ระบบคำนวณสถานะความพร้อมของแต่ละช่องทางกลับมา ป้ายบนการ์ดเปลี่ยนเป็น กำหนดค่าแล้ว
  3. ผู้ดูแลฟอร์มเปิดฟอร์มที่ต้องการใน Form Builder แล้วเปิด Profile Mapping พร้อมเลือก Member Database ซึ่งเป็นเงื่อนไขบังคับ เพราะรหัส OTP จะถูกส่งไปยังคอลัมน์ของระเบียนที่ค้นหาเจอ ไม่ใช่ค่าที่ผู้ใช้กรอกในฟอร์ม
  4. ไปที่แท็บการยืนยันตัวตนแล้วเปิดสวิตช์ ระบบจะสร้างแถวตั้งค่าให้ 1 แถวโดยเลือกช่องทางที่พร้อมใช้งานให้อัตโนมัติ จากนั้นเลือกคอลัมน์ปลายทางที่จะส่งรหัสไป
  5. หากยังไม่มีช่องทางใดพร้อมใช้งาน แท็บดังกล่าวจะแสดงแถบเตือนพร้อมลิงก์กลับมายังหน้านี้ และปิดปุ่มเพิ่มฟิลด์ไว้ ส่วนช่องทางที่ยังไม่ตั้งค่าจะถูกปิดไม่ให้เลือกในดรอปดาวน์
  6. หากภายหลังปิดช่องทางที่หน้านี้ ฟอร์มที่เปิด OTP ไว้แล้วจะยังคงการตั้งค่าเดิมและแสดงแถบเตือนแทน ระบบไม่ปิด OTP ของฟอร์มให้อัตโนมัติ

หน้าจอและองค์ประกอบหลัก

หน้าจอเป็นฟอร์มหน้าเดียวประกอบด้วยการ์ด 2 ใบและปุ่มบันทึกด้านล่าง

การ์ดช่องทาง SMS

  • ป้ายสถานะ — แสดงว่าช่องทางนี้พร้อมใช้งานแล้วหรือยัง คำนวณจากฝั่งเซิร์ฟเวอร์
  • สวิตช์เปิดใช้งาน — เปิดหรือปิดการส่ง OTP ทาง SMS
  • ช่อง API Key — ข้อมูลรับรองจาก ThaiBulkSMS อ่านกลับมาแสดงได้ตามปกติ
  • ช่อง Secret — ช่องกรอกแบบซ่อนข้อความ แสดงค่าเดิมแบบปิดบังเป็นข้อความแนะนำ เว้นว่างไว้เพื่อคงค่าเดิม

การ์ดช่องทางอีเมล

  • ป้ายสถานะ — เช่นเดียวกับการ์ด SMS
  • สวิตช์เปิดใช้งาน — เปิดหรือปิดการส่ง OTP ทางอีเมล
  • ช่องหัวข้ออีเมล — บังคับกรอกเมื่อเปิดใช้งาน
  • ช่องเนื้อหาอีเมล — ช่องข้อความหลายบรรทัดแบบ monospace รองรับการเขียน HTML โดยตรง (ไม่ใช่ตัวแก้ไขแบบ rich text) และต้องมีตัวแปร {otp}
  • คำอธิบายตัวแปร — ป้ายช่วยเหลือที่ระบุตัวแปรที่ใช้ได้ในเทมเพลต

ไฟล์อ้างอิงหลัก: src/app/otp-config/page.tsx, src/components/otp-config/otp-config-form.tsx

บริการฝั่ง API

รวมอยู่ที่ src/services/otp-config.service.ts ภายใต้ path หลัก otp-config

ความสามารถEndpointหมายเหตุ
อ่านการตั้งค่าปัจจุบันGET /otp-configชุดเดียวต่อ LINE OA คืนค่าเริ่มต้นเมื่อยังไม่เคยตั้งค่า จึงไม่เกิดกรณีไม่พบข้อมูล
บันทึกการตั้งค่าPUT /otp-configบันทึกทับค่าเดิม เว้น Secret ว่างไว้เพื่อคงค่าเดิม และคืนข้อมูลรูปแบบเดียวกับการอ่าน

ข้อมูลที่รับส่งประกอบด้วยสถานะเปิด/ปิดของทั้งสองช่องทาง API Key ของ SMS หัวข้อและเนื้อหาอีเมล และสถานะความพร้อมของแต่ละช่องทางที่คำนวณจากฝั่งเซิร์ฟเวอร์ โดยการอ่านค่าจะได้ Secret แบบปิดบังเท่านั้น ส่วนการบันทึกจึงจะส่ง Secret ตัวจริงขึ้นไป

จุดเชื่อมต่อกับฟีเจอร์อื่น

  • สิทธิ์การใช้งาน — หน้านี้ถูกควบคุมด้วยโมดูล form-builder เช่นเดียวกับ Form Builder ไม่มีโมดูลแยกเฉพาะสำหรับ OTP ดังนั้นการปิดโมดูล Form Builder จะทำให้เมนูนี้หายไปด้วย
  • Form Builder — เป็นผู้ใช้ค่าการตั้งค่านี้เพียงรายเดียวในฝั่ง CMS โดยแท็บการยืนยันตัวตนอ่านสถานะความพร้อมของช่องทางมาใช้เป็นเงื่อนไข ขณะที่หน้านี้เองไม่ทราบว่ามีฟอร์มใดเปิดใช้ OTP อยู่บ้าง
  • Member Database — ไม่เกี่ยวข้องกับหน้านี้โดยตรง แต่เป็นเงื่อนไขจำเป็นของฝั่งฟอร์ม เพราะรหัส OTP ถูกส่งไปยังคอลัมน์ของระเบียนสมาชิกที่จับคู่ได้
  • ThaiBulkSMS — ผู้ให้บริการ SMS ภายนอก ข้อมูลรับรองถูกเก็บไว้ฝั่งเซิร์ฟเวอร์ ระบบ CMS มองเห็นได้เพียงค่าที่ปิดบังแล้ว
  • การตั้งค่า SMTP ระดับ channel — ช่องทางอีเมลใช้เซิร์ฟเวอร์ส่งอีเมลที่ตั้งไว้ในระดับ channel หน้านี้กำหนดได้เฉพาะหัวข้อและเนื้อหาเท่านั้น
  • โครงสร้างพื้นฐานร่วม — ใช้ระบบยืนยันตัวตนและ HTTP client กลางของ CMS ซึ่งผูกข้อมูลไว้กับ LINE OA ที่ล็อกอินอยู่โดยอัตโนมัติ (ไม่ต้องส่งรหัส OA ใน URL) รวมถึงระบบ breadcrumb เมนูด้านข้าง และสถานะ loading กลางของแอปพลิเคชัน

รายละเอียดฝั่ง Backend (CMS API)

โค้ดฝั่ง backend อยู่ที่ internal/modules/otpconfig/ เป็น โมดูลที่เขียนขึ้นใหม่ ไม่ได้ย้ายมาจากระบบเดิม โครงสร้างโค้ดอ้างอิงรูปแบบของโมดูล Quick Reply แต่ต่างกันตรงที่โมดูลนี้เป็น singleton คือมีข้อมูลได้ชุดเดียวต่อ LINE OA ไม่ใช่ CRUD หลายแถว

ทำไมจึงมีแค่ 2 endpoint

  • ตาราง otp_config กำหนดให้ค่าอ้างอิง LINE OA เป็นค่าที่ห้ามซ้ำ (unique) จึงเป็นไปไม่ได้ที่จะมีการตั้งค่าสองชุดใน OA เดียว
  • ผลคือไม่มี endpoint สร้างและไม่มี endpoint ลบ มีเพียง GET /api/otp-config สำหรับอ่าน และ PUT /api/otp-config ซึ่งเป็นการ upsert (มีแถวอยู่แล้วก็อัปเดต ไม่มีก็สร้างให้)
  • การยังไม่เคยตั้งค่าถือเป็นสถานะปกติ ไม่ใช่ข้อผิดพลาด backend จึงคืนโครงสร้างค่าว่าง/ค่าเริ่มต้นกลับมา ไม่ตอบว่า "ไม่พบข้อมูล" นี่คือเหตุผลที่หน้าจอ render ฟอร์มได้เสมอโดยไม่ต้องมีกรณีจัดการหน้าว่าง

สิทธิ์ที่ต้องมี

  • ทั้งสอง route ต้องผ่านการยืนยันตัวตนกลาง (JWT) และ token ต้องมี LINE OA ที่เลือกไว้ เพราะ backend ใช้ค่านี้ในการหาแถวการตั้งค่าที่ถูกต้อง — ไม่มีการส่งรหัส OA มาทาง URL หรือ body เลย
  • ข้อสังเกต — โมดูลนี้ ไม่ได้ครอบด้วย module gate และ policy ที่ประกาศไว้ยังเป็นเพียงข้อมูลกำกับที่ยังไม่บังคับใช้
  • ที่น่าสนใจคือ backend ประกาศชื่อ policy แยกไว้เป็น otp-config ของตัวเอง (ตั้งให้ตรงกับชื่อเมนูฝั่ง CMS เผื่อเปิดใช้ในอนาคต) ขณะที่ ฝั่งหน้าจอกลับควบคุมเมนูนี้ด้วยสิทธิ์ของโมดูล form-builder ทั้งสองฝั่งจึงยังมองการแบ่งสิทธิ์ของหน้านี้ไม่ตรงกัน

สิ่งที่บันทึกและผลข้างเคียง (Side Effect)

  • ข้อมูลทั้งหมดอยู่ในตาราง otp_config เพียงตารางเดียว โมดูลนี้ไม่เขียน cache และไม่ส่งงานเข้าคิว
  • การบันทึกมีผลทันทีกับทุกฟอร์มที่เปิด OTP ไว้ เพราะฟอร์มไม่ได้เก็บสำเนาข้อมูลรับรองไว้เอง แต่อ่านค่าจากตารางนี้ตอนใช้งานจริง
  • ผู้ส่งและตรวจ OTP จริงคือ line-management-client-api-go ไม่ใช่ cms-api หน้านี้เป็นเพียงที่เก็บข้อมูลรับรองและเทมเพลต การกดบันทึกสำเร็จจึงไม่ได้พิสูจน์ว่าข้อมูลรับรองใช้ส่งได้จริง
  • เมื่อผู้กรอกยืนยัน OTP สำเร็จแล้วเท่านั้น ฝั่ง client-api จึงจะยอมรับการส่งฟอร์ม — ถ้าปิด OTP ฟอร์มจะรับคำตอบได้ทันทีโดยไม่ต้องยืนยัน

Edge Case และข้อสังเกตที่ควรรู้

  • เพราะเป็น upsert ที่เขียนทับทั้งชุด การบันทึกทุกครั้งคือการแทนที่ค่าเดิมทั้งหมด ไม่ใช่การแก้ทีละฟิลด์ กติกาที่ว่า "เว้นช่อง Secret ว่างไว้เพื่อคงค่าเดิม" จึงเป็นตรรกะที่ backend ต้องจัดการให้ ไม่ใช่ผลข้างเคียงตามธรรมชาติของการเขียนทับ
  • ไม่มี endpoint สำหรับทดสอบส่งจริง และไม่มีที่เก็บประวัติการส่งในโมดูลนี้ การยืนยันว่าข้อมูลรับรองถูกต้องจึงทำได้ทางเดียวคือทดลองส่งฟอร์มจริง
  • โมดูลนี้ไม่รู้ว่ามีฟอร์มใดกำลังใช้ช่องทางใดอยู่ การปิดสวิตช์ช่องทางจึงไม่มีการเตือนใด ๆ จาก backend และไม่มีการปิด OTP ของฟอร์มให้อัตโนมัติ
  • ข้อมูลถูกจำกัดขอบเขตตาม LINE OA ที่เลือกอยู่เสมอ การสลับ OA ในระบบ CMS จึงเท่ากับเปลี่ยนไปดูการตั้งค่าคนละชุดโดยสิ้นเชิง