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.