Implement FCM Notification with Laravel

There're plenty of libraries for setting up FCM notifications with Laravel. But i found it pretty tough to set it up. In this short tutorial, we'll implement FCM Notifications with Laravel from the ground up. So fasten your seat belts and follow along.

Pre-requisites

  • Basic understanding of Laravel
  • Basic understanding of APIs
  • Some knowledge of CURL or GuzzleHTTP
  • Know what FCM is?
  • Firebase Account and Project setup

Project Setup

Setup a new Laravel application by running the following command.

laravel new fcm-notifications

Getting ready the sample Payload

{
"payload": {
"a": "b",
"c": "d",
"e": "f"
},
"receiver_user": "receiver_fcm_registeration_id",
"sender_user": "sender_fcm_registeration_id",
"title":"sample title",
"message":"sample message",
"push_type":"individual"
}
  • Payload is the sample payload data by providing custom sample data.
  • Receiver User is the FCM registration ID of the user you want to send notification to.
  • Sender User is the FCM registration ID of the user who sends the notification (optional)
  • Title for the notification
  • Message for the notification
  • Post Type would be either individual for single user, topic for sending it to topic or multiple for sending it to multiple users.

API Endpoint

For this task, we’ll just have a simple POST API endpoint for sending FCM notifications to users.

Head over to project folder and open up routes/api.php and add our POST route to some NotificationController, which we’ll create later on.

Route::post( 'notify', 'NotificationController@notify' );

Let’s now create a controller and a notify method inside it using artisan command line.

php artisan make:controller NotificationController

Now let’s get this sample payload from request in your Controller app\Http\Controllers\NotificationController.php like so,

public function notify() {

$data = json_decode( \request()->getContent() );

$sender = $data->sender_user;
$receiver = $data->receiver_user;
$notification_payload = $data->payload;
$notification_title = $data->title;
$notification_message = $data->message;
$notification_push_type = $data->push_type;

}

FCM and Push Notification Setup

Now before moving further, let’s just stop here and think of whats going to be next? Well to send FCM notification now, we’d need some sort of mechanism to work. For a yet simple solution, we’ll create a couple of files here: Firebase.php and Push.php

Firebase.php will be responsible for sending messages and will handle the push type of message you want to send.

Push.php will be responsible for setting the data from sample payload and set our final JSON for the notification.

Let’s create our files now. We’ll put it inside app\Libraries namespace.

Now in our Firebase.php, add the following methods.

class Firebase {

/**
* Sending push message to single user by Firebase Registration ID
*
@param $to
*
@param $message
*
*
@return bool|string
*/
public function
send( $to, $message ) {

$fields = array(
'to' => $to,
'data' => $message,
);

return $this->sendPushNotification( $fields );
}


/**
* Sending message to a topic by topic name
*
@param $to
*
@param $message
*
*
@return bool|string
*/
public function
sendToTopic( $to, $message ) {
$fields = array(
'to' => '/topics/' . $to,
'data' => $message,
);

return $this->sendPushNotification( $fields );
}


/**
* Sending push message to multiple users by firebase registration ids
*
@param $registration_ids
*
@param $message
*
*
@return bool|string
*/
public function
sendMultiple( $registration_ids, $message ) {
$fields = array(
'to' => $registration_ids,
'data' => $message,
);

return $this->sendPushNotification( $fields );
}

/**
* CURL request to firebase servers
*
@param $fields
*
*
@return bool|string
*/
private function
sendPushNotification( $fields ) {

// Set POST variables
$url = 'https://fcm.googleapis.com/fcm/send';

$headers = array(
'Authorization: key=' . env('FCM_LEGACY_KEY')',
'Content-Type: application/json'
);
// Open connection
$ch = curl_init();

// Set the url, number of POST vars, POST data
curl_setopt
( $ch, CURLOPT_URL, $url );

curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

// Disabling SSL Certificate support temporarly
curl_setopt
( $ch, CURLOPT_SSL_VERIFYPEER, false );

curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $fields ) );

// Execute post
$result = curl_exec( $ch );
if ( $result === false ) {
die( 'Curl failed: ' . curl_error( $ch ) );
}

// Close connection
curl_close
( $ch );

return $result;
}

This Firebase class is pretty straight forward to get. It’s just a collection of methods for sending push notifications. Here if you’ve noted, you’ll have to add FCM_LEGACY_KEY, which we’re getting from our .env file.

You can get your FCM_LEGACY_KEY from your FCM console under your project settings in cloud messaging tab.

Now For Push.php,

class Push {

private $title;
private $message;
private $data;


/**
*
@param $title
*/
public function
setTitle( $title ) {
$this->title = $title;
}

/**
*
@param $message
*/
public function
setMessage( $message ) {
$this->message = $message;
}


/**
*
@param $data
*/
public function
setPayload( $data ) {
$this->data = $data;
}


/**
*
@return array
*/
public function
getPush() {
$response = array();
$response['data']['title'] = $this->title;
$response['data']['message'] = $this->message;
$response['data']['payload'] = $this->data;
$response['data']['timestamp'] = date( 'Y-m-d G:i:s' );

return $response;
}

}

Here, we’re setting our data, title and message etc. Pretty straight forward? eh?

Back to NotificationController

In our notify method, add the following code under data.

try {

$sender_id = "";
$receiver_id = "";

$firebase = new Firebase();
$push = new Push();

// optional payload
$payload = $notification_payload;

$title = $notification_title ?? '';

// notification message
$message = $notification_message ?? '';

// push type - single user / topic
$push_type = $notification_push_type ?? '';

$push->setTitle( $title );
$push->setMessage( $message );
$push->setPayload( $payload );

$json = '';
$response = '';

if ( $push_type === 'topic' ) {
$json = $push->getPush();
$response = $firebase->sendToTopic( 'global', $json );
} else if ( $push_type === 'individual' ) {
$json = $push->getPush();
$regId = $receiver_id ?? '';
$response = $firebase->send( $regId, $json );

return response()->json( [
'response' => $response
] );
}


} catch ( \Exception $ex ) {
return response()->json( [
'error' => true,
'message' => $ex->getMessage()
] );
}

Finally

So, if all went well and you test it out in postman or your application. You’ll get a response like so,

{
"response": {
"multicast_id": 7537747549381668791,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1562948236493630%12bb27e9f9fd7ecd"
}
]
}
}

Additionally

Now if you’re bit disliking the CURL part. We’ve got you covered here. Let’s refactor a bit and convert CURL call to GuzzleHTTP.

Install the package by running

composer require guzzlehttp/guzzle

Now we’ll replace code in our sendPushNotification function in Firebase.php

Updated sendPushNotification function would now look like:

private function sendPushNotification( $fields ) {

// Set POST variables
$url = 'https://fcm.googleapis.com/fcm/send';

$client = new Client();

$result = $client->post( $url, [
'json' =>
$fields
,
'headers' => [
'Authorization' => 'key='.env('FCM_LEGACY_KEY'),
'Content-Type' => 'application/json',
],
] );


return json_decode( $result->getBody(), true );

}

Pretty clean? Also DON’T forget to use GuzzleHttp\Client on the top of Class.

Conclusion

Well, we’ve successfully implemented FCM notifications with Laravel. If you encountered any errors in between, please let us know in the comments section below. You can find the complete code on the Github Repository.