Firebase cloud function / notification - firebase

I am trying to make a notification function to deploy using cloud functions of firebase
I did the first part of the code and it was successfully done which is:
'use-strict'
const functions = require('firebase-functions');
//const paypal=require('paypal-rest-sdk');
const admin=require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification=functions.firestore
.document("Users/{user_id}/Notifications/{notification_id}")
onWrite((change, context)=>{
const user_id=context.params.user_id;
const notification_id=context.params.notification_id;
});
without returning promise and it was ok but when i tried to complete like this:
'use-strict'
const functions = require('firebase-functions');
//const paypal=require('paypal-rest-sdk');
const admin=require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification=functions.firestore
.document("Users/{user_id}/Notifications/{notification_id}")
.onWrite((change, context)=>{
const user_id=context.params.user_id;
const notification_id=context.params.notification_id;
return admin.firestore().collection("Users").doc(user_id)
.collection("Notifications")
.doc(notification_id)
.get()
.then(queryResult=>{
const from_user_id=queryResult.data().from;
const from_data=admin.firestore()
.collection("Users").doc(from_user_id).get();
const to_data=admin.firestore().collection("Users")
.doc(user_id).get();
return Promise.all([from_data,to_data]).then(result=>{
const from_name=result[0].data().name;
const to_name=result[1].data().name;
console.log("from :"+from_name+"TO"+to_name);
});
});
// console.log("user_id"+ user_id+ "notification_id"+notification_id);
});
I have these 2 errors in node.cm:
1-Avoid nesting promises
2-each then()should return a value
how can i fix this problem???

