How to post trigger firebase cloud functions with express.js - firebase

What i am trying to do is send data(inputs) from client to firebase cloud function with post trigger using express.js and use that data to create a new user.
this is the cloud function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')({origin: true});
admin.initializeApp(functions.config().firebase);
exports.registeration = functions.https.onRequest((req, res) => {
res.status(400).send({
message: 'error',
message2:req,
message3:req.body
});
res.send({
message: 'success'
});
});
So how do i write client part with express.js

Maybe something like this :
const express = require('express');
// Create the server
const app = express();
app.use((err, req, res, _next) => {
console.log('Error handler', err);
if(err){
res.status(400).send({
message:'error',
message2:req,
message3:req.body
});
} else {
res.send({
message: 'success'
});
}
});
exports.registeration = functions.https.onRequest(app);

Related

Why am I keep getting INTERNAL ERROR 500 with my firebase cloud function?

I was trying to deploy a cloud function on firebase but I keep getting this error. I deleted all of my logic to console the response and debug but nothing's changed.
I am sure that the problem is not related to permissions because the invocation is allowed for unauthenticated users.
this is the block of my function:
// Firebase config
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require("cors")({
origin: true
});
admin.initializeApp();
exports.emailMessage = functions.https.onCall((req, res) => {
return cors(req, res, async() => {
console.log(req);
console.log(res);
}).catch(() => {
res.status(500).send("error");
});
});

Unable to send data from Stripe Webhook to Firebase Firestore

I have made a Stripe webhook and I want to write data to Firebase when a Stripe purchase happens, and it isn't working although the payment always succeeds but the data is not sent to Firebase database.
In the following I will provide my code:
` import {
buffer
} from "micro";
import * as admin from "firebase-admin";
// <--SECURE A CONNECTION TO FIREBASE FROM THE BACKEND -->
const serviceAccount = require("../../../permissions.json");
const app = !admin.apps.length ?
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
}) :
admin.app();
// Establish connection to stripe. Stripe initialization
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
const endpointSecret = process.env.STRIPE_SIGNING_SECRET;
const fulfillOrder = async(session) => {
console.log("FULFILL ORDER", session);
return app
.firestore()
.collection("user")
.doc(session.metadata.email)
.collection("orders")
.doc(session.id)
.set({
amount: session.amount_total / 100,
amount_shipping: session.total_details.amount_shipping / 100,
images: JSON.parse(session.metadata.images),
timestamp: admin.firestore().FieldValue.serverTimestamp(),
})
.then(() => {
console.log(`SUCCESS: Order ${session.id} had been added to the DB `);
})
};
export default async(req, res) =>
// In next js if we want to check if we have a get request or post request, etc, we do in the following way
if (req.method === "POST") {
const requestBuffer = await buffer(req);
const payload = requestBuffer.toString();
const sig = req.headers["stripe-signature"];
let event;
// Verify that the EVENT POSTED came from Stripe
try {
event = stripe.webhooks.constructEvent(payload, sig, endpointSecret);
} catch (err) {
console.log("Error", err.message);
return res.status(400).send(`Webhook error: ${err.message}`);
}
if (event.type === "checkout.session.completed") {
const session = event.data.object;
return fulfillOrder(session)
.then(() => res.status(200))
.catch((err) => res.status(400).send(`Webhook Error: ${err.message}`));
}
}
};
// in order to implement webhook with NEXTJS we need to DISABLE few features in the config
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
}; `

Unable to deploy functions in firebase

I am trying to integrate Razorpay in my nuxt app.
For that, I installed razorpay dependency using npm i razorpay
My index.js files starts with
const functions = require('firebase-functions')
const Razorpay = require('razorpay')
const admin = require('firebase-admin')
const crypto = require('crypto')
But after writing the function(basic helloWorld function) and deploying it gave me an error unable to deploy function.
But when I commented below line the helloWorld function deployed successfully.
//const Razorpay = require('razorpay')
Again I uncommented above line and it still gives me error unable to deploy.
Version info
Node v12.18.3
Firebase v8.16.2
My Dependencies
"dependencies": {
"#nuxtjs/axios": "^5.12.2",
"#nuxtjs/pwa": "^3.0.2",
"cookieparser": "^0.1.0",
"core-js": "^3.6.5",
"firebase": "^8.2.0",
"js-cookie": "^2.2.1",
"jwt-decode": "^3.1.2",
"nuxt": "^2.14.6",
"nuxt-buefy": "^0.4.3",
"razorpay": "^2.0.6",
"uuid": "^8.3.2",
"vuexfire": "^3.2.5"
},
Please note that you will need to put the following in the Firebase Cloud Function to integrate the Razorpray:
const Razorpay = require("razorpay");
var key_id = "YOUR_RAZORPAY_KEY_ID";
var key_secret = "YOUR_RAZORPAY_KEY_SECRET";
var instance = new Razorpay({
key_id: key_id,
key_secret: key_secret
});
You need to follow the next steps to integrate it:
Signup for razorpay and grab your Key_Id and Key_Secret from Razorpray
Integrate the checkout modal from razorpay in the front end to accept the payment details from user.
Implement Order API in the backend.
Capture Authorized payments.
Please have a look into the following Medium tutorial for better understanding and this GitHub Repository for a code example.
********** UPDATE **********
Regarding Cors error, please make sure the following:
Import Cors
const cors = require('cors')({origin: true});
Call the cors module at the top of each function as following:
exports.createPayment = functions.https.onRequest(async (req, res) => {
cors(req, res, () => {
// your function body here - use the provided req and res from cors
})
});
const functions = require('firebase-functions')
const Razorpay = require('razorpay')
const admin = require('firebase-admin')
const crypto = require('crypto')
const cors = require('cors')({ origin: true })
admin.initializeApp()
//Function to Create Payment
exports.createPayment = functions.https.onRequest(async (req, res) => {
cors(req, res, () => {
admin
.firestore()
.collection('payments')
.add(req.body.data)
.then((payment) => {
var instance = new Razorpay({
key_id: 'rzp_test_my_key',
key_secret: 'my_secret_key',
})
var options = {
amount: req.body.data.amount * 100,
currency: 'INR',
receipt: payment.id,
payment_capture: 1,
}
instance.orders.create(options, function (err, order) {
res.status(201).send({ data: order })
})
})
})
})
// Function to Verify Payment
exports.verifyPayment = functions.https.onRequest(async (req, res) => {
cors(req, res, () => {
const order = req.body.data
const text = order.razorpay_order_id + '|' + order.razorpay_payment_id
var signature = crypto
.createHmac('sha256', secret_key)
.update(text)
.digest('hex')
if (signature === order.razorpay_signature) {
res.status(201).send({ data: { message: 'Successfull Payment' } })
} else {
res.status(400).send({ data: { message: 'Signature mismatch' } })
}
})
})

Firebase Cloud Functions: Cannot pass the token retrieved from Realtime Database

I'm having issues in retrieving a token saved in realtime database using cloud function's admin.database(). There is only one token to read from the child.
Firebase Database structure
Here's my code in Index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.database
.ref('/Logs/{LogsID}')
.onWrite( (change, context) => {
const notificationSnapshot = change.after.val();
const status = notificationSnapshot.Status;
const time = notificationSnapshot.Time;
const payload = {
notification: {
title : status,
body : time
}
}
console.info(notificationSnapshot);
const pushToken = admin.database().ref('/Tokens').once('child_added').then( (data) => {
const tokenSnapshot = data.val();
const finaltoken = tokenSnapshot.token;
console.info(finaltoken);
})
// Need help down here.
admin.messaging().sendToDevice(finaltoken, payload)
.then( () => {
console.log('Notification sent');
})
.catch( () =>{
console.log('Notification failed');
})
return null;
});
finalToken shows the correct token in log as expected. Log Showing the token
But I'm getting error while I'm passing the same token to admin.messaging(). Console is logging 'Notification sent' but not receiving a notification.
ReferenceError: finaltoken is not defined
at exports.sendNotification.functions.database.ref.onWrite (/user_code/index.js:43:36)
at cloudFunctionNewSignature (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:105:23)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:135:20)
at /var/tmp/worker/worker.js:827:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
It works when I directly pass the token like,
var finalToken = 'ephrj1........kndji'
so the admin.messaging() works, only passing the token is not working.
I'm new to Cloud Functions and javascript, so any help is much appreciated.
Final token is being retrieved in callback / async function.
That means that when you add it to .sendToDevice() the token is undefined because the async function has not retrieved the token from the database... yet.
const pushToken = admin.database().ref('/Tokens').once('child_added').then( (data) => {
const tokenSnapshot = data.val();
const finaltoken = tokenSnapshot.token;
console.info(finaltoken);
admin.messaging().sendToDevice(finaltoken, payload)
.then( () => {
console.log('Notification sent');
})
.catch( () =>{
console.log('Notification failed');
})
// I moved admin.messaging above this bracket
})
// It used to be here
return null;
Try putting the admin.messaging code within the code block of (data) => {}
By doing this we ensure that whenever we call sendToDevice() the token is defined.

Trying to connect to firebase function from React app - cors issue?

I'm creating a react application. I have code like this
async componentDidMount() {
const questions = await axios.get('getQuestions');
console.log(questions);
}
(I have a baseURL set up for axios and all, so the URL is correct)
I created a firebase function as follows (typescript)
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
admin.firestore().settings({ timestampsInSnapshots: true });
const db = admin.firestore();
exports.getQuestions = functions.https.onRequest(async (request, response) => {
const questions = [];
const querySnapshot = await db.collection('questions').get();
const documents = querySnapshot.docs;
documents.forEach(doc => {
questions.push(doc.data());
});
response.json({ questions: questions });
});
Now when I build and run firebase deploy --only functions, and then visit the url directly, everything works. I see my questions.
But in the react app, I get the following error
Access to XMLHttpRequest at '.../getQuestions' from origin
'http://localhost:3000' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
After some googling, I tried
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
admin.firestore().settings({ timestampsInSnapshots: true });
const db = admin.firestore();
const cors = require('cors')({ origin: true });
exports.getQuestions = functions.https.onRequest(
cors(async (request, response) => {
const questions = [];
const querySnapshot = await db.collection('questions').get();
const documents = querySnapshot.docs;
documents.forEach(doc => {
questions.push(doc.data());
});
response.json({ questions: questions });
})
);
But that just gave me an error when I ran firebase deploy --only functions
✔ functions: Finished running predeploy script. i functions:
ensuring necessary APIs are enabled... ✔ functions: all necessary
APIs are enabled i functions: preparing functions directory for
uploading...
Error: Error occurred while parsing your function triggers.
TypeError: Cannot read property 'origin' of undefined
at ...
And tbh, even if this command worked, I don't know if it is the correct solution
Got it :) I was doing something silly
import * as cors from 'cors';
const corsHandler = cors({ origin: true });
exports.getQuestions = functions.https.onRequest(async (request, response) => {
corsHandler(request, response, async () => {
const questions = [];
const querySnapshot = await db.collection('questions').get();
const documents = querySnapshot.docs;
documents.forEach(doc => {
questions.push(doc.data());
});
response.status(200).json({ questions: questions });
});
});
This answer will help someone who facing cors error.
01 - Create Firebase Function Called BtnTrigger (You can name whatever you like)
// Include Firebase Function
const functions = require('firebase-functions');
// Include Firebase Admin SDK
const admin = require('firebase-admin');
admin.initializeApp();
//cors setup include it before you do this
//run npm install cors if its not in package.json file
const cors = require('cors');
//set origin true
const corsHandler = cors({ origin: true });
//firebase function
export const BtnTrigger = functions.https.onRequest((request, response) => {
corsHandler(request, response, async () => {
//response.send("test");
response.status(200).json({ data: request.body });
});
});
Then Run firebase deploy --only functions this will create your firebase function. if you need you can check it from your Firebase Console.
02 - Create Function Trigger from your Application from your application code
i used same BtnTrigger name to understand it properly you can change variable here but httpsCallable params should same as your Firebase Function Name you created.
var BtnTrigger =firebase.functions().httpsCallable('BtnTrigger');
BtnTrigger({ key: value }).then(function(result) {
// Read result of the Cloud Function.
console.log(result.data)
// this will log what you have sent from Application BtnTrigger
// { key: value}
});
Don't Forget to import 'firebase/functions' from your Application Code

Resources