I am working via Postman to send a FCM push notification to my phone that already has the app installed. I have push notifications enabled, the app is on the background, and I have a valid (confirmed) Firebase push token.
I'm POSTing to https://fcm.googleapis.com/fcm/send with the headers (Authorization: key=APP_SERVER_KEY, Content-Type: application/json), and my body looks like:
{ "notification": {
"title": "Portugal vs. Denmark",
"text": "5 to 1"
},
"to": MY_PUSH_TOKEN
}
I'm getting the following 200 OK response with body:
{
"multicast_id": MULTICAST_ID,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [{
"message_id": "0:MESSAGE_ID"
}]
}
everything looks fine, but I'm not getting a notification on my phone? How can I troubleshoot this, does anyone know what I'm missing?
Found the solution!
But before I offer the solution, here is a bit more background on the situation for others who might find themselves in a similar problem. I was able to POST and send a notification to an Android device, and I was able to send a push via the Firebase console to both Android and iOS device, so the only thing didn't work was sending the push to specifically an iOS device via a POST HTTP request (quite baffling).
I found this discussion here: https://github.com/firebase/quickstart-ios/issues/21. Basically for iOS, I was missing two othere parameters in the request body. I needed to set content_available to true, and priority to high.
so it looked like this:
{
"notification": {
"title": "Portugal vs. Denmark",
"body": "5 to 1"
},
"content_available": true,
"priority": "high",
"to": MY_PUSH_TOKEN
}
I believe the github discussion said something about how those added request body parameters allows FCM to push via APNS for iOS.
Thank you for your answer and explaining your context.
In my context, it wasnt working anyways.
So i added content_available and also replaced "text" with "body"
If anyone is still fighting with that, here it's how i handle it.
Cheers man !
import request from 'request'
const KEYS = require('../hardcodekeys')
export function send (title, message, ids) {
//POST: https://fcm.googleapis.com/fcm/send
//HEADER: Content-Type: application/json
//HEADER: Authorization: key=AIzaSy*******************
let push = {
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
},
content_available: true,
to: ids
priority: 'high'
}
let options = {
method: 'POST',
url: 'https://fcm.googleapis.com/fcm/send',
headers: {
'Content-Type': 'application/json',
'Authorization' : `key=${KEYS.FCM_KEY}`
},
body: JSON.stringify(push)
}
function callback(error, response, body) {
console.log(response.statusCode)
console.log(body)
console.log(error)
if (!error && response.statusCode == 200) {
var info = JSON.parse(body)
console.log(info)
}
}
request(options, callback)
}
Alternative working solution to send push notification to iOS device using php script.
Just change value for keys 'to' from fields array and Authorization from header array as per comment
//To Execute this this from Mac Terminal type php thisFilename.php
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array (
'to' => 'fq5fI_wcXNY:APA91bGpR-qCYW01wNJ8pnp1ftfgR3DHqPk3ViXDqTYrq-p7MUhry9cPcpXEl7z4GFHGUPcTduww656Rks8cOpSZR-FjrseDX4S-eGdzGaBEqI46KWF8ZJmJpegbf3tzVZwILmnf64aU',//Replace with FIRInstanceID.instanceID().token() this you can get in Appdelegate, note this is NOT token received in didRegisterForRemoteNotificationsWithDeviceToken
'notification' => array (
"body" => "message",
"title" => "Title",
"icon" => "myicon"
)
);
$fields = json_encode ( $fields );
$headers = array (
'Authorization: key=' . "AIdfdfzaSyC_0F8sqVqOgdg3Es4trWFcrNcrLpBjG6w06w",//This is Server Key, you can get it from Firebase console -> App Setting -> Cloud Messaging Tab - Legacy 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_POSTFIELDS, $fields );
$result = curl_exec ( $ch );
curl_close ( $ch );
?>
Related
I'm sending push notifications using FCM to Android with MySSQL and PHP. This is my code:
<?php
function send_notification ($tokens, $message)
{
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array(
'registration_ids' => $tokens,
'data' => $message
);
$headers = array(
'Authorization:key = YOUR_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;
}
$conn = mysqli_connect("localhost","root","","fcm");
$sql = " Select Token From users";
$result = mysqli_query($conn,$sql);
$tokens = array();
if(mysqli_num_rows($result) > 0 ){
while ($row = mysqli_fetch_assoc($result)) {
$tokens[] = $row["Token"];
}
}
mysqli_close($conn);
$message = array("message" => " FCM PUSH NOTIFICATION TEST MESSAGE");
$message_status = send_notification($tokens, $message);
echo $message_status;
?>
But I tried sending notifications on iOS(Swift) devices and it does not work. I get the token (FIRInstanceID.instanceID().token()) and try to send a notification from send.php (above code) and not worked.
I send individual/group/topic notification from Firebase Console and worked perfectly. Why doesn't it work from file.php?
help?!
To send iOS through FCM, you need to define notification key in your payload. It is explained in docs please take a look at there. https://firebase.google.com/docs/cloud-messaging/ios/send-multiple
Here is an example request
{
"condition": "'all' in topics",
"priority" : "high",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message Title",
}
}
In the example above I'm sending to the topic named all. You should create topic and subscribe your users to related topics.
You need to make necessary changes in your $fields variable.
I am using Firebase push notifications in my iOS Application. Although I am able to send the notification by sending below payload, it doesn't play a sound when received.
{
"to": "myToken",
"notification": {
"body": "test",
"title": "test"
},
"priority": "high"
"sound": "default"
}
If I send the test message from console, it works well and plays notification sound. Note:
My Authorization code is correct
I am sending http request to https://fcm.googleapis.com/fcm/send
I have tested it on IPhone 4 , IPhone 6 and IPhone 6S, All recieve
notifications without sound
your JSON "sound" : "default" should be inside the "notification" key not in the root of the JSON. This JSON should work.
{
"to": "myToken",
"notification": {
"body": "test",
"title": "test",
"sound": "default"
},
"priority": "high"
}
When using the FCM admin SDK, you have to specify sounds separately for Android and Apple devices:
let message = {
notification: {
'body': 'This is the message the user sees',
},
data: {
'param1': 'specify some extra data here',
},
// Apple specific settings
apns: {
headers: {
'apns-priority': '10',
},
payload: {
aps: {
sound: 'default',
}
},
},
android: {
priority: 'high',
notification: {
sound: 'default',
}
},
token: 'target FCM token goes here',
};
(Note: I've only tested the Apple settings thus far)
payload = {
notification:{
title: 'SOLO has been changed by an administrator',
body: 'Administrator changed your SOLO schedule',
},
android: {
},
apns: {
headers:{
"apns-collapse-id": "solo_changed_administrator",
"content-available": "1",
"apns-priority": "10",
},
payload:{
aps:{
sound: 'default',
badge: 12213123223
}
}
},
data:{
type: 'type'
}
}
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages?authuser=0#ApnsConfig
I had the same problem. When notifications come through FCM to iOS not working sounds or vibrations. Here I followed this link: https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1
And finally went successful. I created my apple notification as an alert in my payload and it works for me. Here is my JSON below to get some idea about my solution.
"apns": {
"payload": {
"aps" : {
"alert" : {
"body": "Notification body",
"title": "Notification title"
},
"badge" : 2,
"sound" : "default"
}
}
}
Note: Please put this "apns" key in the relevant place of your message request. I was using REST call for requesting message.
Please refer the following link to get a good idea of how to send a notification message with platform-specific delivery options.
Link: https://firebase.google.com/docs/cloud-messaging/concept-options#example-notification-message-with-platform-specific-delivery-options
I am playing with ruby & services, I try to retreive a json response, BUT only get an empty body response :
uri = URI("http://.../v1/queryContext")
req = Net::HTTP::Post.new(uri.path, initheader = {'content-type' => 'application/json', 'Accept' => 'application/json'})
req.body = {
"entities": [
{
"type": "Printer",
"isPattern": "false",
"id": "UM1"
}
]
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req)
end
Requests works fine (Status 200 / Message OK) but the JSON content that returns is not there (response.body.size = 0). very strange as I can see that its produced by the server.
Response payload: '{
"contextResponses" : [
{
"contextElement" : {
"type" : "Printer",
"isPattern" : "false",
"id" : "UM1",
"attributes" : [
{
"name" : "bed",
"type" : "float",
"value" : "50"
},
{
"name" : "temperature",
"type" : "float",
"value" : "180"
}
]
},
"statusCode" : {
"code" : "200",
"reasonPhrase" : "OK"
}
}
]
}
'
Also, The following curl equivalent Works fine :
(curl http://.../v1/queryContext -s -S --header 'Content-Type: application/json' \
--header 'Accept: application/json' -d #- | python -mjson.tool) <<EOF
{
"entities": [
{
"type": "Printer",
"isPattern": "false",
"id": "UM1"
}
]
}
EOF
I have the same exact issue using gems like httpclient or unirest. Is There anything special in Ruby that has to be done to receive the awaited json contents ?
Thanks
Your code looks fine, I would suggest clearing bundle's cache (bundle clean --force) and install packages again.
Have you also tried running it on a different machine?
By the way, here's a clear example about doing a json request with the HTTP library you are using:
https://www.socialtext.net/open/very_simple_rest_in_ruby_part_3_post_to_create_a_new_workspace
It seems body of your request pretty print formatted. If you use object mapper or et. could you please check your object mapper have enabled prettyprint property or something like that? If it is enabled, remove it and try again. If you don't use object mapper, try to send a compact body instead of formatted one.
Good luck!
I have enabled the background modes in xcode and checked "Remote notifications".
Do I have to enable "Push Notifications" too? for GCM
here is the payload from my rest client
{
"data": {
"displayMessage": {
"message": "Package delivered",
}
},
"registration_ids": [
"dgfdghdfghgfhhfjhgjghjghjhjghjghjghjghjghjghjhgggh"
],
"content-available" : true,
"priority": "high"
}
This works when the app is in foreground and does not work when the app is not in foreground.
Any help to get this GCM for ios working would be highly appreciated.
I would suggest to check the format of the message as it is mentioned here :
Making GCM work for iOS device in the background
Your key is wrong. Use content_available, not content-available.
Also, your JSON is invalid. Specifically, this:
"message": "Package delivered",
should not have a comma at the end.
This issue occurred from server side. Notification message body should be like this.
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"content_available" : "true"
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark"
}
}
Here is the code that I have implemented and working fine.
<?php
// Message to send
$notificationTitle = "Notification title";
$notificationtBody = "Notification arrived";
$registrationId = 'GCM_DEVICE_TOKEN';
$apiKey = "GCM_SERVER_KEY";
$response = sendNotification(
$apiKey,
$registrationId,
array(
'sound' => "default",
'badge' => 1,
'body' => $notificationtBody,
'title' => $notificationTitle
)
);
echo $response;
function sendNotification( $apiKey, $registrationId, $messageData )
{
$headers = array("Content-Type:" . "application/json", "Authorization:" . "key=" . $apiKey);
$data = array(
'to' => $registrationId,
'content_available' => true,
'notification' => $messageData
);
$ch = curl_init();
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_URL, "https://android.googleapis.com/gcm/send" );
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($data) );
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
This notification worked for me
{
"to":"ID",
"notification":{
"sound":"default",
"title":"TITLE",
"body":"BODY"
},
"priority": "high"
}
Running into parseError attempting to follow the "start a resumable session" YouTube Data API - Resumable Uploads documentation.
complete list of efforts ,response and code
I read on the Google APIs - "Global domain errors" page "parseError The API server cannot parse the request body."
I have watched "YouTube Developers Live: Debugging & Dealing with Errors" still know clue there
I have read "stack over flow" for similar questions, but never get answered,or answers are still un clear
the test youtube account i want to upload to has a youtube channel with videos
I tried the client PHP upload API, but found out later its not a resumable upload.
I thought resumable upoad would be a better option, so i dont frustrate users, by wasting there time,if there connection drops out....
I am runing PHP from hostgator account
I noticed how when i did not get an error, it would return the regular snippet and status data and not the "Step 2 - Save the resumable session URI" data
I am using long lived access tokens pulled from my database...in the requests, the youtube user has a channel with videos before i stored the access tokens
I do check the access tokens with tokeninfo?
I noticed changing "uploadType" to "uploadtype" would produce "message": "Media type 'application/json; charset=utf-8'
is not supported. Valid media types: [video/*, application/octet-stream]",following this error by changing content type to "application/octet-stream" would return "kind = youtube#video
object with json snippet,status" not the Step 2 - Save the resumable session URI, so i changed things back to "uploadType" and "application/json; charset=utf-8" now facing same parse error
I notice in the docs "Parameter values in the request URL must be URL-encoded." when i would urlencode() "Parameter values" it would return errors or parseError when i removed the urlencode function
Even changing "Host: www.googleapis.com" to "Host: https://www.googleapis.com" would produce "The requested URL /upload/youtube/v3/videos was not found on this server. That’s all we know."
parse error appears to be most persistent so far
I have changed urlencode() to rawurlencode() still parse error
i would add charset=utf-8;multipart/form-data;application/octet-stream to content type header, still parse error
I notice content type on string is text/plain; charset=us-ascii not sure if google server expects pure application/json
any help would be great…
Array
(
[response] => Array
(
[0] => {
"error": {
"errors": [
{
"domain": "global",
"reason": "parseError",
"message": "Parse Error"
}
],
"code": 400,
"message": "Parse Error"
}
}
)
[headers] => [
"POST \/upload\/youtube\/v3\/videos?uploadType=resumable&part=snippet,status HTTP\/1.1",
"Host: www.googleapis.com",
"Authorization: Bearer ya29.vAAY5n3SJq3uCG7z4tOhehDxYj9Z7mxFENtD5PKF_dJqFlLqwCktRHTrEJkUgY_NrJD3KMetKeBA_w",
"Content-Length: 303",
"Content-Type: application\/json; charset=utf-8",
"X-Upload-Content-Length: 20121",
"X-Upload-Content-Type: video\/*"
]
[curl_resource] => Resource id #18
[video_aray] => {
"snippet": {
"title": "test video",
"description": "testing api",
"tags": [
"any",
"thing"
],
"categoryId": 25
},
"status": {
"privacyStatus": "public",
"embeddable": true,
"license": "youtube"
}
}
[json_requestbody] => {
"snippet": {
"title": "test video",
"description": "testing api",
"tags": [
"any",
"thing"
],
"categoryId": 25
},
"status": {
"privacyStatus": "public",
"embeddable": true,
"license": "youtube"
}
}
[request_url] => https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status
[content_type_of_request] => text/plain; charset=us-ascii
[0] => text/plain; charset=us-ascii
[1] => text/plain; charset=us-ascii
)
Source
public function startResumableSession()
{
$videoResource = array( 'snippet'=>array('title'=>"test video",'description'=>"testing api",
'tags'=>array("any","thing"),'categoryId'=>25),
'status'=>array('privacyStatus'=>"public",'embeddable'=>True,'license'=>"youtube"));
$requestBody = json_encode($videoResource,JSON_PRETTY_PRINT);
$headers = array
(
"POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status HTTP/1.1",
"Host: www.googleapis.com",
"Authorization: Bearer ya29.vAAY5n3SJq3uCG7z4tOhehDxYj9Z7mxFENtD5PKF_dJqFlLqwCktRHTrEJkUgY_NrJD3KMetKeBA_w",
"Content-Length: ".strlen($requestBody),
"Content-Type: application/json; charset=utf-8",
"X-Upload-Content-Length: 20121",
"X-Upload-Content-Type: video/*"
);
/* Parameter values in the request URL must be URL-encoded. */
$url = "https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch, CURLOPT_POSTFIELDS,urlencode($requestBody));
curl_setopt($ch, CURLOPT_RETURNTRANSFER,TRUE);
$result = curl_exec($ch);
$json = json_decode($result);
/* Check request body contenttype */
$finfo = new finfo(FILEINFO_MIME);
$t1= $finfo->buffer($requestBody);
$t2 = $finfo->buffer("test");
$t3 = $finfo->buffer(utf8_encode("test"));
/* debug info */
return array( 'response'=>(array)$result,
'headers'=>json_encode($headers,JSON_PRETTY_PRINT),
'curl_resource'=>$ch,
'video_aray'=>json_encode($videoResource,JSON_PRETTY_PRINT),
'json_requestbody'=>$requestBody,
'request_url'=>$url,
'content_type_of_request'=>$t1,$t2,$t3
);
}
Easy answer is - you do it wrong.
You are NOT supposed to add "POST", "Host:" and "Content-Length:" into $headers because that is generated by curl (CURLOPT_URL and CURLOPT_POSTFIELDS).
YouTube API works correctly. It is not their fault.