การเชื่อมเครื่อง POS ด้วยรหัสเชื่อมเครื่อง
แอปแคชเชียร์ ไม่มีหน้าล็อกอินด้วยชื่อผู้ใช้/รหัสผ่าน เครื่องแต่ละเครื่องพิสูจน์ตัวตนด้วย "รหัสเชื่อมเครื่อง" (device token) หนึ่งค่าที่ผู้ดูแลออกจากหน้าตั้งค่า POS ใน BC Ai Account (ดู ตั้งค่าและควบคุมระบบขายหน้าร้าน POS (PosSetupAndControlScreen)) แล้วนำมาวางในแอป ภาพรวมระบบดู ระบบ POS ขายหน้าร้าน ภาพรวม การเปิดใช้ และแผนที่บันทึก (sys-pos-overview)
ขั้นตอนใช้งาน
- ผู้ดูแลออกรหัสให้เครื่องที่ลงทะเบียนไว้แล้วในตั้งค่า POS (ฝั่งเซิร์ฟเวอร์อธิบายใน POS ซิงก์ข้อมูลเครื่องแคชเชียร์ ผูกเครื่อง/ดึงส่วนต่าง/กู้คืน/รูปภาพ (POS Device Sync) ส่วนโทเคนเครื่องและการผูกเครื่อง)
- ในแอป กดปุ่มตั้งค่าเครื่องที่แถบบน แล้วเปิดแท็บ "เครื่อง POS & ค่าจาก BC Ai Account" (
settings_dialog.dart:143) - วางรหัสในช่อง "รหัสเชื่อมเครื่อง" (ช่องซ่อนตัวอักษร) แล้วกด "เชื่อมเครื่อง" (
settings_dialog.dart:530-551) - แอปตัดช่องว่างทิ้ง ตรวจว่าขึ้นต้นด้วย
bcpos1.ถ้าไม่ใช่แจ้ง "รหัสเชื่อมเครื่องไม่ถูกต้อง" (settings_dialog.dart:643-652) ช่องว่างกดแล้วไม่ทำอะไร - แอปบันทึกรหัส ล้างรูปแบบเลขที่บิลเดิม ล้างสถานะผิดพลาด ล้างแคชรูป แล้วสั่งซิงก์ทันทีเพื่อดึงข้อมูลเครื่องนี้ (
pos_provider.dart:311-335)
บนแอป Windows/มือถือ ถ้ายังไม่ได้เชื่อม ป้ายสถานะแสดง "ยังไม่เชื่อมเครื่อง" และข้อความ "ยังไม่ได้เชื่อมเครื่อง กรุณาวางรหัสเชื่อมเครื่องในตั้งค่า" (pos_provider.dart:44) แอปยังเปิดจอขายได้ แต่ออกบิล รับ-ส่งเงิน และยกเลิกบิลไม่ได้จนกว่าจะเชื่อม
แอปที่ฝังในหน้าเว็บ /pos ไม่ต้องวางรหัส
บน Flutter Web ที่ฝังอยู่ในหน้า /pos ถ้ายังไม่เคยวางรหัส แอปใช้ตัวบ่งชี้ bcpos1.web แทน จึงนับว่า "เชื่อมแล้ว" และซิงก์ได้ทันที (storage_service.dart:150-156) คำขอทั้งหมดผ่านพร็อกซี /api/pos/* ของเว็บ ซึ่งแนบโทเคนของผู้ใช้ที่ล็อกอินอยู่และฐานข้อมูลที่เลือกอยู่ไปยังเซิร์ฟเวอร์ (frontend/src/app/api/pos/[...path]/route.ts:45-54) ถ้าไม่มีเซสชันเว็บ พร็อกซีใช้รหัสเครื่องที่แอปส่งมา (รูปแบบ bcpos1. ตามด้วยอักขระอย่างน้อย 20 ตัว) และถ้ารหัสเครื่องนั้นถูกปฏิเสธ 401 ขณะมีเซสชันเว็บ พร็อกซีสลับไปใช้เซสชันเว็บแทน (route.ts:17,47,66-77) เส้นทาง /api/pos/* ที่แอปทุกแพลตฟอร์มเรียกมีอยู่ในพร็อกซีของเว็บ ส่วนหลังบ้านใช้ /api/v1/pos/* (API จุดขาย POS (POS endpoints /api/v1/pos)) ดังนั้นช่อง "ที่อยู่เซิร์ฟเวอร์" ของแอป Windows/มือถือ ต้องชี้ไปที่เว็บ BC Ai Account
กลไกของรหัส (ไม่แสดงค่า)
- ทุกคำขอไปยังเซิร์ฟเวอร์ส่งหัว
Authorization: Bearer <รหัส>เครื่อง ฐานข้อมูล และบริษัทถูกอ่านจากรหัสฝั่งเซิร์ฟเวอร์ จึงไม่มีพารามิเตอร์?db=หรือหัวX-Holdingในคำขอของแอป (api_service.dart:34-57) - ที่อยู่เซิร์ฟเวอร์: ถ้าไม่กรอกในช่อง "ที่อยู่เซิร์ฟเวอร์ BC Ai Account" แอปแบบเว็บใช้ origin ของหน้าเดียวกัน ส่วนแอปบน Windows/มือถือใช้ค่าเริ่มต้นเป็นเครื่องตัวเองที่พอร์ต 3001 (
api_service.dart:41-50) - การเก็บ: รหัสไม่ถูกเก็บเป็นข้อความเปล่า แต่แปลงด้วยคีย์สุ่มของเครื่องแล้วเก็บใน
SharedPreferences(ชื่อคีย์ลงท้าย_v2_enc) และมีการย้ายจากรุ่นเก่าที่เคยเก็บเป็นข้อความเปล่าให้อัตโนมัติ (storage_service.dart:17-19,39,142-175) รหัสห้ามถูก log หรือพิมพ์ออกหน้าจอ - รูปแบบรหัสและการตรวจฝั่งเซิร์ฟเวอร์ (ขึ้นต้น
bcpos1.เก็บเฉพาะแฮชของความลับฝั่ง DB) อยู่ใน POS ซิงก์ข้อมูลเครื่องแคชเชียร์ ผูกเครื่อง/ดึงส่วนต่าง/กู้คืน/รูปภาพ (POS Device Sync) และ POS Sync API: เครื่อง POS เชื่อมกับ Account (POS device sync)
เมื่อรหัสถูกยกเลิก (401)
เซิร์ฟเวอร์ตอบ 401 → SyncEngine ตั้งสถานะ unauthorized แสดง "รหัสเชื่อมเครื่องถูกยกเลิก กรุณาขอรหัสใหม่" และหยุดซิงก์ทั้งหมดจนกว่าจะวางรหัสใหม่ (sync_engine.dart:26,194-208, :164) การวางรหัสใหม่จะล้างสถานะนี้ (sync_engine.dart:76-80)
กฎกันข้อมูลหาย: เปลี่ยน/ถอดรหัสไม่ได้ถ้ามีของค้างส่ง
ถ้าเครื่องมีบิลหรือรูปใบเสร็จที่ยังไม่ขึ้นเซิร์ฟเวอร์ (รอส่งหรือถูกปฏิเสธ) การเปลี่ยนรหัสจะถูกบล็อกพร้อมข้อความบอกจำนวนที่ค้าง เพราะรหัสใหม่อาจเป็นคนละเครื่อง/คนละบริษัท ข้อยกเว้นคือรหัสเดิมโดน 401 ซึ่งส่งอะไรไม่ได้อยู่แล้ว (sync_engine.dart:90-101, pos_provider.dart:311-319) ฟังก์ชันถอดเครื่อง (ส่งรหัสว่าง) มีในตัวแอปแต่หน้าตั้งค่าไม่เรียกด้วยค่าว่าง
หลังเชื่อมครั้งแรก
เมื่อดึงข้อมูลรอบแรกเสร็จ ถ้าเครื่องยังว่างจริง (ไม่มีบิลในคิว ไม่มีกะ ไม่มีรายการรับ-ส่งเงิน) แอปจะกู้คืนกะและบิลของเครื่องนี้จากเซิร์ฟเวอร์ให้อัตโนมัติหนึ่งครั้ง (sync_engine.dart:104-110,194) รายละเอียดใน กะแคชเชียร์ รับ-ส่งเงิน ยกเลิกบิล และกู้คืนข้อมูลเครื่อง POS (sys-pos-shift-cash)
ที่มาในโค้ด
frontend/pos/lib/ui/widgets/settings_dialog.dart:530-551,643-659ช่องวางรหัสและการตรวจรูปแบบfrontend/pos/lib/providers/pos_provider.dart:309-335ตั้ง/เปลี่ยนรหัสและผลที่ตามมาfrontend/pos/lib/services/api_service.dart:34-57หัว Bearer และที่อยู่เซิร์ฟเวอร์frontend/pos/lib/services/storage_service.dart:90-175การเก็บรหัสแบบแปลงค่าfrontend/pos/lib/services/sync_engine.dart:76-110,194-208สถานะ 401 ตัวบล็อกการเปลี่ยนรหัส และกู้คืนอัตโนมัติ- ดูเพิ่ม: ระบบ POS ขายหน้าร้าน ภาพรวม การเปิดใช้ และแผนที่บันทึก (sys-pos-overview) · การซิงก์ฝั่งแอป POS ส่งบิลขึ้น ดึงข้อมูลลง และลองใหม่ (sys-pos-sync-client) · POS ซิงก์ข้อมูลเครื่องแคชเชียร์ ผูกเครื่อง/ดึงส่วนต่าง/กู้คืน/รูปภาพ (POS Device Sync) · POS Sync API: เครื่อง POS เชื่อมกับ Account (POS device sync) · API จุดขาย POS (POS endpoints /api/v1/pos) · ตั้งค่าและควบคุมระบบขายหน้าร้าน POS (PosSetupAndControlScreen)