Update July 2023
The batch messaging endpoint has been deprecated and will be removed in July 2024. The recommendation is to iterate through the tokens use the standard v1 api send method: https://firebase.google.com/docs/cloud-messaging/send-message#send-a-batch-of-messages
Here is example on how to send a notification to a single device:
<?php
require_once '<Path_to_google-api-php-client>/vendor/autoload.php';
function getOATHToken()
{
$client = new Google_Client();
try {
$client->setAuthConfig("<path_to_your_private_json_key.json>");
$client->addScope(Google_Service_FirebaseCloudMessaging::CLOUD_PLATFORM);
$savedTokenJson = readSavedToken();
if ($savedTokenJson) {
// the token exists, set it to the client and check if it's still valid
$client->setAccessToken($savedTokenJson);
$accessToken = $savedTokenJson;
if ($client->isAccessTokenExpired()) {
// the token is expired, generate a new token and set it to the client
$accessToken = generateToken($client);
$client->setAccessToken($accessToken);
}
} else {
// the token doesn't exist, generate a new token and set it to the client
$accessToken = generateToken($client);
$client->setAccessToken($accessToken);
}
$oauthToken = $accessToken["access_token"];
return $oauthToken;
} catch (Google_Exception $e) {}
return false;
}
//Using a simple file to cache and read the toke, can store it in a databse also
function readSavedToken() {
$tk = @file_get_contents('token.cache');
if ($tk) return json_decode($tk, true); else return false;
}
function writeToken($tk) {
file_put_contents("token.cache",$tk);
}
function generateToken($client)
{
$client->fetchAccessTokenWithAssertion();
$accessToken = $client->getAccessToken();
$tokenJson = json_encode($accessToken);
writeToken($tokenJson);
return $accessToken;
}
// Finally
function sendNotification($token, $title, $body, $accessToken) {
$payload = ["message" => ["token" => $token, "notification"=>["title" => $title, "body"=> $body]]];
$postdata = json_encode($payload);
$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/<your_firebase_project_id>/messages:send', false, $context);
echo "\n\n======RESPONSE======\n\n";
echo $result;
}
$token = "token-1"; //FCM Device token
$title = "Test from PHP";
$body = "This is a test from PHP";
sendNotification($token, $title, $body, getOATHToken());
?>
The batch sending example (now deprecated)
Here is a complete example on how to send a push to multiple tokens using the Google API PHP Client, using the FCM HTTP v1 api, as given in the FCM docs.
(Modified from lubilis answer above)
<?php
require_once '<Path_to_google-api-php-client>/vendor/autoload.php';
function getOATHToken()
{
$client = new Google_Client();
try {
$client->setAuthConfig("<path_to_your_private_json_key.json>");
$client->addScope(Google_Service_FirebaseCloudMessaging::CLOUD_PLATFORM);
$savedTokenJson = readSavedToken();
if ($savedTokenJson) {
// the token exists, set it to the client and check if it's still valid
$client->setAccessToken($savedTokenJson);
$accessToken = $savedTokenJson;
if ($client->isAccessTokenExpired()) {
// the token is expired, generate a new token and set it to the client
$accessToken = generateToken($client);
$client->setAccessToken($accessToken);
}
} else {
// the token doesn't exist, generate a new token and set it to the client
$accessToken = generateToken($client);
$client->setAccessToken($accessToken);
}
$oauthToken = $accessToken["access_token"];
return $oauthToken;
} catch (Google_Exception $e) {}
return false;
}
//Using a simple file to cache and read the toke, can store it in a databse also
function readSavedToken() {
$tk = @file_get_contents('token.cache');
if ($tk) return json_decode($tk, true); else return false;
}
function writeToken($tk) {
file_put_contents("token.cache",$tk);
}
function generateToken($client)
{
$client->fetchAccessTokenWithAssertion();
$accessToken = $client->getAccessToken();
$tokenJson = json_encode($accessToken);
writeToken($tokenJson);
return $accessToken;
}
// Finally
function sendNotification($tokens, $title, $body, $accessToken) {
$boundary = "--subrequest_boundary";
$multiPayload = $boundary;
foreach ($tokens as $token) {
$head = "Content-Type: application/http\r\n".
"Content-Transfer-Encoding: binary\r\n\r\n".
"POST /v1/projects/<your_firebase_project_name>/messages:send\r\n".
"Content-Type: application/json\r\n".
"accept: application/json\r\n\r\n";
$payload = ["message" => ["token" => $token, "notification"=>["title" => $title, "body"=> $body]]];
$postdata = json_encode($payload);
$multiPayload .= "\r\n".$head.$postdata."\r\n".$boundary;
}
$multiPayload .= "--";
//Uncomment for debugging
//echo "\n\n==== POST DATA====\n\n";
//echo $multiPayload;
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-Type: multipart/mixed; boundary="subrequest_boundary"' . "\r\nAuthorization: Bearer $accessToken",
'content' => $multiPayload
)
);
//Uncomment for debugging
//echo "\n\n==== HTTP OPTIONS====\n\n";
//var_dump($opts);
$context = stream_context_create($opts);
// This is the path for sending push multiple tokens (upto 500 as per the docs)
$result = file_get_contents('https://fcm.googleapis.com/batch', false, $context);
echo "\n\n======RESPONSE======\n\n";
echo $result;
}
$tokens = ["token-1","token-2"]; //FCM Device tokens as array
$title = "Test from PHP";
$body = "This is a test from PHP";
sendNotification($tokens, $title, $body, getOATHToken());
?>