Đánh Dấu Thông Báo Đã Đọc
API đánh dấu thông báo đã đọc cho khách hàng. Hỗ trợ đánh dấu một thông báo, nhiều thông báo, hoặc tất cả thông báo chưa đọc. Có thể lọc theo loại thông báo khi đánh dấu tất cả.
GET/POST https://api.socdo.vn/mini-app/v1/update-notification
Request Headers
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Content-Type: application/json
Request Parameters (GET) / Request Body (POST)
Tham số Loại Bắt buộc Mô tả
Authorization header JWT token từ API login (Bearer token)
notification_id integer - ID của thông báo cần đánh dấu đã đọc (chỉ đánh dấu 1 thông báo)
notification_ids array - Mảng ID các thông báo cần đánh dấu đã đọc (đánh dấu nhiều thông báo)
mark_all boolean - Đánh dấu tất cả thông báo chưa đọc đã đọc (true/false)
type string - Lọc theo loại thông báo khi mark_all = true (order, voucher_new, etc.)
Các Cách Sử Dụng
Cách Tham số Mô tả
Đánh dấu 1 thông báo notification_id Đánh dấu một thông báo cụ thể đã đọc
Đánh dấu nhiều thông báo notification_ids (array) Đánh dấu nhiều thông báo cùng lúc
Đánh dấu tất cả mark_all = true Đánh dấu tất cả thông báo chưa đọc đã đọc
Đánh dấu tất cả theo loại mark_all = true + type Đánh dấu tất cả thông báo chưa đọc của một loại cụ thể
Response thành công - Đánh dấu 1 thông báo (200)
{
    "success": true,
    "message": "Đã đánh dấu thông báo đã đọc",
    "data": {
        "notification_id": 582,
        "read_at": 1762934433
    }
}
Response thành công - Đánh dấu nhiều thông báo (200)
{
    "success": true,
    "message": "Đã đánh dấu 3 thông báo đã đọc",
    "data": {
        "notification_ids": [582, 581, 580],
        "affected_count": 3,
        "read_at": 1762934433
    }
}
Response thành công - Đánh dấu tất cả (200)
{
    "success": true,
    "message": "Đã đánh dấu 15 thông báo đã đọc",
    "data": {
        "affected_count": 15,
        "mark_all": true,
        "type": null
    }
}
Response thành công - Đánh dấu tất cả theo loại (200)
{
    "success": true,
    "message": "Đã đánh dấu 8 thông báo đã đọc",
    "data": {
        "affected_count": 8,
        "mark_all": true,
        "type": "order"
    }
}
Response lỗi (400 - Thiếu tham số)
{
    "success": false,
    "message": "Vui lòng cung cấp notification_id, notification_ids (mảng), hoặc mark_all = true"
}
Response lỗi (400 - Danh sách ID không hợp lệ)
{
    "success": false,
    "message": "Danh sách ID thông báo không hợp lệ"
}
Response lỗi (401 - Token không hợp lệ)
{
    "success": false,
    "message": "Token không hợp lệ - không có user_id"
}
Response lỗi (404 - Không tìm thấy)
{
    "success": false,
    "message": "Không tìm thấy thông báo hoặc không có quyền truy cập"
}
Response lỗi (500 - Lỗi hệ thống)
{
    "success": false,
    "message": "Lỗi xử lý đánh dấu thông báo đã đọc",
    "error": "Error message details"
}
Ví dụ JavaScript
// Đánh dấu một thông báo đã đọc
async function markNotificationAsRead(notificationId) {
    try {
        const authToken = localStorage.getItem('auth_token');
        
        if (!authToken) {
            throw new Error('Chưa đăng nhập');
        }
        
        const response = await fetch(`https://api.socdo.vn/mini-app/v1/update-notification?notification_id=${notificationId}`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${authToken}`
            }
        });
        
        const result = await response.json();
        
        if (result.success) {
            console.log('Đã đánh dấu thông báo đã đọc:', result.data);
            return result;
        } else {
            console.error('Lỗi:', result.message);
            return result;
        }
    } catch (error) {
        console.error('Lỗi kết nối:', error);
        return { success: false, message: 'Lỗi kết nối mạng' };
    }
}

// Đánh dấu nhiều thông báo đã đọc
async function markMultipleNotificationsAsRead(notificationIds) {
    try {
        const authToken = localStorage.getItem('auth_token');
        
        const response = await fetch('https://api.socdo.vn/mini-app/v1/update-notification', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${authToken}`
            },
            body: JSON.stringify({
                notification_ids: notificationIds
            })
        });
        
        const result = await response.json();
        
        if (result.success) {
            console.log(`Đã đánh dấu ${result.data.affected_count} thông báo đã đọc`);
            return result;
        }
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

// Đánh dấu tất cả thông báo chưa đọc đã đọc
async function markAllNotificationsAsRead() {
    try {
        const authToken = localStorage.getItem('auth_token');
        
        const response = await fetch('https://api.socdo.vn/mini-app/v1/update-notification', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${authToken}`
            },
            body: JSON.stringify({
                mark_all: true
            })
        });
        
        const result = await response.json();
        
        if (result.success) {
            console.log(`Đã đánh dấu ${result.data.affected_count} thông báo đã đọc`);
            return result;
        }
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

// Đánh dấu tất cả thông báo của một loại cụ thể đã đọc
async function markAllNotificationsByTypeAsRead(type) {
    try {
        const authToken = localStorage.getItem('auth_token');
        
        const response = await fetch('https://api.socdo.vn/mini-app/v1/update-notification', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${authToken}`
            },
            body: JSON.stringify({
                mark_all: true,
                type: type
            })
        });
        
        const result = await response.json();
        
        if (result.success) {
            console.log(`Đã đánh dấu ${result.data.affected_count} thông báo loại ${type} đã đọc`);
            return result;
        }
    } catch (error) {
        console.error('Lỗi:', error);
    }
}