Send push notification through FCM and cloud function when a change in Firestore database
You can try like this
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.firestore
.document('/users/{documentId}')
.onWrite((change, context) => {
console.log("CHANGE in DOCUMENT ID : " + context.params.documentId);
// Fetch data using standard accessors
const userId = change.after.data().userId;
const ownerId = change.after.data().ownerId;
console.log('We have a new request UID:', userId, 'for owner:', ownerId);
const owner_data = admin.firestore().collection('users').doc(ownerId).get();
const user_data = admin.firestore().collection('users').doc(userId).get();
return Promise.all([owner_data, user_data]).then(result => {
const ownerFCMToken = result[0].data().fcmToken;
const userName = result[1].data().displayName;
console.log("OWNER Token : " + ownerFCMToken + " USER: " + userName);
const payload = {
notification: {
title: 'Test title!',
body: `${userName} sent you a following request.`
// icon: follower.photoURL
}
};
admin.messaging().sendToDevice(followedFCMToken, payload)
.then(function (response) {
console.log("Push response : " + response);
return response
})
.catch(function (error) {
console.error("Error in sending push");
});
});

Related

Stripe presentPaymentSheet() method does not dismiss itself and return any kind of response React Native

Hello I am trying to integrate stripe payment method in react native app everything work fine except for last step in which presentPaymentSheet has to dismiss and payment should be successfull in stripe account but it says incomplete in stripe account.
Client Side Code
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const { paymentIntent, ephemeralKey, customer } =
await fetchPaymentSheetParams();
const { error } = await initPaymentSheet({
customerId: customer,
customerEphemeralKeySecret: ephemeralKey,
paymentIntentClientSecret: paymentIntent.client_secret,
});
if (!error) {
setPaymentSheetEnabled(true);
}
const openPaymentSheet = async () => {
if (!clientSecret) {
return;
}
setLoading(true);
const { error } = await presentPaymentSheet();
console.log({error});
}
Server Side Code
const functions = require("firebase-functions");
const stripe = require("stripe")(functions.config().stripe.secret);
console.log(stripe);
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
exports.paymentSheet = functions.https.onRequest(async (req, res) => {
const db = admin.firestore();
const uid = db.collection("place_order").doc("id");
const id = await uid.get();
const cityRef = db.collection("orders").doc(id.data().id);
const doc = await cityRef.get();
const price = doc.data().order;
const code = db.collection("settings").doc("currency");
const currencyCode = await code.get();
const cCode = currencyCode.data().code;
const customer = await stripe.customers.create();
const ephemeralKey = await stripe.ephemeralKeys.create(
{customer: customer.id},
{apiVersion: "2022-08-01"},
);
const paymentIntent = await stripe.paymentIntents.create({
amount: price[price.length - 1].order_data[0].price * 100,
currency: cCode,
customer: customer.id,
automatic_payment_methods: {
enabled: true,
},
});
res.json({
paymentIntent: paymentIntent,
ephemeralKey: ephemeralKey.secret,
customer: customer.id,
});
});

How to use the app object in cloud functions without passing it as parameter?

I am building cloud functions for the backend of my app but I couldn't figure out a way to use the app or db variables without passing them into my functions as parameters. I tried initializing the apps seperately in its own functions but multiple app initialization of the same app is not allowed but I want to use only one app.
So the question is, is there a way to implement the below code without passing the app/db parameter into every function?
PS: Also I would appreciate if you could suggest few tips to improve the quality of the file structuring and how I import / export functions.
index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const cors = require("cors")({ credentials: true, origin: true });
const app = admin.initializeApp();
const db = app.firestore();
const { addVehicle } = require("./src/vehicles/addVehicle");
const { getVehicles } = require("./src/vehicles/getVehicles");
exports.addVehicle = functions.https.onRequest(async (req, res) => {
cors(req, res, async () => {
const result = await addVehicle(req, res, db);
res.json((result));
});
});
exports.getVehicles = functions.https.onRequest(async (req, res) => {
cors(req, res, async () => {
res.json((await getVehicles(req,res,db)));
});
});
addVehicle.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const Vehicle = require("../../models/Vehicle");
exports.addVehicle = async (req, res, db) => {
try{
const vehicleInfo = new Vehicle(req.body);
const addedVehicle = await db.collection("vehicles").add(vehicleInfo);
console.log(addedVehicle);
res.json({data: "Succesfully added vehicle"});
}
catch(err){
if(err){
res.json(err);
}
}
};
getVehicles.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const Vehicle = require("../../models/Vehicle");
exports.getVehicles = async (req, res, db) => {
try{
const vehiclesSnapshot = await db.collection("vehicles").get();
const vehicles = [];
vehiclesSnapshot.forEach(doc => {
vehicles.push(doc.data());
});
res.json({ data: vehicles });
}
catch(err){
if(err){
res.json(err);
}
}
};

Getting Error to firebase functions - "TypeError: Cannot read property 'from' of undefined..."

I am developing android apps and using firebase functions for sending Notifications through firebase cloud messaging. I have not much knowledge on firebase functions. I tried some tutorials.
I am getting an error to firebase functions logs as below:
image link...error image
TypeError: Cannot read property 'from' of undefined
at admin.firestore.collection.doc.collection.doc.get.then.queryResult (/user_code/index.js:14:42)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
If you know solutions please edit my code and paste as an answer. Thanks in Advance.
My index code as below
'use-strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.firestore.document("Users/{user_id}/Notifications/{notification_id}").onWrite((change,context)=> {
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log("USER ID : "+user_id+" NOTIFICATION ID "+notification_id);
return admin.firestore().collection("Users").doc(user_id).collection("Notifications").doc(notification_id).get().then(queryResult =>{
const from_user_id = queryResult.data().from;
const type = queryResult.data().type;
console.log("FROM_USER ID : "+from_user_id+" TYPE "+type);
const from_data = admin.firestore().collection("Users").doc(from_user_id).get();
const to_data = admin.firestore().collection("Users").doc(user_id).get();
return Promise.all([from_data, to_data]).then(result => {
const from_name = result[0].data().name;
const to_name = result[1].data().name;
const token_id = result[1].data().token_id;
const payload = {
notification: {
tag : from_user_id+"Follow",
title : "Request From : "+from_name,
icon : "follow_icon_for_notification",
color : "white",
sound : "TYPE_NOTIFICATION",
body : "Click here to accept Follow Request.",
click_action:"jony.Activities.ONFOLLOWREQUESTRECEIVED"
},
data : {
message : "Click here to accept Follow Request.",
user_id : from_user_id
}
};
return admin.messaging().sendToDevice(token_id, payload).then(result => {
var db = admin.firestore();
const FieldValue = require('firebase-admin').firestore.FieldValue;
var notificationRef = db.collection("Users").doc(user_id).collection("Notifications").doc(notification_id).delete();
return console.log("Follow notification sent");
});
});
});
});
Would you use change.after.data()?
See https://firebase.google.com/docs/functions/firestore-events .
"use-strict";
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.sendNotification = functions.firestore
.document("Users/{user_id}/Notifications/{notification_id}")
.onWrite((change, context) => {
const user_id = context.params.user_id;
const notification_id = context.params.notification_id;
console.log("USER ID : " + user_id + " NOTIFICATION ID " + notification_id);
console.log("change.after.exists:" + change.after.exists);
console.log("change.after.data():" + change.after.data());
const data = change.after.data();
const from_user_id = data.from;
const type = data.type;
console.log("FROM_USER ID : " + from_user_id + " TYPE " + type);
const from_data = admin
.firestore()
.collection("Users")
.doc(from_user_id)
.get();
const to_data = admin
.firestore()
.collection("Users")
.doc(user_id)
.get();
return Promise.all([from_data, to_data]).then(result => {
const from_name = result[0].data().name;
const to_name = result[1].data().name;
const token_id = result[1].data().token_id;
const payload = {
notification: {
tag: from_user_id + "Follow",
title: "Request From : " + from_name,
icon: "follow_icon_for_notification",
color: "white",
sound: "TYPE_NOTIFICATION",
body: "Click here to accept Follow Request.",
click_action: "jony.Activities.ONFOLLOWREQUESTRECEIVED"
},
data: {
message: "Click here to accept Follow Request.",
user_id: from_user_id
}
};
return admin
.messaging()
.sendToDevice(token_id, payload)
.then(result => {
var db = admin.firestore();
const FieldValue = require("firebase-admin").firestore.FieldValue;
var notificationRef = db
.collection("Users")
.doc(user_id)
.collection("Notifications")
.doc(notification_id)
.delete();
return console.log("Follow notification sent");
});
});
});

