Skip to content

Instantly share code, notes, and snippets.

@exaland
Created December 16, 2024 13:37
Show Gist options
  • Save exaland/9141c7641366f7c84fbdfac7c80d33a4 to your computer and use it in GitHub Desktop.
Save exaland/9141c7641366f7c84fbdfac7c80d33a4 to your computer and use it in GitHub Desktop.
Firebase FCM (New Auth with Service Config File) Class for Laravel / Symfony or PHP
<?php
namespace App;
use GuzzleHttp\Client;
class ExalandFirebase
{
private $fcmUrl;
private $serviceAccountPath;
private $httpClient;
private $projectId;
public function __construct()
{
$this->serviceAccountPath = storage_path('app/firebase/service-account.json');
$this->httpClient = new Client();
// Lire le fichier service_account.json
$credentials = json_decode(file_get_contents($this->serviceAccountPath), true);
// Récupérer le project_id
if (!isset($credentials['project_id'])) {
throw new RuntimeException('Project ID missing in service_account.json.');
}
$this->projectId = $credentials['project_id'];
$this->fcmUrl = "https://fcm.googleapis.com/v1/projects/{$this->projectId}/messages:send";
}
private function getAccessToken()
{
$scope = 'https://www.googleapis.com/auth/firebase.messaging';
// Charger les informations du compte de service
$credentials = json_decode(file_get_contents($this->serviceAccountPath), true);
$now = time();
$jwtHeader = base64_encode(json_encode(['alg' => 'RS256', 'typ' => 'JWT']));
$jwtPayload = base64_encode(json_encode([
'iss' => $credentials['client_email'],
'sub' => $credentials['client_email'],
'aud' => 'https://oauth2.googleapis.com/token',
'scope' => $scope,
'iat' => $now,
'exp' => $now + 3600,
]));
$signature = '';
openssl_sign("$jwtHeader.$jwtPayload", $signature, $credentials['private_key'], 'SHA256');
$jwt = "$jwtHeader.$jwtPayload." . base64_encode($signature);
// Faire une requête pour obtenir un jeton d'accès
$response = $this->httpClient->post('https://oauth2.googleapis.com/token', [
'form_params' => [
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $jwt,
],
]);
$data = json_decode($response->getBody(), true);
return $data['access_token'];
}
public function sendMulticast($registrationTokens, $title, $body, $data = [])
{
if (empty($registrationTokens)) {
throw new InvalidArgumentException('Tokens list cannot be empty.');
}
// Nettoyer les données de la notification si vide ou null
$data = $this->cleanArray($data);
// Convertir les valeurs en chaînes de caractères
$data = array_map('strval', $data);
// Construire la charge utile FCM
$payload = [
'message' => [
'token' => null, // Sera défini dans chaque itération
'notification' => [
'title' => $title,
'body' => $body,
],
'data' => $data,
'android' => [
'priority' => 'high',
'ttl' => '0s',
'notification' => [
'sound' => 'notification.mp3',
'channel_id' => 'Your Channel',
],
],
'apns' => [
'headers' => [
'apns-priority' => '10',
],
'payload' => [
'aps' => [
'sound' => 'notification.mp3',
'content-available' => 1,
],
],
],
],
];
$responses = [];
$accessToken = $this->getAccessToken();
// Envoyer la notification pour chaque token
foreach ($registrationTokens as $token) {
$payload['message']['token'] = $token;
$response = $this->httpClient->post($this->fcmUrl, [
'headers' => [
'Authorization' => 'Bearer ' . $accessToken,
'Content-Type' => 'application/json',
],
'json' => $payload,
]);
$responses[] = json_decode($response->getBody(), true);
}
return $responses;
}
/**
* Nettoyer un tableau en supprimant les valeurs indésirables
* @param array $array
*/
function cleanArray(array $array)
{
foreach ($array as $key => $value) {
if (is_array($value)) {
$array[$key] = cleanArray($value); // Nettoyage récursif
}
if (is_null($value) || $value === '' || $value === '0000-00-00 00:00:00') {
unset($array[$key]); // Supprimer les valeurs indésirables
}
}
return $array;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment