Kiến Trúc Hệ Thống & Đặc Tả Cấu Trúc API (App & POS)
Ngày cập nhật: 20/06/2026
Nguồn dữ liệu: Review chính sách App - Kiến trúc và cấu trúc API.csv
Tài liệu này đặc tả kiến trúc đồng bộ dữ liệu thời gian thực và cấu trúc các API endpoints kết nối giữa Client Mobile App, Cloud Backend và Hệ thống POS (Point of Sale) tại các chi nhánh.
1. Mô Hình Kiến Trúc Đồng Bộ (Synchronization Architecture)
Để đảm bảo hệ thống vận hành ổn định ngay cả khi chi nhánh gặp sự cố mất mạng (offline), kiến trúc hệ thống được thiết kế theo mô hình 3 lớp đồng bộ qua hàng đợi tin nhắn (Message Queue) hoặc cơ chế Webhook + Polling thay vì gọi trực tiếp từ App xuống POS:
graph TD
App[Tier 1: Mobile App<br>Giao diện Khách hàng] <-->|Rest API / GraphQL| Backend[Tier 2: Cloud Backend<br>Xử lý Logic & Core DB]
Backend <-->|Websocket / MQTT / Webhook| POS[Tier 3: POS System<br>Lễ tân / Thu ngân chi nhánh]
- Tier 1: Mobile App (Frontend): Giao diện dành cho khách hàng tìm kiếm dịch vụ, đặt lịch hẹn healing/wellness và theo dõi ví điểm thưởng GPoint.
- Tier 2: Cloud Backend (Core System): Hệ thống máy chủ trung tâm lưu trữ cơ sở dữ liệu chính (Master Database) quản lý điểm thưởng, hạng thành viên, cấu hình minigame và trạng thái các booking.
- Tier 3: POS System (Local / Branch): Phần mềm quản lý và máy tính tính tiền đặt tại quầy lễ tân của từng chi nhánh, có nhiệm vụ xác thực trạng thái vật lý của lịch hẹn (Check-in, Check-out, In hóa đơn).
2. Cỗ Máy Trạng Thái Booking (Booking State Machine)
Trạng thái của một lượt đặt lịch (booking) được quản lý nghiêm ngặt theo mô hình cỗ máy trạng thái một chiều (State Machine), không cho phép nhảy cóc trạng thái để đảm bảo tính toàn vẹn của dữ liệu:
stateDiagram-v2
[*] --> PENDING : Khách đặt lịch trên App
PENDING --> CONFIRMED : Lễ tân bấm nhận trên POS
CONFIRMED --> CHECKED_IN : Khách đến Spa & check-in
CHECKED_IN --> COMPLETED : Khách thanh toán & checkout
PENDING --> CANCELLED : Hủy lịch
CONFIRMED --> CANCELLED : Hủy lịch / Quá giờ (No-show)
CHECKED_IN --> CANCELLED : Hủy lịch
- PENDING (Chờ xác nhận)
- CONFIRMED (Đã chốt lịch)
- CHECKED_IN (Khách đã đến chi nhánh)
- COMPLETED (Đã thanh toán thành công - trạng thái cuối)
- CANCELLED (Đã hủy lịch / Khách không đến - No-show)
3. Thiết Kế Các Luồng API Chi Tiết
Luồng 1: Khách đặt lịch từ App (App ➡️ Backend ➡️ POS)
Khi khách chọn dịch vụ và giờ đến, App gửi dữ liệu lên Backend. Backend lập tức đẩy thông báo thời gian thực về máy POS tại chi nhánh.
- API 1: Khách tạo lịch đặt mới
- Endpoint:
POST /api/v1/bookings(App ➡️ Backend) - Payload mẫu (JSON):
{"user_id": "123","branch_id": "Q2","services": ["healing_massage"],"time": "2026-06-20 14:00"}
- Endpoint:
- Event 2: Đẩy thông báo thời gian thực
- Cơ chế: Websocket / MQTT (Backend ➡️ POS)
- Hành vi: Hệ thống Backend bắn event
NEW_BOOKINGkèm chuông thông báo trực quan trên màn hình POS của lễ tân chi nhánh.
- API 3: Lễ tân bấm nhận lịch
- Endpoint:
PUT /api/v1/admin/bookings/{id}/confirm(POS ➡️ Backend) - Payload mẫu (JSON):
{"status": "CONFIRMED","staff_id": "LT_01"}
- Endpoint:
Luồng 2: Khách sử dụng xong và Thanh toán (POS ➡️ Backend ➡️ App)
Đây là luồng quan trọng nhất để tránh sai lệch báo cáo doanh thu ảo. Trạng thái COMPLETED chỉ được kích hoạt bằng hành động bấm thanh toán của lễ tân tại quầy.
- API 1: Lễ tân in hóa đơn & thanh toán
- Endpoint:
POST /api/v1/pos/webhook/checkout(POS ➡️ Backend) - Payload mẫu (JSON):
{"booking_id": "B_999","status": "COMPLETED","total_paid": 1500000,"payment_method": "CASH"}
- Endpoint:
- Xử lý nội bộ (Internal Logic):
- Backend đọc trường
total_paid, nhân tỷ lệ tích điểm theo hạng thành viên hiện tại của khách hàng. - Cộng điểm tích lũy GPoint vào ví khách hàng.
- Kiểm tra và cập nhật tiến trình thăng hạng thành viên.
- Backend đọc trường
- Thông báo cho khách hàng:
- Cơ chế: Push Notification (Backend ➡️ App)
- Nội dung: “Cảm ơn bạn đã trải nghiệm dịch vụ. Bạn được cộng +150 Point.”
Luồng 3: Xử lý Hủy lịch / Khách không đến (No-show)
Giải phóng slot đặt chỗ khi quá giờ hoặc khách chủ động hủy lịch.
- API 1: Tự động quét lịch trễ (Cron Job)
- Endpoint:
/internal/jobs/check-noshow(Chạy nội bộ Backend) - Cơ chế: Hệ thống chạy ngầm tự động quét các lịch ở trạng thái
CONFIRMEDnhưng đã quá giờ hẹn (ví dụ quá 30 phút). Tự động chuyển trạng thái sangCANCELLED(lý do: No-show).
- Endpoint:
- API 2: Hủy lịch thủ công
- Endpoint:
PUT /api/v1/admin/bookings/{id}/cancel(POS ➡️ Backend) - Payload mẫu (JSON):
(Trạng thái trên ứng dụng của khách hàng sẽ lập tức cập nhật thành "Đã hủy").{"status": "CANCELLED","reason": "Khách báo bận đột xuất","staff_id": "LT_01"}
- Endpoint:
4. Giải Pháp Kỹ Thuật Chống Lỗi (Fault Tolerance)
Để hệ thống vận hành trơn tru và không bị sai lệch dữ liệu khi đường truyền mạng của chi nhánh không ổn định, bắt buộc triển khai 2 giải pháp sau:
4.1. Chống cộng điểm trùng lặp bằng Idempotency Key
- Vấn đề: Khi mạng chập chờn, lễ tân có thể click nút "Thanh toán" nhiều lần hoặc máy POS gửi trùng request thanh toán. Điều này dễ dẫn đến lỗi cộng x2, x3 số điểm thưởng cho khách hàng.
- Giải pháp:
- Yêu cầu mọi request thanh toán từ POS gửi lên Backend phải đính kèm một mã định danh giao dịch duy nhất trong Header gọi là Idempotency-Key (ví dụ:
Idempotency-Key: tx_unique_999). - Hệ thống Backend sẽ lưu trữ các mã Key này. Nếu nhận được request có mã Key trùng lặp đã được xử lý thành công trước đó, Backend lập tức từ chối xử lý và chỉ trả về kết quả của giao dịch đầu tiên.
- Yêu cầu mọi request thanh toán từ POS gửi lên Backend phải đính kèm một mã định danh giao dịch duy nhất trong Header gọi là Idempotency-Key (ví dụ:
4.2. Cơ chế Lưu trữ & Chuyển tiếp khi mất mạng (Offline Store & Forward)
- Vấn đề: Chi nhánh Spa bị đứt cáp quang hoặc mất mạng diện rộng, lễ tân không thể kết nối tới Cloud Backend để cập nhật trạng thái đơn hàng.
- Giải pháp:
- Khi mất kết nối mạng, phần mềm POS vẫn cho phép lễ tân thực hiện Check-out và in Bill bình thường.
- Dữ liệu giao dịch offline sẽ được lưu trữ tạm thời tại bộ nhớ cục bộ (SQLite hoặc LocalStorage) trên máy tính POS chi nhánh.
- Một Background Service (dịch vụ chạy ngầm) trên POS sẽ liên tục kiểm tra kết nối mạng. Ngay khi phát hiện có mạng trở lại, service này sẽ tự động gửi bù (Forward) toàn bộ request
POST /webhook/checkoutbị kẹt lên Cloud Backend để đồng bộ điểm số và hạng thành viên cho khách hàng.