23

I am developing chat app which is based on Firebase Database and Storage. Everything is working fine, but now I need implementation of FCM to receive notification on app when app is in background or foreground. I can't find a way to implement in PHP which listen any changes in firebase database and if there is any change then send push notification to app.

There is so many code which send notification from PHP, but none is based on Firebase database and even official documentation has Node.js guide which my shared hosting doesn't support.

I already implemented FCM code on my app side which is tested from Firebase Console.

Here is my Firebase database structure Firebase Database Structure

KENdi
  • 7,576
  • 2
  • 16
  • 31
Ritu
  • 518
  • 2
  • 12
  • 35
  • 1
    use a postman. :) – Manoj Perumarath Mar 24 '17 at 04:52
  • 1
    You should have a look at [Cloud Functions for Firebase](https://firebase.google.com/docs/functions/). Specifically at [Realtime Database Triggers](https://firebase.google.com/docs/functions/database-events). – AL. Mar 28 '17 at 06:56
  • @AL.my server don't support Npm – Ritu Apr 08 '17 at 10:14
  • A detail blog : http://sforsuresh.in/sending-push-notifications-to-android-mobile-using-firebase-php – Suresh Kamrushi Aug 11 '21 at 08:04
  • May be this link very helpful: [send push notifications using firebase cloud messaging.](https://devnote.in/how-to-send-push-notifications-using-firebase-cloud-messaging-with-php/) – Fefar Ravi Mar 22 '22 at 05:06

6 Answers6

52

Sending a push notification is only a matter of sending a post request to FCM servers.

Here is working example:

$data = json_encode($json_data);
//FCM API end-point
$url = 'https://fcm.googleapis.com/fcm/send';
//api_key in Firebase Console -> Project Settings -> CLOUD MESSAGING -> Server key
$server_key = 'YOUR_KEY';
//header with content_type api key
$headers = array(
    'Content-Type:application/json',
    'Authorization:key='.$server_key
);
//CURL request to route notification to FCM connection server (provided by Google)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch);
if ($result === FALSE) {
    die('Oops! FCM Send Error: ' . curl_error($ch));
}
curl_close($ch);

Example of the JSON pay load:

[
    "to" => 'DEVICE_TOKEN',
    "notification" => [
        "body" => "SOMETHING",
        "title" => "SOMETHING",
        "icon" => "ic_launcher"
    ],
    "data" => [
        "ANYTHING EXTRA HERE"
    ]
]
yaxe
  • 367
  • 5
  • 26
meda
  • 45,103
  • 14
  • 92
  • 122
  • 1
    fetch data from your database, and build that playload message thats all – meda Mar 24 '17 at 11:39
  • 1
    @meda I had a question... In this case what will be the server key if I want to send a notification to ios device? Or how to use pem file to send a notification to ios device? – AmarjaPatil4 Aug 21 '17 at 06:17
  • 1
    Shows "Error=MissingRegistration". – Vishnu T Asok Sep 26 '18 at 08:14
  • 2
    Hello, I've followed so many examples like yours but I don't receive any notification, neither the notification get listed in firebase console, even if the CURL response is positive.. status: 200 string(143) "{"multicast_id":8573812091209374332,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1550852694105682%0762e9f8f9fd7ecd"}]}" when I send it via firebase console to the same device token it works , any idea? device token got from firebase cloud firestore – andrea.somovigo Feb 22 '19 at 16:35
  • 1
    @VishnuTasok I was getting this error, too. turn out it is the header not setting properly, if you use POSTMAN, u must choose raw in the body and select JSON(application/json) from the dropdown menu next to the raw radio button. IT WILL THEN OVERWRITE YOUR HEADER. So even you entered the header in the header tab, a wrong setting in body tab will get your header overwritten in POSTMAN. – Lawrence Cheuk Jun 06 '19 at 18:10
  • @meda I am troubleshooting an issue I face in one of my apps and wanted to know that the above-mentioned approach falls in which category from this list https://firebase.google.com/docs/cloud-messaging/server#choosing-a-server-option – Jignesh Ansodariya Aug 16 '19 at 07:19
  • @meda meda how to send `channel_id` in http request? Kindly suggest. Thanks. – Kamlesh Sep 05 '21 at 16:25
  • @Kamlesh anything extra goes under the `data` key as indicated in my post `data => ['channel_id'=>123]` – meda Sep 06 '21 at 14:21
  • How can I send the message to all devices? Thanks – Kareem JO Jan 29 '23 at 13:33
