Fcm xử lý hỏi cho phép bằng button thay vì mặc định

Fcm xử lý hỏi cho phép bằng button thay vì mặc định

Nếu bạn đã dùng https://laravel-notification-channels.com/fcm/#usage thì chắc chắn biết rằng notification rất có ích cho người dùng , dưới đây mình hướng dẫn sử dụng FCM để giúp chúng ta gửi thông tin đến người dùng 1 cách trực tuyến hơn 

Bước 1 : Chúng ta cần copy config vào file : fcm_demo_html\fcm.js như sau 

const firebaseConfig = {
  apiKey: "AIzaSyBumY1plcU2hEXhREyTTTFIYhbaTCBHYrY",
  authDomain: "truyenvideo-3eb09.firebaseapp.com",
  projectId: "truyenvideo-3eb09",
  storageBucket: "truyenvideo-3eb09.firebasestorage.app",
  messagingSenderId: "22119134901",
  appId: "1:22119134901:web:180e66a9a8c2d70c4230fc"
};
// Kiểm tra trình duyệt
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const isNotificationSupported = "Notification" in window;
const isServiceWorkerSupported = "serviceWorker" in navigator;
const isFCMSupported = typeof firebase.messaging?.isSupported === "function" ? firebase.messaging.isSupported() : true;

const VAPID_KEY = 'BP8nJ0RMcmghWAboBRo44OBIpp5retAcNqYWy43_XYofiicTGKfngIca79J7g7DpG4-dq0lDsv6YyTcAO_rNzn4';

if (!isNotificationSupported || !isServiceWorkerSupported || !isFCMSupported || isSafari) {
     console.warn('Trình duyệt không hỗ trợ thông báo đẩy FCM');
     document.querySelector('.register')?.remove();
} else {
     firebase.initializeApp(firebaseConfig);

     let messaging;
     let serviceWorkerRegistration;
     const token = document.querySelector("meta[name='token']").getAttribute('content');
     console.log(token)

     const getTokenAndSend = async () => {
          try {
               const token = await messaging.getToken({
                    vapidKey: VAPID_KEY,
                    serviceWorkerRegistration,
               });

               if (token) {
                    // Gửi token về server tại đây nếu cần
                    document.querySelector('.register')?.remove();
                    console.log('FCM Token:', token);
                    const fing = document.querySelector("meta[name='fing']")?.getAttribute('content');
                    const fingerprint = document.querySelector("meta[name='fingerprint']")?.getAttribute('content');
                    console.log('fing:', fing, 'fingerprint:', fingerprint);
               } else {
                    console.warn('Không thể lấy token');
               }
          } catch (error) {
               console.error('Lỗi khi lấy FCM token:', error);
          }
     };

     const handleNotificationPermission = async () => {
          const permission = await Notification.requestPermission();
          if (permission === 'granted') {
               await getTokenAndSend();
          } else {
               console.warn('Người dùng chưa chấp nhận thông báo');
          }
     };

     const setupRegisterButton = () => {
          const registerBtn = document.querySelector('.register');
          if (!registerBtn) {
               console.warn('Không tìm thấy nút .register');
               return;
          }

          switch (Notification.permission) {
               case 'granted':
                    registerBtn.style.display = 'none';
                    break;
               case 'denied':
                    registerBtn.style.display = 'none';
                    console.log('Người dùng đã từ chối cấp quyền thông báo');
                    return;
               default:
                    registerBtn.style.display = 'inline-block';
          }

          registerBtn.addEventListener('click', handleNotificationPermission);
     };

     window.addEventListener('DOMContentLoaded', async () => {
          try {
               serviceWorkerRegistration = await navigator.serviceWorker.register('/firebase-messaging-sw.js');
               console.log('Service worker đã được đăng kí');
               messaging = firebase.messaging();

               if (Notification.permission === 'granted') {
                    await getTokenAndSend();
               }

               setupRegisterButton();
          } catch (error) {
               console.error('Lỗi đăng ký Service Worker hoặc khởi tạo FCM:', error);
          }
     });
}

Ở đây chúng ta đợi website load xong thì mới kiểm tra nếu như được quyền truy cập thì sẽ lấy token gửi lên server 

Tiếp theo chúng ta cần có file firebase-messaging-sw.js 

importScripts('https://www.gstatic.com/firebasejs/10.10.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.10.0/firebase-messaging-compat.js');

// Khởi tạo Firebase
firebase.initializeApp({
     apiKey: "AIzaSyBumY1plcU2hEXhREyTTTFIYhbaTCBHYrY",
     authDomain: "truyenvideo-3eb09.firebaseapp.com",
     projectId: "truyenvideo-3eb09",
     storageBucket: "truyenvideo-3eb09.firebasestorage.app",
     messagingSenderId: "22119134901",
     appId: "1:22119134901:web:180e66a9a8c2d70c4230fc"
});

const messaging = firebase.messaging();

// Nhận thông báo khi ở chế độ nền
messaging.onBackgroundMessage((payload) => {
     // console.log('[firebase-messaging-sw.js] Received background message ', payload);
});

// Nhận push từ server
self.addEventListener('push', function (event) {
     const payload = event.data?.json() ?? {};
     console.log("payload ");
     console.log(payload);
     const notificationOptions = {
          body: payload.data.body ?? 'Bạn có một thông báo mới!',
          image: payload.data.image,
          icon: payload.data.icon ?? 'https://truyenvideo.com/images/logo_notification.png',
          badge: payload.data.badge ?? 'https://truyenvideo.com/images/logo_notification.png',
          data: payload.data ?? {},
          actions: [
               { action: 'open', title: '🔗 Xem chi tiết' },
               { action: 'dismiss', title: '❌ Đóng' }
          ]
     };

     event.waitUntil(
          self.registration.showNotification(payload.data.title ?? '🔥 Thông báo mới!', notificationOptions)
     );
});

// Xử lý sự kiện khi người dùng tương tác với thông báo
self.addEventListener('notificationclick', function (event) {
     event.notification.close();

     let url = event.notification.data?.url || 'https://truyenvideo.com';

     if (event.action === 'open' || !event.action) {
          event.waitUntil(clients.openWindow(url));
     }
});

Ở trang index.html :

 <!-- Firebase SDK -->
     <script src="https://www.gstatic.com/firebasejs/10.10.0/firebase-app-compat.js"></script>
     <script src="https://www.gstatic.com/firebasejs/10.10.0/firebase-messaging-compat.js"></script>
     <script src="fcm.js"></script>

Dưới đây là code đầy đủ : https://drive.google.com/file/d/1N-59W0deXnmCtoFjvDLgrqf-hZqb-qni/view?usp=sharing