I have a PHP application, through which users can send out alerts (to read a message) to clients who have an app installed. It seems to work pretty well, but I have a consistent small percentage of recipients who say they never get any alerts on their phones. The problem doesn't seem to be restricted to any particular model of phone, and the few users I've spoken to have had the relevant notification permissions allowed.
My code:
First I loop through the recipients identified by the web application and create a notification packet per recipient device:
$packets = [];
foreach($messages_to_send as $msg)
{
$message_id = intval($msg['message_id']);
$device_token = $msg['device_token'];
if(!isset($packets[$device_token]))
$packets[$device_token] = [];
if(!isset($packets[$device_token][$message_id])) {
$packets[$device_token][$message_id] = [
'notification' => [
'title' => 'A new message has been received!',
'body' => 'Open notifications',
'sound' => 'default',
'badge' => '1'
],
'priority' => 'high',
'data' => [
'type' => 'sms',
'msg_id' => $message_id,
]
];
}
}
Then I loop through those packets and send a cURL request to FCM per message, per device:
$headers = [];
$headers[] = 'Content-Type: application/json';
$headers[] = 'Authorization: key='. $server_key;
foreach($packets as $device_token => $messages)
{
foreach($messages as $msg_id => $messages_to_send)
{
$msg_json = json_encode($messages_to_send);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $fcm_url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $msg_json);
curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//Send the request
$curl_response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = null;
if( ($httpCode != 200) || (curl_errno($ch)) )
$curl_error = ($httpCode != 200) ? 'Firebase response not received (200)' : 'Firebase cURL error: ' . curl_strerror(curl_errno($ch));
curl_close($ch);
$curl_response = json_decode($curl_response, true);
$status = null;
$sent_ok = 0;
if($curl_error !== null)
$status = $curl_error;
else
{
if($curl_response['success'] != 1)
$status = 'FCM failure';
else
{
if(!isset($curl_response['results'][0]['message_id']))
$status = 'Device token no longer recognised by FCM';
else
{
$sent_ok = 1;
$status = $curl_response['results'][0]['message_id'];
}
}
}
// Register the sending status per recipient
}
}
I would love to get this issue closed off. Is there anything wrong with the way I am sending out these notifications? If not, what (other than express permissions) would cause a device to not display an alert?
Related
I'm send push notifications using php, what I've realise is the push notification comes to the phone, but fails to send the additional data I add to the script for example page etc.
<?php
$url = "https://fcm.googleapis.com/fcm/send";
$token = 'device_id here';
$serverKey = 'AIzaSxxxbAGLyxxxx';
$title = "New Message";
$body = 'Hello there';
$notification = array('title' =>$title , 'message' => $body,'priority'=>'high','badge'=>'1','notId'=>''.time(), 'id' => '33','page' => 'news');
$arrayToSend = array('to' => $token, 'notification' => $notification);
$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);
?>
You are attempting to add custom data fields to a Notification message. Notification messages only allow certain fields. If you want to send custom data then you need to make your message a Data message or a Notification message with data payload.
From the FCM docs a combination Notification message with data payload for android could look like this:
{
"to":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"New Message",
"body":"Hello there"
},
"data" : {
"notId" : 201801,
"id" : 33,
"page" : "news",
}
}
Make these changes to the message structure:
$notification = array('title' =>$title , 'message' => $body);
$data = array('notId'=>''.time(), 'id' => '33','page' => 'news');
$arrayToSend = array('to' => $token, 'notification' => $notification, 'data' => $data);
You will need to change your android code to accommodate the data field and parse the data accordingly.
Please read the FCM documentation carefully is see which ramifications this change can have on your project. Most importantly, how data messages are handled when you app is in the background!
When my app opens for the first time, I save the user's device ID into a table in my database. When I select from the table with my below script to send push notifications,
PHP SCRIPT
$stmt = $conn->query("SELECT device_id from devices");
$gcmRegIds = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
array_push($gcmRegIds, $row['device_id']);
}
//echo json_encode($gcmRegIds);
$url = "https://fcm.googleapis.com/fcm/send";
$token =$gcmRegIds;
$serverKey = 'AIzxxyBbAxxxxxx-rJ0zoTExxx1Q';
$title = "New Alert from NCSC";
$body = 'test';
$notification = array('title' =>$title , 'message' => $body);
$data = array('timestamp'=>''.time(), 'id' => '90','display' => 'alert');
$arrayToSend = array('to' => $token, 'notification' => $notification, 'data' => $data);
$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);
I get this error `Field "to" must be a JSON string:
["fAx8pL2Ms9w:APA91bxxxxxnBidJg-kSxhA0DbfzmN9P6vrdxxxxxxxx-P"]
when I change this line of code
$token = json_encode($gcmRegIds);
to json format I get this error
{
"multicast_id": 5909880630769187000,
"success": 0,
"failure": 1,
"canonical_ids": 0,
"results": [
{
"error": "InvalidRegistration"
}
]
}
which means the ID which I'm picking from the db is from, but when I hard code the device ID in the script, it's able to send the push notification.
I am developing a facebook chatbot. I am facing a issue which I cannot solve. I am developing this in laravel. Here I cannot get the postback payload. here is my code
public function index(Request $request) {
if ($request->hub_verify_token === $this->verifyToken) {
echo $request->hub_challenge;
exit;
}
$input = json_decode(file_get_contents("php://input"), true);
$senderId = $input['entry'][0]['messaging'][0]['sender']['id'];
$messageText = $input['entry'][0]['messaging'][0]['message']['text'];
$pageId = $input['entry'][0]['id'];
$accessToken = "access_token_that_got_from_fb";
//set Message
if($messageText != "") {
$answer = "Howdy! User";
}
if($messageText == "hello") {
$answer = 'Testing hello from bot';
}
foreach ($input['entry'][0]['messaging'] as $message) {
// When bot receive message from user
if (!empty($message['postback'])) {
$answer = 'got it tada';
}
}
//send message to facebook bot
$response = [
'recipient' => [ 'id' => $senderId ],
'message' => [ 'text' => $answer ] //json_encode($request->getContent())
];
$ch = curl_init('https://graph.facebook.com/v2.11/me/messages?access_token='.$accessToken);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($response));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$result = curl_exec($ch);
curl_close($ch);
}
and my route is
Route::any('chatbot', 'ChatbotController#index');
here the message is working . but the postback payload request is not going to server. on the other hand using the same code in normal php file I am able to get postback paylod.
$hubVerifyToken = 'chatbot';
$accessToken = "access_token";
// check token at setup
if ($_REQUEST['hub_verify_token'] === $hubVerifyToken) {
echo $_REQUEST['hub_challenge'];
exit;
}
// handle bot's anwser
$input = json_decode(file_get_contents('php://input'), true);
$senderId = $input['entry'][0]['messaging'][0]['sender']['id'];
$messageText = $input['entry'][0]['messaging'][0]['message']['text'];
$postback = isset($input['entry'][0]['messaging'][0]['postback']['payload']) ? $input['entry'][0]['messaging'][0]['postback']['payload'] : '' ;
//set Message
if($messageText == "hi") {
$answer = "Hello";
}
if($messageText == "hello") {
$answer = "Hello there, welcome to Chatleads";
}
if($postback) {
$answer = "postback TADA";
}
//send message to facebook bot
$response = [
'recipient' => [ 'id' => $senderId ],
'message' => [ 'text' => $answer ]
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://graph.facebook.com/v2.11/me/messages?access_token=$accessToken");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($response));
curl_setopt($ch, CURLOPT_POST, 1);
$headers = array();
$headers[] = "Content-Type: application/json";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
How to solve this issue? can anyone show me a path?
Solved it by checking at laravel.log file.
$this->messageText = isset($this->input['entry'][0]['messaging'][0]['message']['text']) ? $this->input['entry'][0]['messaging'][0]['message']['text'] : '' ;
messageText should be like this. that's why its causing an error.
I am trying to send push notification from my react native app using fcm and php as server.Following is my code in react to receive notification from server.
pushNotification.js
import React, { Component } from "react";
import FCM from "react-native-fcm";
export default class PushNotification extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
// this method generate fcm token.
FCM.requestPermissions();
FCM.getFCMToken().then(token => {
console.log("TOKEN (getFCMToken)", token);
});
// This method get all notification from server side.
FCM.getInitialNotification().then(notif => {
console.log("INITIAL NOTIFICATION", notif)
});
// This method give received notifications to mobile to display.
this.notificationUnsubscribe = FCM.on("notification", notif => {
console.log("a", notif);
if (notif && notif.local_notification) {
return;
}
this.sendRemote(notif);
});
// this method call when FCM token is update(FCM token update any time so will get updated token from this method)
this.refreshUnsubscribe = FCM.on("refreshToken", token => {
console.log("TOKEN (refreshUnsubscribe)", token);
this.props.onChangeToken(token);
});
}
// This method display the notification on mobile screen.
sendRemote(notif) {
console.log('send');
FCM.presentLocalNotification({
title: notif.title,
body: notif.body,
priority: "high",
click_action: notif.click_action,
show_in_foreground: true,
local: true
});
}
componentWillUnmount() {
this.refreshUnsubscribe();
this.notificationUnsubscribe();
}
render() {
return null;
}
}
My php script is as follows.Here i am trying to send notification by taking the device token of each user.
notification.php
<?php
include 'db.php';
$check_json = file_get_contents('php://input');
$obj= json_decode($check_json);
$uid =$obj->{'uuid'};
$fcm =$obj->{'fcm'}
$to =$fcm;
$data = array(
'title'=>"Testmessage",
'message'=>"You have a new request");
function send_message($to,$data){
$server_key=
'*******';
$target= $to;
$headers = array(
'Content-Type:application/json',
'Authorization:key=' .$server_key
);
$ch = curl_init();
$message = array(
'fcm' => $to,
'priority' => 'high',
'data' => $data
);
curl_setopt_array($ch, array(
CURLOPT_URL => 'https://fcm.googleapis.com/fcm/send',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => json_encode($message)
));
$response = curl_exec($ch);
}
curl_close($ch);
//echo $response;
return $response;
?>
I am testing this on a real device and an emulator.Trying to send push notification from a real device to an emulator (possible right?) .But not working.Can anybody please help me.I am new to react , so please..
It's possible to send Push notifications from physical device to Emulator but the Emulator should registered with the FCM
public function sendMessageThroughFCM($arr) {
//Google Firebase messaging FCM-API url
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = (array) $arr;
define("GOOGLE_API_KEY","XXXXXXXXXXXXXXXXXXXXX");
$headers = array(
'Authorization: key=' . GOOGLE_API_KEY,
'Content-Type: application/json'
);
$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, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
return $result;
}
Framing the array to send notification
$arr = array(
'registration_ids' => $androidTokens,
'notification' => array( 'title' => $notificationTitle, 'body' => $notificationBody),
'data' => array( 'title' => $notificationTitle, 'body' => $notificationBody)
);
Push the list of FCM tokens to which device you need to send the notification
array_push($androidTokens,$token['Fcm_registration_token']);
Refresh the FCM token if it's not generated
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Update the refreshedToken to server through an API call.
I have tried Firebase notification with Laravel to send notification to IOS and Android devices.
But IOS device not received the notifications but Android devices working good.
So what is the issue in my script?
I have tried following,
$firebase = new \Firebase();
$push = new \Push();
// optional payload
$payload = array();
$payload['team'] = 'India';
$payload['score'] = '5.6';
// notification title
$title = Input::get('title');
// notification message
$message = Input::get('message');
// push type - single user / topic
$push_type = Input::get('push_type');
// whether to include to image or not
$include_image = Input::get('include_image') ? TRUE : FALSE;
$include_image = TRUE;
$push->setTitle($title);
$push->setMessage($message);
if ($include_image) {
$push->setImage('http://api.androidhive.info/images/minion.jpg');
} else {
$push->setImage('');
}
$push->setIsBackground(FALSE);
$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 = Input::get('regId');
$response = $firebase->send($regId, $json);
}
I have refer this question but there is no answer provided.
you need a 'notification' json block for iOS to respond
$url = "https://fcm.googleapis.com/fcm/send";
$token = "";
$serverKey = '';
$title = "Title";
$body = "Body of the message";
$notification = array('title' =>$title , 'text' => $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);