// Xử lý khi user click vào thông báo
function handleNotificationClick(notification) {
    // Đánh dấu thông báo đã đọc khi user click
    if (!notification.is_read) {
        markNotificationAsRead(notification.id).then(result => {
            if (result.success) {
                // Cập nhật UI
                updateNotificationUI(notification.id, true);
                
                // Giảm số thông báo chưa đọc
                updateUnreadCount();
            }
        });
    }
    
    // Xử lý navigation hoặc action khác
    if (notification.type === 'order' && notification.data && notification.data.order_id) {
        window.location.href = `/order-detail?id=${notification.data.order_id}`;
    }
}

// Cập nhật UI sau khi đánh dấu đã đọc
function updateNotificationUI(notificationId, isRead) {
    const notificationElement = document.querySelector(`[data-notification-id="${notificationId}"]`);
    if (notificationElement) {
        if (isRead) {
            notificationElement.classList.remove('unread');
            notificationElement.classList.add('read');
            const badge = notificationElement.querySelector('.unread-badge');
            if (badge) {
                badge.remove();
            }
        }
    }
}

// Cập nhật số thông báo chưa đọc
async function updateUnreadCount() {
    try {
        const authToken = localStorage.getItem('auth_token');
        const response = await fetch('https://api.socdo.vn/mini-app/v1/get-list-notification?limit=1', {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${authToken}`
            }
        });
        
        const result = await response.json();
        
        if (result.success) {
            const unreadBadge = document.getElementById('unread-badge');
            if (unreadBadge) {
                const count = result.data.unread_count;
                unreadBadge.textContent = count;
                unreadBadge.style.display = count > 0 ? 'block' : 'none';
            }
        }
    } catch (error) {
        console.error('Lỗi cập nhật số thông báo chưa đọc:', error);
    }
}

// Đánh dấu tất cả khi click nút "Đánh dấu tất cả đã đọc"
document.getElementById('mark-all-read-btn')?.addEventListener('click', async function() {
    const result = await markAllNotificationsAsRead();
    if (result && result.success) {
        // Reload danh sách thông báo
        loadNotifications();
        // Cập nhật số thông báo chưa đọc
        updateUnreadCount();
        
        // Hiển thị thông báo thành công
        showNotification('Đã đánh dấu tất cả thông báo đã đọc', 'success');
    }
});

// Ví dụ sử dụng
// Đánh dấu một thông báo
markNotificationAsRead(582);

// Đánh dấu nhiều thông báo
markMultipleNotificationsAsRead([582, 581, 580]);

// Đánh dấu tất cả
markAllNotificationsAsRead();

// Đánh dấu tất cả thông báo loại "order"
markAllNotificationsByTypeAsRead('order');
Lưu ý quan trọng
  • User Token Required: API yêu cầu user token từ login (Bearer token trong Authorization header)
  • Chỉ cập nhật thông báo của user: API tự động lọc theo user_id từ token, không thể đánh dấu thông báo của user khác
  • Ưu tiên tham số: Nếu có nhiều tham số, ưu tiên: mark_all > notification_ids > notification_id
  • mark_all: Chỉ đánh dấu các thông báo chưa đọc (is_read = 0), không ảnh hưởng đến thông báo đã đọc
  • type filter: Chỉ áp dụng khi mark_all = true, dùng để lọc theo loại thông báo cụ thể
  • notification_ids: Có thể là mảng hoặc JSON string, API sẽ tự động parse
  • read_at timestamp: API tự động cập nhật read_at và updated_at khi đánh dấu đã đọc
  • GET và POST: API hỗ trợ cả GET (query parameters) và POST (request body)
  • Affected rows: Response trả về số lượng thông báo đã được cập nhật
Cấu trúc Response Data
Trường Loại Mô tả
notification_id integer ID thông báo đã đánh dấu (khi đánh dấu 1 thông báo)
notification_ids array Danh sách ID thông báo đã đánh dấu (khi đánh dấu nhiều thông báo)
affected_count integer Số lượng thông báo đã được cập nhật
read_at integer Timestamp khi đánh dấu đã đọc
mark_all boolean true nếu đánh dấu tất cả
type string/null Loại thông báo đã lọc (nếu có)
Bảo mật
  • JWT Verification: Sử dụng JWT để xác thực token
  • User Isolation: API chỉ cho phép cập nhật thông báo của user đang đăng nhập (tự động filter theo user_id từ token)
  • SQL Injection Protection: Sử dụng mysqli_real_escape_string và validation để bảo vệ
  • CORS Headers: Cấu hình CORS để bảo mật cross-origin requests
  • Input Validation: Validate và sanitize tất cả input parameters
  • ID Validation: Chỉ chấp nhận ID là số nguyên dương
API Liên Quan