InvalidRegistration on sending push to muliple devices - php

I'm trying to send push notifications to multiple device using Google Firebase and I always received the error : "InvalidRegistration".
This is the tokens that I sent in the "to"
:json_encode($tokensPerEvent):
["eV9g4oTwjZs:APA91bF3YLGtDkCDekvR6eahbVAn-jIY0sVGjxMWyBEyR-
3AB9q6RBhw4fyeqE4ZkZxQs0TsYhUee9Txy_exAGxtrBPV_-
sjKlWcV3z3nDYXOcVSVwlpPyGzUJKxGMU16drMR41bLI4t"]
and this is the response :
{
"multicast_id":***,
"success":0,
"failure":1,
"canonical_ids":0,
"results":[
{
"error":"InvalidRegistration"
}
]
}
another questions: if the one of the tokens not exist anymore, this is effect on all the other tokens , or just the only old one will effected ?
This is my code:
<?php
require_once '../CommonFunctions.php';
ignore_user_abort();
ob_start();
$url = 'https://fcm.googleapis.com/fcm/send';
//GET TOKENS FROM DB
$db = new Database();
$db->query("SELECT push_token FROM User");
$db1 = new Database();
$db1->query("SELECT phone FROM invite_list where event_id = 137");
$response = $db->resultset();
$response1 = $db1->resultset();
$arr2 = array_column($response1, 'phone');
$phones = join("','",$arr2);
$db2 = new Database();
$db2->query("SELECT push_token FROM User WHERE phone IN ('$phones')");
$tokensPerEvent = array();
$tokensrr = $db2->resultset();
$tokensPerEvent = array_column($tokensrr, 'push_token');
echo json_encode($tokensPerEvent);
$fields = array('to' => json_encode($tokensPerEvent),
'notification' => array('body' => 'HI', 'title' => ':)'));
define('GOOGLE_API_KEY', '***********');
$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_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if($result === false)
die('Curl failed ' . curl_error());
curl_close($ch);
return $result;
?>

If you want to send push notification to many clients by theirs registration ids, you have to use registration_ids instead of to field. You can find this in docs (second parameter).
You are also encoding tokens two times:
$fields = array('to' => json_encode($tokensPerEvent), ...
and
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
Try by skipping encoding $tokensPerEvent in array:
$fields = array('to' => $tokensPerEvent, ...

Related

Android Firebase Push notification using php

I implemented FCM for my app. I'm using php to send the notification for the registered ids in my DB . I want to send a specific message for each user. Now when I push the notification, I'm getting the same message for all the users.
Example:
I have two registered users in the DB:
1- User called John and his custom message is "Welcome"
2- User called Marco and his custom message is "Happy birth day"
Now when I push the notification all the two users are getting the same message "Welcome".
This is my code:
<?php
function send_notification ($tokens, $message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids' => $tokens,
'data' => $message,
'priority' => "high",
);
$headers = array(
'Authorization:key = FCM Server 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;
}
include("conn.php");
mysql_select_db($db, $conn);
$query_users = sprintf("Select token, message From users");
$users = mysql_query($query_users, $conn) or die(mysql_error());
$row_users = mysql_fetch_assoc($users);
$totalRows_users = mysql_num_rows($users);
if($totalRows_users > 0 ) {
do {
$tokens[] = $row_users["token"];
$message = $row_users["message"];
} while ($row_users = mysql_fetch_assoc($users));
}
$message_status = send_notification($tokens, $message);
echo $message_status;
?>
you can send fcm with multiple token at once (1000 token limit if i'm not mistake), but, you cannot send with multiple messages
the message that you send is the message from your last record in your queries
$message = $row_users["message"];
if you want to send with different message, then you need to call
send_notification($tokens, $message);
multiple times.

GCM push notification return error: field data must be a json array

When I am using GCM for push notification , I got an error return as: field "data" must be a JSON array.
When user create the new post then notification will be send to all Registered devices. Any one have some idea of how to solve it? Thank you.
function Notification($post) {
global $wpdb;
$pub_post = get_post($post_ID);
$post_title=$pub_post->post_title;
$totalrecord = $this->get_allrecord();
$message = "Your New post, " .$post_title." has been published";
if (count($totalrecord) > 0) {
//$display_row = null;
foreach ($totalrecord as $row) {
$a = $row->token;
$this->sendPushNotification($a, $message);
}
}
}
function get_allrecord(){
global $wpdb;
$results =$wpdb->get_results('SELECT token FROM wp_push_tokens ', OBJECT);
return $results;
}
function sendPushNotification($registration_ids, $message) {
$apiKey = "xxxxxxxxxxxxxxxxxxxxxxx";
$headers = array("Content-Type:" . "application/json", "Authorization:" . "key=" . $apiKey);
$fields = array(
'register' =>$registration_ids,
'data' =>$message );
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, "https://android.googleapis.com/gcm/send");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true );
// Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, wp_json_encode($fields));
// Execute post
$result = curl_exec($ch);
if($result === false)
die('Curl failed ' . curl_error());
// Close connection
curl_close($ch);
return $result;
}
Your content type is "application/json", which means the "data" field must be a JSON of the form :
"data": {
"message": "your message"
}
Note that the "message" key in this example is custom. You can use whatever keys you wish, and your app will have to search for those keys when it receives the message.
I don't know PHP, but something like this may work :
$fields = array(
'registration_ids' =>$registration_ids,
'data' => array('message' => $message));

GCM Curl connection Error

I am trying to send a message from a server to client (android) using GCM and curl,
the code i used worked perfectly for localhost (emulator and device) , however it would not work for a regular server, attached is the code used and the error message,
are there any additional steps or changes i need to do to make the code work for online server. Any help is appreciated :)
<?php
function Reg($USER_REG_ID)
{
require_once __DIR__ . '/db_connect.php';
$db = new DB_CONNECT();
$response = array();
$API_Key = 'AIzaSyCQgPGhpAzuWGuUd0DCI8pYaXXAItthEsg';
$url = 'https://android.googleapis.com/gcm/send';
$result = mysql_query("SELECT * FROM users where type = 'bus'") or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
$Registration_ID = $row["user_RegID"];
array_push($response, $Registration_ID);
}
//THIS PART SENDS TEH REQUEST USING GCM
$fields = array(
'registration_ids' => $response,
'data' => array(
"message" => $USER_REG_ID
)
);
print_r ($fields);
$headers = array(
'Authorization: key=' . $API_Key,
'Content-Type: application/json'
);
// Open connection
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
// Execute post
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
// Close connection
curl_close($ch);
}
Reg(1)
?>
the fields array
Array ( [registration_ids] => Array ( [0] => APA91bFolV5ZK2diIbTyxwPLp6BqTMdhqaMDYgEsGOlznmxn4NRV6QQzPtfr58ORrpmxq0N_UMwz6s30gWgj--w5SqHxCEHh662PnvjDpGce_4EiHDe-muflVYMOsLlbVDRybvNDubX9aF_RE4VPJdArUsqQjcrQRg ) [data] => Array ( [message] => 1 ) )
The error message
Curl failed: Failed to connect to 2a00:1450:400c:c05::5f: Network is unreachable
This should do it:
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
If the above doesn't work, you can try to disable ipv6 system wide:
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6

The GCM response is not correct, missing },{

I am sending a GCM push message (less then 1000) with:
$Regids = mysql_query("SELECT regid FROM $tabel WHERE active = '1'");
$result_array = array();
while ($row = mysql_fetch_array($Regids)){
$result_array[] = $row['regid'];
}
$headers = array(
'Content-Type:application/json',
'Authorization:key=' . $serverApiKey
);
$data = array(
'registration_ids' => $result_array,
'data' => array(
'type' => 'New',
'title' => 'LH',
'msg' => ''.$msj.''
)
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if ($headers)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$result = curl_exec($ch);
curl_close($ch);
When I print the $result to check (and use for updating the database) it shows:
{"multicast_id":000,"success":274,"failure":75,"canonical_ids":13,"results":[{"message_id":"123"},{"message_id":"123"},{"error":"NotRegistered"},{"error":"NotRegistered"},{"message_id":"123"},{"message_id":"123"},{"registration_id":"456","message_id":"123"}]}
There is no },{ between every (canonical) registration_id and the next (success) message_id or error.
(I shortened the response to make it readable)
So my update part fails
$result = json_decode($result);
for ($i = 0; $i < count($result->{'results'}); $i++) {
if ($result->{'results'}[$i]->{'message_id'}) {
...
} elseif($result->{'results'}[$i]->{'error'}) {
...
} elseif ($result->{'results'}[$i]->{'registration_id'}) {
...
}
}
Does someone know what's wrong?
The format of the response you got is correct . A message for which you get a canonical registration id is still accepted by Google and is therefore successful , and that's why you get a message id in addition to the canonical registration id for that message . That's why there are no brackets after the canonical registration id.

Getting curly braces in output - GCM send multiple data

I am trying to send data to device with GCM but getting curly braces in output(as below image). I'm new to php and I wonder how to fix this issue. Here is the part of PHP server code :
public function send_notification($registatoin_ids, $message, $title) {
// include config
include_once './config.php';
$url = 'https://android.googleapis.com/gcm/send';
$data = array("title" => $title, "message" => $message);
$fields = array(
'registration_ids' => $registatoin_ids,
'data' => $data
);
$headers = array(
'Authorization: key=' . GOOGLE_API_KEY,
'Content-Type: application/json'
);
// Open connection
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
// Execute post
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
// Close connection
curl_close($ch);
echo $result;
}
/////////
I changed the send_message.php like this and it fixed.
if (isset($_GET["regId"]) && isset($_GET["message"]) && isset($_GET["title"])) {
$regId = $_GET["regId"];
$messagem = $_GET["message"];
$titlem = $_GET["title"];
include_once './GCM.php';
$gcm = new GCM();
$registatoin_ids = array($regId);
$message = array("message" => $messagem);
$title = array($titlem);
$result = $gcm->send_notification($registatoin_ids, $messagem, $titlem);
echo $result;`
}
EDIT: sorry, with JSON GCM payload data should be an assoc array. Mixed up with an older flavor of the protocol. That said, what is your intent on the Android side like?
EDIT: dump the whole extra bundle.
Bundle b = intent.getExtras();
for(String k : b.keySet())
Log.d("tag", k + "=" + b.get(k).toString());
edited:
ok, I think your problem is you're posting the value {.....} with no key. it's like saying
http://..... com?{myjson:"stuff"}
I haven't reviewed the api, but it seems it should be something like post "data=".json_encode($fields);

Categories