Unable to Access Firestore Document Within a Firestore Cloud Function

Issue: Type Error
I setup a Firestore Cloud Function to call from my Android app which is being called as expected, however I am unable to access a Firestore document from within the method and receiving a TypeError in the logs.
Attempted Solutions
functions.firestore().document('qa/content/feeds/main/content/'+contentTitle)
functions.firestore().ref('qa/content/feeds/main/content/'+contentTitle)
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
const MAIN_FEED_TYPE = "MAIN";
const SAVED_FEED_TYPE = "SAVED";
const ARCHIVED_FEED_TYPE = "ARCHIVED";
const SAVE_USER_ACTION = "SAVE";
const ARCHIVE_USER_ACTION = "ARCHIVE";
const SAVED_PATH = "saved"
const ARCHIVED_PATH = "archived"
exports.updateQualityScore = functions.https.onCall((data, context) => {
const environment = data.environment
const feedType = data.feedType
const action = data.action
const contentTitle = data.contentTitle
const uid = context.auth.uid;
var feedTypePath
if (feedType === SAVED_FEED_TYPE) {
feedTypePath = SAVED_PATH
} else if (feedType === ARCHIVED_FEED_TYPE) {
feedTypePath = ARCHIVED_PATH
}
admin.firestore().ref('qa/content/feeds/main/content/'+contentTitle)
.get().then(function(doc) {
console.log('Trigger fired on content: '
+ contentTitle + " | user: " + uid
+ " | action: " + action + ' | feedType: ' + feedType);
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
console.log("No such document!");
}
return {
status: 'Get content success.'
}
}).catch(function(error) {
console.log("Error getting document:", error);
return {
status: 'Get content error.'
}
});
});
Firestore doesn't have a ref() method. Realtime Database does. You're probably confusing the two.
With Firestore, you deal with collections and documents, and there are different methods to get a hold of collection and document references. Maybe you meant to use the doc() method instead, like this?
admin.firestore().doc('qa/content/feeds/main/content/'+contentTitle)
Sorry wrong answer.
You need to pass credential when initializing app.
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
var db = admin.firestore();
or
admin.initializeApp({
credential: admin.credential.cert({
projectId: '<PROJECT_ID>',
clientEmail: 'foo#<PROJECT_ID>.iam.gserviceaccount.com',
privateKey: '-----BEGIN PRIVATE KEY-----\n<KEY>\n-----END PRIVATE KEY-----\n'
}),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});
initialize the sdk
Quick Start