32

Try this code it works for me android as well as iOS

<?php
    $url = "https://fcm.googleapis.com/fcm/send";
    $token = "your device token";
    $serverKey = 'your server token of FCM project';
    $title = "Notification title";
    $body = "Hello I am from Your php server";
    $notification = array('title' =>$title , 'body' => $body, 'sound' => 'default', 'badge' => '1');
    $arrayToSend = array('to' => $token, 'notification' => $notification,'priority'=>'high');
    $json = json_encode($arrayToSend);
    $headers = array();
    $headers[] = 'Content-Type: application/json';
    $headers[] = 'Authorization: key='. $serverKey;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
    curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
    //Send the request
    $response = curl_exec($ch);
    //Close request
    if ($response === FALSE) {
    die('FCM Send Error: ' . curl_error($ch));
    }
    curl_close($ch);
?>
Shihas
  • 814
  • 15
  • 44
Riajul Islam
  • 1,425
  • 15
  • 19
  • 1
    How to add multiple device id or registration id in to – Shawkat Alam Oct 17 '18 at 11:05
  • 1
    Make an array of your device token $token = ["device_token_1", "device_token_2"] or $token = array("device_token_1", "device_token_2") – Riajul Islam Oct 17 '18 at 11:24
  • 2
    Thanks for the reply , and we need to change the parameter to "registration_ids" else , it will show error – Shawkat Alam Oct 17 '18 at 11:28
  • 1
    I think no problem with variable name but "registration_ids" is standard for FCM. thanks @ShawkatAlam – Riajul Islam Oct 17 '18 at 11:31
  • @RiajulIslam iam getting invalid registration id error – Nishant Saini Feb 27 '19 at 08:19
  • @NishantSaini Invalid Registration ID Check the formatting of the registration ID that you pass to the server. Make sure it matches the registration ID the phone receives in the com.google.firebase.INSTANCE_ID_EVENT intent and that you're not truncating it or adding additional characters. Happens when error code is InvalidRegistration. – Riajul Islam Feb 27 '19 at 09:45
  • very nice digipaz – sirmagid Oct 14 '19 at 10:06
  • it returns message id but nothing happens in registered devices into a topic, I'm sure that the device registration is right because it works when I send a notification manually from firebase console – blank94 Nov 26 '19 at 11:46
  • how do i send my deeplink to open my custom intent in android – saber tabatabaee yazdi Jul 14 '20 at 12:28
  • `'sound' => 'default'` not worked for me. I did not hear any sound when received notification. Any suggestion? Thanks – Kamlesh Sep 06 '21 at 16:31
9

You can send the post request without curl (which was not available on my server)

sendNotification("New post!", "How to send a simple FCM notification in php", ["new_post_id" => "605"], "YOUR_SERVER_KEY");

function sendNotification($title = "", $body = "", $customData = [], $serverKey = ""){
    if($serverKey != ""){
        ini_set("allow_url_fopen", "On");
        $data = 
        [
            "to" => '/topics/new_post',
            "notification" => [
                "body" => $body,
                "title" => $title,
            ],
            "data" => $customData
        ];

        $options = array(
            'http' => array(
                'method'  => 'POST',
                'content' => json_encode( $data ),
                'header'=>  "Content-Type: application/json\r\n" .
                            "Accept: application/json\r\n" . 
                            "Authorization:key=".$serverKey
            )
        );

        $context  = stream_context_create( $options );
        $result = file_get_contents( "https://fcm.googleapis.com/fcm/send", false, $context );
        return json_decode( $result );
    }
    return false;
}
Ambrus Tóth
  • 552
  • 6
  • 14
5

You can use Postman instead. Open Postman extension in chrome and use the POST url https://fcm.googleapis.com/fcm/send.

