How to send a notification to device using firebase admin - node.js

I am adding notification support to an app. I'm using react native firebase for the react native client and am able to receive notification sent by the console.
However, when I send the notification using the firebase admin tool no notification is received.
firebase admin is initialised once on server startup
let admin = require('firebase-admin')
let serviceAccount = require('../../appname-firebase-admin.json')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://appname-12e14.firebaseio.com',
})
console.log('initialise firebase admin')
and then I've made this test function based on the firebase admin documentation
async function sendNotification() {
let admin = require('firebase-admin')
let registrationToken =
'super-long-token-goes-here'
let message = {
notification: { title: 'Super title', body: 'this is a test' },
token: registrationToken,
}
admin
.messaging()
.send(message)
.then(response => {
// Response is a message ID string.
console.log('Successfully sent notification:', response)
return { success: true }
})
.catch(error => {
console.log('Error sending notification:', error)
})
return {
success: true,
}
}
this results in
Successfully sent notification: projects/appname-12e14/messages/0:1574700947563522%48f1ba652348f1ba99
with no notification on the device.
edit: I've also tried using .sendToDevice()

React-native-firebase does display the notifications in an open app, you can create a custom notification and use the component you like to show it in app. Alternatively you can use a third-party service like Notify, which has a simple API to manage them.

Related

is it possible to send push notification to only active clients using firebase cloud messaging and node.js server

I want to know wether it is possible to send push notification using firebase cloud messaging and node.js server? How can I do this?
Yes, It is possible using either API endpoints provided by firebase or by using firebase-admin npm package.
Minimal Example -
const firebaseAdmin = require('firebase-admin')
if (!firebaseAdmin.apps.length) {
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccountJson),
databaseURL: databaseUrl
})
}
// This registration token comes from the client FCM SDKs.
const registrationToken = 'YOUR_REGISTRATION_TOKEN';
const message = {
data: {
score: '850',
time: '2:45'
},
token: registrationToken
};
// Send a message to the device corresponding to the provided
// registration token.
firebaseAdmin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
For further documentation please refer to -
https://firebase.google.com/docs/cloud-messaging/send-message

Why message id from Firebase Cloud Messaging is empty

