🎯 Tổng Quan Vấn Đề
Vấn Đề Ban Đầu
Triệu chứng: Bot không phản hồi tin nhắn mặc dù đã cấu hình kịch bản (scripts) trong database.
🔴 Hiện tượng quan sát được:
- Webhook nhận tin nhắn từ Facebook ✅
- Tin nhắn được lưu vào database ❓
- Bot hoàn toàn im lặng - không phản hồi ❌
- Không có lỗi rõ ràng trong log ⚠️
Context: Migration Architecture
Hệ thống đã được migrate từ single-user sang multi-user SAAS architecture:
| Aspect | Before (V4.x) | After (V5.2) |
|---|---|---|
| Architecture | Single-user (1 page) | Multi-user SAAS (nhiều users, nhiều pages) |
| Primary Table | facebook_config |
facebook_pages |
| Page Management | 1 page cố định | Multiple pages, is_active flag |
| Data Isolation | Không cần | Bắt buộc theo user_id |
🔍 Phân Tích Nguyên Nhân Gốc Rễ
❌ LỖI #1: getUserIdFromPageId() Query Sai Bảng
Vấn Đề:
Function vẫn query từ bảng facebook_config trong khi data đã migrate sang facebook_pages
❌ CODE CŨ (SAI):
Chuỗi Lỗi:
✅ GIẢI PHÁP:
Query từ bảng facebook_pages
✅ CODE MỚI (ĐÚNG):
fb_webhook.php, dòng ~2700⚡ Impact: CRITICAL - Toàn bộ hệ thống không hoạt động nếu không fix
❌ LỖI #2: getFacebookAccessToken() Query Sai Bảng
Vấn Đề:
Function query access token từ facebook_config nhưng token đã migrate sang facebook_pages
❌ CODE CŨ (SAI):
- Function trả về empty string
- Bot không gửi được message về Facebook (vì không có token)
- Ngay cả khi có response, user vẫn không nhận được
✅ GIẢI PHÁP:
Query từ facebook_pages với điều kiện is_active = 1
✅ CODE MỚI (ĐÚNG):
fb_webhook.php, dòng ~2450⚡ Impact: HIGH - Bot không gửi được tin nhắn
❌ LỖI #3: User ID Isolation Failure
Vấn Đề:
Conversations và customers bị tạo với sai user_id (fallback về user_id = 1 hoặc NULL)
Tình huống thực tế:
Data Mismatch:
| Table | user_id | Status |
|---|---|---|
| bot_scripts | 36 | ✅ Đúng |
| facebook_pages | 36 | ✅ Đúng |
| conversations | 1 / NULL | ❌ SAI |
| customers | 1 / NULL | ❌ SAI |
✅ GIẢI PHÁP:
Bắt buộc lấy user_id từ page_id, KHÔNG FALLBACK
✅ FIX trong processWebhookTextMessageEnhanced():
✅ FIX trong updateCustomerInfo():
⚠️ LỖI #4: Message Cache Duplicate Check Bug
Vấn Đề:
markMessageAsProcessed() trả về false ngay cả khi message chưa được xử lý
Triệu chứng trong log:
- Table structure issue với UNIQUE key
INSERT IGNOREkhông insert nhưng cũng không báo lỗiaffected_rows= 0 mặc dùexecute()trả về TRUE
✅ GIẢI PHÁP TẠM THỜI:
Skip duplicate check để test, log warning nhưng vẫn tiếp tục xử lý
✅ FIX:
fb_webhook.php, trong processWebhookTextMessageEnhanced()⚡ Impact: MEDIUM - Tạm thời skip để test, cần fix vĩnh viễn sau
🔄 Workflow Hoàn Chỉnh
❌ Workflow CŨ (LỖI):
✅ Page ID: 557849694089307
✅ Sender ID: 24502905112710899
✅ Message: "test"
❌ Query: SELECT user_id FROM facebook_config WHERE page_id = ?
❌ Result: NULL (bảng không có page_id)
❌ user_id = NULL
❌ Data isolation thất bại
❌ Query: SELECT * FROM bot_scripts WHERE user_id = NULL
❌ Result: EMPTY
❌ Type: SILENT
❌ No message sent to Facebook
✅ Workflow MỚI (ĐÚNG):
✅ Page ID: 557849694089307
✅ Sender ID: 24502905112710899
✅ Message: "test"
✅ Query: SELECT user_id FROM facebook_pages WHERE page_id = ?
✅ Result: user_id = 36
✅ user_id = 36
✅ Data isolation thành công
✅ Query: SELECT * FROM bot_scripts WHERE user_id = 36
✅ Result: Script ID 25 (Multi-step)
✅ Script executed successfully
✅ Multiple messages sent
✅ Query: SELECT page_access_token FROM facebook_pages WHERE user_id = 36
✅ Token found
✅ Messages sent to Facebook successfully
✅ User receives responses
🛠️ Hướng Dẫn Triển Khai Fix
Checklist Thực Hiện
- Backup database và code trước khi sửa
- Sửa
getUserIdFromPageId()- Query từfacebook_pages - Sửa
getFacebookAccessToken()- Query từfacebook_pages - Sửa
processWebhookTextMessageEnhanced()- Lấy user_id từ page_id - Sửa
updateCustomerInfo()- Không fallback user_id - Tạm thời skip duplicate check để test
- Upload code lên server
- Test với tin nhắn thực tế
- Verify data trong database
- Monitor webhook logs
Testing & Verification
1. Test Webhook Reception:
2. Verify Database:
3. Test với Keyword:
Gửi tin nhắn với keyword đó vào page → Bot phải phản hồi ✅
🗄️ Database Schema Reference
Bảng facebook_pages (Primary Table)
Bảng facebook_config (Settings Only)
Data Isolation Pattern
Nguyên tắc quan trọng:
- MỌI query phải filter theo
user_id - KHÔNG bao giờ fallback về
user_id = 1hoặc mặc định - Nếu không tìm được
user_id→ Bot im lặng (đúng hành vi) - Mỗi user chỉ thấy data của mình
Example Queries:
📚 Bài Học Rút Ra
1. Migration Must Be Complete
Khi migrate architecture, phải update TẤT CẢ functions query database. Không được bỏ sót một function nào.
- ✅ Search toàn bộ code với keyword của bảng cũ (vd: "facebook_config")
- ✅ List tất cả functions query bảng đó
- ✅ Update từng function một
- ✅ Test từng function sau khi update
- ✅ Integration test toàn bộ workflow
2. Data Isolation Is Critical
Trong multi-user system, KHÔNG BAO GIỜ fallback về user_id mặc định. Tốt hơn là bot im lặng còn hơn phản hồi sai data.
- Không có user_id → Không xử lý
- Log error rõ ràng
- Bot im lặng là hành vi đúng (không leak data)
3. Debug Systematically
Debug theo workflow từ đầu đến cuối:
- Webhook có nhận tin nhắn không?
- page_id có đúng không?
- user_id có được lấy ra không?
- Conversations có được lưu không?
- Scripts có được query không?
- Keyword có match không?
- Response có được generate không?
- Token có hợp lệ không?
- Message có được gửi về Facebook không?
4. Logging Is Essential
Thêm logging chi tiết tại mọi bước quan trọng:
⚡ Quick Reference
3 Functions Cần Fix
| Function | File | Line ~ | Fix |
|---|---|---|---|
getUserIdFromPageId() |
fb_webhook.php | 2700 | Query từ facebook_pages |
getFacebookAccessToken() |
fb_webhook.php | 2450 | Query từ facebook_pages |
updateCustomerInfo() |
fb_webhook.php | 2600 | Không fallback user_id |