enter image description here

enter image description here

Ruthwik
  • 539
  • 1
  • 4
  • 5
2
function MultiandroidNotification($deviceToken, $message,$type,$title=null,$sub_title=null,$device_type=null,$data = null,$content_available = null)
{

    if($content_available == 1){
        $content_available = false;
    }else{
        $content_available =  true;
    }
    if($type == 12 || $type == 13){
        $priority = '';
    }else{
        $priority = 'high';
    }

    $deviceToken = array_values($deviceToken);
    $no = null;

    $apiKey = 'XXXXXXXXXXXXXXXXXXXXXX';

    $notification = array("text" => "test",'badge' => "1",'sound' => 'shutter.wav','body'=>$message,'icon'=>'notif_icn','title'=>$title,'priority'=>'high','tag'=>'test','vibrate'=> 1,'alert'=> $message);

    $msg = array('message'=> $message,'title'=> $title,'sub_title'=> $sub_title,'type'=>$type,'activitydata' => $data);

    if($device_type == 'android'){
        $fields = array("content_available" => true,"priority" => "high",'registration_ids'=> $deviceToken,'data'=> $msg);
    }else{
        $fields = array('notification' => $notification,"content_available" => $content_available,"priority" => $priority,'registration_ids'=> $deviceToken,'data'=> $msg);
    }

    $headers = array('Authorization: key=' . $apiKey,'Content-Type: application/json');

    if ($headers){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "https://fcm.googleapis.com/fcm/send");
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
        $response = curl_exec($ch);
    }
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if (curl_errno($ch)) {
            return false; //probably you want to return false
        }
        if ($httpCode != 200) {
            return false; //probably you want to return false
        }
        curl_close($ch);
        return $response;
}
Paul Chu
  • 1,249
  • 3
  • 19
  • 27
satyandera
  • 56
  • 6
  • 1
    Getting error : {"multicast_id":132596829075065854,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidParameters: The data field in the request can not contain duplicate keys."}]} – Aman Deep Mar 06 '21 at 13:06
1
<?php  
 function sendFCM($title, $urduTitle, $pathimg, $tokens) {
  $url1 = 'https://fcm.googleapis.com/fcm/send';
  $apiKey = "AAAA4zDorrw:APA91bHgehYGI5QWyvUv47FWizkjybMK36hdZQH4PHwdGBQcKCBpdCFUSqNSNGZWcO-l07YfIBuXv_lK9rMEr5y0Ms9CvrwCUmuSn8M0aqj3oGg10bpCyxvm0PYrrrvCF-R4zHqSYyqR";
  $headers = array (
    'Authorization:key=' . $apiKey,
    'Content-Type:application/json'
  );
    // Add notification content to a variable for easy reference
  $notifData = [
    'title' => "".$urduTitle,
    'body' => "".$title,
     'priority' => "high",
    'image'=> "".$pathimg//,//Optional
   // 'click_action' => "activities.SinglePostActivity" //Action/Activity - Optional
  ];
  $dataPayload = [
   'to'=> $_SESSION['lastinsertedid'], 
   'title'=>"".$urduTitle, 
   'title1' =>"".$title,
   'channel'=>'Posts',
   'icon' =>"".$pathimg.""
  ];
 // echo $tokens;
  $apiBody = array(
    'notification' => $notifData,
    'data' => $dataPayload,
    'time_to_live' => 600,
    'to' => ''.$tokens
    //'to' => '/topics/all'
  );
  $ch = curl_init();
  curl_setopt ($ch, CURLOPT_URL, $url1);
  curl_setopt ($ch, CURLOPT_POST, true);
  curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt ($ch, CURLOPT_POSTFIELDS, json_encode($apiBody));
  $result = curl_exec($ch);
  return $result;
}
?>
  • Welcome to SO! Please don't post code-only answers but add a little textual explanation about how and why your approach works and what makes it different from the other answers given. You can find out more at our ["How to write a good answer"](https://stackoverflow.com/help/how-to-answer) page. – ahuemmer Dec 29 '22 at 10:14