I am receiving this error while getting notifications from firebase

'use strict'
const functions = require('firebase-functions');
const admin=require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification=functions.database.ref('/notifications/{user_id}/{notification_id }').onWrite((change,context) =>{
const user_id=context.params.user_id;
const notification_id=context.params.notification_id;
console.log('The user ID is :',user_id);
if(!change.after.val()){
return console.log('A notification has been deleted from database:',notification_id);
}
const fromUser=admin.database().ref(`/notifications/${user_id}/${notification_id}`).once('value');
return fromUser.then(fromUserResult=>{
const from_user_id=fromUserResult.val().from;
console.log('You have new notification from: : ', from_user_id);
const userQuery=admin.database().ref(`users/${from_user_id}/name`).once('value');
return userQuery.then(userResult=>{
const userName=userResult.val();
const deviceToken=admin.database().ref(`/users/${user_id}/device_token`).once('value');
return deviceToken.then(result =>{
const token_id=result.val();
const payload={
notification:{
title:"Friend Request",
body:`${userName} has sent you request`,
icon:"default"
}
};
return admin.messaging().sendToDevice(token_id, payload);
});
});
});
});
TypeError: Cannot read property 'from' of null
at fromUser.then.fromUserResult (/user_code/index.js:22:47)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
The only line of code where you're accessing a property called from is here:
const from_user_id=fromUserResult.val().from;
Therefore, fromUserResult.val() must be returning null.
fromUserResult is a DataSnapshot type object. According to the API documentation for the val() method, it can return null if there is no data at the location of the query. So, you will have to check for that case in your code.
I have achieved sending a notification with sender's name using this code:
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Notifications/{receiver_user_id}/{notification_id}')
.onWrite((data, context) =>
{
const receiver_user_id = context.params.receiver_user_id;
const notification_id = context.params.notification_id;
if(!data.after.val())
{
console.log('A notification has been deleted :' , notification_id);
return null;
}
const sender_user_id = admin.database().ref(`/Notifications/${receiver_user_id}/${notification_id}`).once('value');
return sender_user_id.then(fromUserResult =>
{
const from_sender_user_id = fromUserResult.val().from;
const userQuery = admin.database().ref(`/Users/${from_sender_user_id}/name`).once('value');
return userQuery.then(userResult =>
{
const senderUserName = userResult.val();
console.log('You have notification from :' , senderUserName);
const DeviceToken = admin.database().ref(`/Users/${receiver_user_id}/device_token`).once('value');
console.log('Checkpoint2');
return DeviceToken.then(result =>
{
const token_id = result.val();
const payload =
{
notification:
{
//from_sender_user_id : from_sender_user_id,
title: "New Chat Request",
body: `${senderUserName} wants to connect with you`,
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response =>
{
console.log('This was the notification Feature');
return null;
}).catch(error => {
console.error(error);
res.error(500);
});
});
});
});
});

Resources