- vừa được xem lúc

Push notification cho React App sử dụng Firebase kết hợp backend Laravel

0 0 267

Người đăng: Đinh Xuân Dương

Theo Viblo Asia

1. Giới thiệu

Firebase là công ty mà Google mua lại vào năm 2014. Kể từ đó, Google đã thực hiện một số cải tiến đối với nền tảng này, đến mức hiện tại họ quảng cáo Firebase như một giải pháp phụ trợ một cửa như một dịch vụ cho các ứng dụng di động.

Bao gồm các giải pháp như Centralized Authentication, Realtime Databases, Cloud Functions, trong đó có một phần được xây dựng lên để tối ưu và gửi thông báo cho các ứng dụng. Đó chính là Firebase Cloud Messaging.

Trong bài viết này chúng mình cùng thử tìm hiểu làm sao để push notification từ một web Server Laravel đến browser chạy bằng 1 React app nhé .

Bắt đầu thôi ?

2. Setting Firebase

  • Đầu tiên chúng ta cần tạo mới 1 project

image.png

  • Sau đó ta cần tạo mới web application

image.png

  • Thực hiện điền các thông tin cơ bản và chúng ta sẽ thu được 1 đoạn script sau

image.png

  • Sau các bước trên các bạn truy cập vào Project setting > Cloud Messaging

    Thực hiện Coppy cho mình server key; nó sẽ được sử dụng là FiRE_BASE_FCM_KEY ở dưới logic server

    image.png

3. Server Side (Laravel)

  • Tạo mới migration để add column device_token vào bảng users
 > php artisan make:migration add_column_device_token_to_users_table --table=users
 /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function (Blueprint $table) { $table->string('device_key')->nullable(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('device_key'); }); }
  • sau đó là chạy migrate

  • tiếp theo là xử lý trong phần UserController

    • Đây là phần receive và add token vào trong database
     /** * Add device token for user * * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function addDeviceToken(Request $request) { $user = getUser($request->bearerToken()); //getUser($request->bearerToken()) là mình đang sử dụng JWT nên mình chỉ lấy ra user với user_id truyển nên mà thôi  return response()->json([ $user->update(['device_key' => $request->device_token]) ], 200); }
    
    • Đây sẽ là function send notification
    /**
    * handle push notification
    *
    * @param Request $request
    * @return \Illuminate\Http\JsonResponse
    */
    public function sendNotification(Request $request)
    { $deviceToken = User::whereNotNull('device_key')->pluck('device_key')->all(); $dataEndCode = json_encode([ "registration_ids" => $deviceToken, "notification" => [ "title" => $request->title, "body" => $request->body, ] ]); $headerRequest = [ 'Authorization: key=' . env('FIRE_BASE_FCM_KEY'), 'Content-Type: application/json' ]; // FIRE_BASE_FCM_KEY mình có note ở phần 2.setting firebase nhé // CURL $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, env('FIRE_BASE_URL')); //FIRE_BASE_URL = https://fcm.googleapis.com/fcm/send  curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headerRequest); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, $dataEndCode); // Mục đích mình đưa các tham số kia vào env để tùy biến nhé $output = curl_exec($ch); if ($output === FALSE) { log('Curl error: ' . curl_error($ch)); } curl_close($ch); return response()->json($output);
    }
    
  • Trong file routers/api.php mình sẽ có 2 router sau

     Route::post('update-device-token', [UserController::class, 'addDeviceToken']); Route::post('send-notifications', [UserController::class, 'sendNotification']);
    

Xong rồi tiếp đến phần client side nhé

4. Client Side (React App)

