Push Notifications With Firebase Cloud Messaging From PHP Server

You are currently viewing Push Notifications With Firebase Cloud Messaging From PHP Server

In this post I will show you how you can implement Firebase Cloud Messaging on your PHP server to use in your app to push notifications to users.

The guided information will be with the understanding that you already created a Firebase Cloud Messaging project and have implemented the client side to receive notifications. I am performing this in a test environment using Windows IIS with PHP installed.

You will need to get the Google APIs Client library for PHP

https://github.com/googleapis/google-api-php-client

You can follow the directions on the page for Composer install or download the package to use in your project.

I am not prone to utilizing Composer just yet due to limitations on my production server when my projects are complete. However, due to the size of the package, I opted to use Composer in my test environment to gather the required components and strip down the package to use in my production environment.

Configure the Google API Client Library

Navigate to your project folder then run the below command

composer require google/apiclient

This will gather the entire Google API Client library. It will load into the current directory you executed the command in with the main source in the vendor folder. It will also create a composer.json file in your current directory. To remove unnecessary packages, you will need to edit the composer.json file and specify which packages you want.

Below is my example.

{
    "require": {
        "google/apiclient": "^2.18"
    },
    "scripts": {
        "pre-autoload-dump": "Google\\Task\\Composer::cleanup"
    },
    "extra": {
        "google/apiclient-services": [
            "FirebaseCloudMessaging"
        ]
    }
}

Then you enter this is the command prompt in the current working directory

composer update

Now the Google API Client library packages has been trimmed down to only include the necessary components to utilize Firebase Cloud Messaging.

BONUS

This is the extent of my need for Composer. All I need to implement this on my production server is to copy the folder vendor to my server without the need to install Composer, which I have already tested.

Configuration

Due to my test environment not having SSL, I needed to adjust a small piece of code in the Google API Client library. I needed to edit the Client.php file under GuzzleHttp to allow Curl to not need to verify certificate. NOTE: This is unsafe to use in production environment, change back when deploying.

My issues lead me to this post for the information I needed.

https://stackoverflow.com/questions/28066409/how-to-ignore-invalid-ssl-certificate-errors-in-guzzle-5

The file location should be <project path>\vendor\guzzlehttp\guzzle\src

You will need to edit the Client.php file

Find and replace the code below. All that was changed was setting ‘verify’ => false

 /**
     * Configures the default options for a client.
     */
    private function configureDefaults(array $config): void
    {
        $defaults = [
            'allow_redirects' => RedirectMiddleware::$defaultSettings,
            'http_errors' => true,
            'decode_content' => true,
            'verify' => false,//true,
            'cookies' => false,
            'idn_conversion' => false,
        ];

Now you will need a few pieces of information from your Firebase Console.

-You will need your Project ID which can be found in the Project Settings under the General tab

-Then you will need to generate a new private key and download the *.json file in the Project Settings under the Service accounts tab. Place the file in a secure location.

The new Firebase Cloud Messaging system needs this key for authentication. You will need to request a token using this key to then use the token to push notifications.

Code

Finally the server side code to put all this together. From my research, I have found a few different methods to getting the token using the Google API Client library that I will post here.

References while creating/troubleshooting:

https://stackoverflow.com/questions/49782134/how-to-use-the-fcm-http-v1-api-with-php

https://github.com/lkaybob/php-fcm-v1

https://stackoverflow.com/questions/77697543/how-to-send-fcm-push-notification-using-php

Method #1 – using the ServiceAccountCredentials class

<?php


require_once 'vendor/autoload.php'; 

use Google\Auth\Credentials\ServiceAccountCredentials;

...

function getAccessToken() {
    $key = json_decode(file_get_contents('<json file path you downloaded from Firebase console>'), true);
    
    $scopes = [\Google\Service\FirebaseCloudMessaging::FIREBASE_MESSAGING];
    $credentials = new ServiceAccountCredentials($scopes, [
        'client_email' => $key['client_email'],
        'private_key' => $key['private_key']
    ]);
    
    return $credentials->fetchAuthToken()['access_token'];
}

...

?>

Method #2 – using Google_Client class and add in specific parameters

<?php


require_once 'vendor/autoload.php'; 

...

function getAccessToken()
{
    $client = new Google_Client();
    try {

        $client->setAuthConfig("<json file path you downloaded from Firebase console>");
        $client->addScope(\Google\Service\FirebaseCloudMessaging::FIREBASE_MESSAGING);

        $client->fetchAccessTokenWithAssertion();
        $accessToken = $client->getAccessToken();
    
        $tokenJson = json_encode($accessToken);
        

        $oauthToken = $accessToken["access_token"];

        return $oauthToken;

        
    } catch (Google_Exception $e) {}
   return false;
}

...

?>

Either method just needs to be called to retrieve the token needed to move on to the next step to push the notifications to the users.

To push the notifications to the users, I have posted two methods that can be used as well. I prefer the curl method.

Method #1 – using curl to submit request

<?php

function sendNotification($dev_token, $title, $body, $accessToken) {

    $payload = [
        'title' => $title,
        'body' => $body,
    ];

    //custom data fields
    $data = [
        'id' => '211',
        'username' => 'Winston',
    ];

    $fcm = [
        'message' => [
           'token' => $dev_token,
            'notification' => $payload,
            'data' => $data
        ],
    ];
    
    $headers = [
        'Authorization: Bearer ' . $accessToken,
        'Content-Type: application/json'
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://fcm.googleapis.com/v1/projects/<project-id from Firebase Console under General>/messages:send');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fcm));
    $result = curl_exec($ch);
    curl_close($ch);
    echo $result; 
}

?>

Method #2

<?php

function sendNotification($dev_token, $title, $body, $accessToken) {

    
    $payload = [
        'title' => $title,
        'body' => $body,
    ];

    //custom data fields
    $data = [
        'id' => '211',
        'username' => 'Winston',
    ];

    $fcm = [
        'message' => [
           'token' => $dev_token,
            'notification' => $payload,
            'data' => $data
        ],
    ];
    
    $postdata = json_encode($fcm);
    
    $opts = array('http' =>
        array(
            'method'  => 'POST',
             'header'  => 'Content-Type: application/json' . "\r\nAuthorization: Bearer $accessToken",
            'content' => $postdata
        )
    );

    $context  = stream_context_create($opts);

    $result = file_get_contents('https://fcm.googleapis.com/v1/projects/<project-id from Firebase Console under General>/messages:send', false, $context);
    
    echo $result;
    
    }

?>

Finally get the token then send notification to user or users.

<?php

require_once 'vendor/autoload.php'; 

$dev_tokens = array("device_1_token", 
"device_2_token"); //FCM Device token

$title = "Testing FCM Notification";
$body = "This is the body of the notification";

$access_token = getAccessToken();
if($access_token !== false){
    foreach($dev_tokens as $token){
        sendNotification($token, $title, $body, $access_token);
    }
}

?>

Hope this was useful.

Leave a Reply