I am migrating from legacy HTTP to v1 using the NPM firebase-admin module. But I have the problem that when sending the notification it doesn't give any error, but it doesn't return the message-id and the notification is not received on the device.
Node version: 12.14.1.
firebase-admin version: 9.6.0
Server code:
const admin = require('firebase-admin');
var serviceAccount = require('./file.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const messaging = admin.messaging();
async function sendPush() {
const message2 = {
notification: {
title: 'test title',
body: 'test'
},
token: 'valid-token'
};
try {
const test = await messaging.send(message2);
console.log('--------------------------Successfully sent message:--------------------------');
console.log(test);
console.log('------------------------------------------------------------------------------');
} catch(err) {
// Will catch both thrown exceptions as well as rejections
console.log('--------------------------Error sending message:', err);
}
}
When I send a notification using the sendPush function, I receive the following response in the console:
--------------------------Successfully sent message:--------------------------
projects/project-name/messages/
------------------------------------------------------------------------------
It does not contain the message-id specified in the docs and I am not receiving the notification.
Docs sample response:
projects/myproject-b5ae1/messages/0:1500415314455276%31bd1c9631bd1c96
Edit:
I tested the sendToDevice function (Legacy API) from firebase-admin and it works.
messaging.sendToDevice('valid-token', message)
.then(response => {
console.log('--------------------------Successfully sent message:--------------------------');
console.log(response);
console.log('------------------------------------------------------------------------------');
})
.catch(err => {
console.log('--------------------------Error sending message:', err);
});
The push is delivered. But send, sendMulticast and sendAll (v1 API) still not working.
Solved.
The problem was that the token coming from android was not correct for the new FCM versions. After updating the token generation in the apps, it has started to work with both legacy and v1.

credentials used to authenticate does not have permission

I am trying to use firebase cloud messaging to deploy a http push notifications onto an actual device. When so, I am getting the error
"The credential used to authenticate this SDK does not have permission to send messages to the device corresponding to the provided registration token. Make sure the credential and registration token both belong to the same Firebase project."
I have checked the credentials on both the frontEnd and backEnd side and they all match up with my firebase correctly. I have tried to follow plenty of examples on here and I have missed on all of them. My node.js file looks like
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
export GOOGLE_APPLICATION_CREDENTIALS = "/Users/myname/mylocation/myfile.json"
exports.sendPushNotifications = functions.https.onRequest((req, res) => {
res.send("Attempting to send push notification")
console.log("LOGGER --- Trying to send push message..");
var uid = 'randomUIDString'
var fcmToken = 'myToken'
return admin.database().ref('/users/' + uid).once('value', snapshot => {
var user = snapshot.val();
console.log("username is " + user.name);
var payload = {
notification: {
title: 'Push Notification Title',
body: 'Test Notification Message'
}
}
admin.messaging().sendToDevice(fcmToken, payload)
.then(function(response) {
console.log('Succesfully sent message:', response);
console.log(response.results[0].error);
})
.catch(function(error) {
console.log('Error sending message', error);
});
})
})
The users name prints from calling the uid, but I am having trouble accessing the fcmToken.
I have checked my info.plist and the correct project is listed. Same with apple developer and appDelegate. is there something more that I am missing??

Firebase web push notification with NodeJS not working

I'm building an app that sends web push notifications using firebase and a NodeJs server but I'm getting a 'mismatched-credential' error, how can I fix this?
I'm first generating a json file that 'generate private key' button from the console gave me , and adding the admin SDK to my app, from my server code, this way
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://nodeproject-2bc3o.firebaseio.com"
});
Then I'm building the send request
// This registration token comes from the client FCM SDKs.
var registrationToken = 'YOUR_REGISTRATION_TOKEN';
var message = {
data: {
score: '850',
time: '2:45'
},
token: registrationToken
};
// Send a message to the device corresponding to the provided
// registration token.
admin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
The docs says that // This registration token comes from the client FCM SDKs so I'm using the token I got from the client as my registrationToken, which I retrieved the following way , from my client javascript code , and then sent to the server
messaging.getToken().then((currentToken) => {
if (currentToken) {
sendTokenToServer(currentToken);
updateUIForPushEnabled(currentToken);
}
Finally, after sending a message from the server, using the token , I get the following error
errorInfo: {
code: 'messaging/mismatched-credential',
message: 'SenderId mismatch'
},
codePrefix: 'messaging'
}
Which is the correct way to retrieve the client token , send it to the server , and then use it to send a push notification to the client? Or what I'm I doing wrong?
If you use Firebase Cloud Functions as backend server then the serviceAccountKey.json is not necessary and more simple.
See https://firebase.google.com/docs/functions/get-started#import-the-required-modules-and-initialize-an-app
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Cloud Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
These lines load the firebase-functions and firebase-admin modules, and initialize an admin app instance from which Cloud Firestore changes can be made.
And, fcm sample is https://github.com/firebase/functions-samples/tree/master/fcm-notifications

Send push notifications with two Firebase projects

I'm using Admin SDK for node.js for sending the push notifications. Followed the tutorial and initialized the multiple projects with like examples given with this link.
I need to know how to send push notifications with two projects using with node.js. Used below methods for sending notifications two projects based its working with default project but another project getting error like below
exports.send_test_mailer = function(req, res) {
// Default project
var registrationToken = ["f-vRsDouUFQ:APA91bGktVzu3WjKGqeXqdiYPI8B0lQXs34TkJS4p7LaMiFGfp5LdfB1ZjEhO3CY5ci92apqgt1hEJY0ml11C4hxYUaPfDl7PeDHhcmDGur0JUx5l3M2mLEj30epwRBWVsE4xMSTls4f"];
var payload = {
notification: {
title: "driver app",
body: "driver app push notfications on the day."
},
data: {
score: "850",
time: "2:45"
}
};
firebaseAdmin.messaging().sendToDevice(registrationToken, payload)
.then(function(response) {
console.log("Successfully sent message driver:", JSON.stringify(response));
})
.catch(function(error) {
console.log("Error sending message driver:", JSON.stringify(error));
});
// Second project
var registrationTokens = ["dzXRXUMIB5w:APA91bHSArtroO8M33IHxaslQTugTcEzJcfkbsXEhwbXbvVzBws-aqG4aqKNr37j8WpZev7lolX7cFQlAKYZ1QV_EgC6zTGeT41n3lvSpcDyBg6t4SZZaoPe7nUO9sbdcXA2KDguxAbk"];
var payloads = {
notification: {
title: "customer app",
body: "customer app push notfications on the day."
},
data: {
score: "850",
time: "2:45"
}
};
firebaseAdmin.messaging().sendToDevice(registrationTokens, payloads)
.then(function(response) {
console.log("Successfully sent message customer:", JSON.stringify(response));
})
.catch(function(error) {
console.log("Error sending message customer:", JSON.stringify(error));
});
};
Error
{"results":[{"error":{"code":"messaging/registration-token-not-registered","message":"The provided registration token is not registered. A previously valid registration token can be unregistered for a variety of reasons. See the error documentation for more details. Remove this registration token and stop using it to send messages."}},{"error":{"code":"messaging/mismatched-credential","message":"The credential used to authenticate this SDK does not have permission to send messages to the device corresponding to the provided registration token. Make sure the credential and registration token both belong to the same Firebase project."}}],"canonicalRegistrationTokenCount":0,"failureCount":2,"successCount":0,"multicastId":9014981858701063000}
Here is my answer
var ServiceAccount = require("./path your default app file.json");
var ServiceAccount1 = require("./path your second app file.json");
var serviceAppConfig = {
credential: firebaseAdmin.credential.cert(ServiceAccount),
databaseURL: "https://your firebase default app url"
};
// Initialize the default app
var serviceApp = firebaseAdmin.initializeApp(serviceAppConfig);
//console.log(serviceApp.name); // "[DEFAULT]"
// Retrieve services via the defaultApp variable...
var serviceAuth = serviceApp.auth();
var serviceDatabase = serviceApp.database();
// Get the Messaging service for the default app
global.serviceMessaging = firebaseAdmin.messaging();
var service1AppConfig = {
credential: firebaseAdmin.credential.cert(ServiceAccount1),
databaseURL: "https://your firebase url second app"
};
// Initialize another app with a different config
var service1App = firebaseAdmin.initializeApp(service1AppConfig, "App2 name");
// Use the otherApp variable to retrieve the other app's services
var service1Auth = service1App.auth();
var service1Database = service1App.database();
// Get the Messaging service for a given app
global.service1Messaging = firebaseAdmin.messaging(service1App);

Resources