Ở phần Client side mình có sử dụng material-ui và react typescrip

  • Tiến hành tạo mới react app, firebase và install material-ui nhé

    > npx create-react-app my-app --template typescript > npm install @material-ui/core > npm i firebase > @firebase/messaging > npm i axios
    
  • Tạo mới file src/firebase.ts là file config firebase nhé :

    import firebase from "firebase/app";
    import '@firebase/messaging' const firebaseConfig = { apiKey: "apiKey", authDomain: "authDomain", projectId: "projectId", storageBucket: "storageBucket", messagingSenderId: "messagingSenderId", appId: "appId", measurementId: "measurementId"
    };
    // các tham số này là phần config lấy ra được từ phần 2. setting firebase nhé
    firebase.initializeApp(firebaseConfig) export const message = firebase.messaging() export default firebase
    
  • Tiếp theo các bạn tạo giúp mình public/firebase-messaging-sw.js với nội dung sau

 // Scripts for firebase and firebase messaging importScripts('https://www.gstatic.com/firebasejs/8.9.0/firebase-app.js'); importScripts('https://www.gstatic.com/firebasejs/8.9.0/firebase-analytics.js'); importScripts('https://www.gstatic.com/firebasejs/8.9.0/firebase-messaging.js') if ('serviceWorker' in navigator) { navigator.serviceWorker.register('../firebase-messaging-sw.js') .then(function(registration) { console.log('Registration successful, scope is:', registration.scope); }).catch(function(err) { console.log('Service worker registration failed, error:', err); }); } // Initialize the Firebase app in the service worker by passing the generated config var firebaseConfig = { messagingSenderId: "messagingSenderId", appId: "appId", }; // phần firebaseConfig tương tự như ở trên nhé firebase.initializeApp(firebaseConfig); const message = firebase.messaging()
  • Ở file src/App.tsx xử lý push token và receive notification server trả về nhé
 import React, {useState, useEffect, useCallback} from 'react'; import Snackbar, {SnackbarOrigin} from '@material-ui/core/Snackbar'; import MuiAlert, { AlertProps } from '@material-ui/lab/Alert'; import firebase, {message} from './firebase' import PushNotification from 'api/push-notification'; import { getAccessToken } from './hooks'; export interface State extends SnackbarOrigin { open: boolean; severity: "error" | "success" | "info" | "warning" | undefined } export interface Notification { title: any, body: any } function Alert(props: AlertProps) { return <MuiAlert elevation={6} variant="filled" {...props} />; } const App: React.FC = () => { const [dataNotify, setDataNotify] = useState<Notification>({title: '', body: ''}); const [stateData, setStateData] = useState<State>({ open: false, vertical: 'bottom', horizontal: 'left', severity: 'success' }); // receive notification server trả về  message.onMessage((payload) => { if(!payload?.notification) { setStateData({...stateData, open: true, severity: 'error'}) return; } const {notification} = payload setStateData({...stateData, open: true, severity: 'success'}) setDataNotify({title: notification.title, body: notification.body}) }); // getToken và push tokenID lên server  useEffect(() => { const messaging = firebase.messaging() messaging.requestPermission() .then(() => { return messaging.getToken() }) .then(token => { return axios.post('http://localhost/api/update-device-token ', {device_token: token}) }) .then(response => { console.log(response) }) }, []) const handleClose = useCallback((event?: React.SyntheticEvent, reason?: string) => { setStateData({ ...stateData, open: false }); }, [stateData]); const { vertical, horizontal, open } = stateData; // push data notification lên server const handlePushDataNotify = () => { axios.post('http://localhost/api/send-notifications ', {title: 'Đây là title', body: 'đây là body'}) } return ( <div> <button onClick={handlePushDataNotify}> Click to me </button> <Snackbar anchorOrigin={{ vertical, horizontal }} open={open} onClose={handleClose} key={vertical + horizontal} > <Alert onClose={handleClose} severity={stateData.severity}> {dataNotify.title} </Alert> </Snackbar> </div> ); } export default App; 
  • ở đây mục đích sử dụng material để design và show notification

5. Kết quả

Sau khi thực hiện bấm vào button "Click to me" sẽ thực hiện call API lên Web server và server sẽ đẩy đến các device token đã lưu trước đó Kết quả

  • Trong trường hợp mình đứng tại page đó thì sẽ có hiển thị thông báo của trang web

    image.png

  • Trong trường hợp mình đã chuyển sang tab khác thì thông báo sẽ như sau:

    image.png

Còn đây là repository React App của mình, mọi người có thể tham khảo thêm : https://github.com/duong120798/redux-saga-typescript/

6. Tham khảo

https://blog.logrocket.com/push-notifications-with-react-and-firebase/ https://www.remotestack.io/how-to-send-web-push-notification-in-laravel-with-firebase/

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 361

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 452

- vừa được xem lúc

Sử dụng Swagger để xây dựng API documentation

Giới thiệu về Swagger. RESTful API là một tiêu chuẩn dùng trong việc thiết kế API cho các ứng dụng web (thiết kế Web services) để tiện cho việc quản lý các resource.

0 0 1k

- vừa được xem lúc

Ví dụ CRUD với Laravel và Vuejs.

1. Cài đặt Laravel. composer create-project --prefer-dist laravel/laravel vuelaravelcrud. .

0 0 163

- vừa được xem lúc

Một số tips khi dùng laravel (Part 1)

1. Show database query in raw SQL format. DB::enableQueryLog(); // Bật tính năng query logging. DB::table('users')->get(); // Chạy truy vấn bạn muốn ghi log.

0 0 84

- vừa được xem lúc

Inertiajs - Xây dựng Single Page App không cần API

Tiêu đề là mình lấy từ trang chủ của https://inertiajs.com/ chứ không phải mình tự nghĩ ra đâu nhé :v. Lâu lâu rồi chưa động tới Laravel (dự án cuối cùng mình code là ở ver 5.8), thế nên một ngày đẹp trời lượn vào đọc docs ver 8.

0 0 242