Firestore and Firebase Cloud Functions - firebase

I have a simple https firebase cloud function which get all user doc from firestore but it actually give me error of
Received RST_STREAM with code 2 triggered by internal client error: Protocol error
This is my index file is
I have initailized the app
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
import {helloWorld} from "./apis/recJobs";
// eslint-disable-next-line #typescript-eslint/no-var-requires
const serviceAccount = require("../serviceAccount.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "*************",
});
// APIs
export const hello = functions.region(
"asia-south1"
).https.onRequest(helloWorld);
This is my HelloWorld Function which is straight forward to get all docs from firestore
import * as admin from "firebase-admin";
export const helloWorld = (req :any, res:any) => {
try {
// get all users doc
const db = admin.firestore();
// get all docs from user
const snapshot = db.collection("user").get();
snapshot.then((data) => {
console.log("data is :", data);
res.status(200).send({
ok: "Success",
});
}
).catch((error) => {
console.log("error is :", error);
res.status(400).send({
ok: error,
});
}
);
} catch (error) {
console.log("error is :", error);
res.status(400).send({
ok: "Final error",
});
}
};
It should return all the user docs

Related

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,
},
}; `

Reference error firestore is not defined in firebase cloud function when using firebase admin sdk

I have a cloud function in which I am listening to the onCreate event of a firestore collection. When the cloud function is triggered I am getting a reference error. Below are the cloud function code and the error.
const functions = require('firebase-functions')
const serviceAccount = require('./serviceAccountKey.json')
const admin = require('firebase-admin')
const { firestore } = require('firebase-admin')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://my-app-id.firebaseio.com', // Here I have replaced my real id for privacy
})
const db = admin.firestore()
exports.handleDiscussionReplyAdded = functions.firestore
.document('/discussions/{discussionId}/replies/{replyId}')
.onCreate(async (snap, context) => {
try {
// 1. Creating a ref to parent chat doc
const discussionRef = db
.collection('discussions')
.doc(context.params.discussionId)
// 2. Updating the data
await discussionRef.update({
totalReplies: firestore.FieldValue.increment(1),
})
// Return true if everything went fine
return true
} catch (error) {
// Return error if something went wrong
functions.logger.error(`Error: ${JSON.stringify(error)}`)
return error
}
})
{
"severity": "ERROR",
"message": "ReferenceError: firestore is not defined\n at /Users/syedalirazabokhari/Desktop/Development/React/omanshopping/functions/index.js:23:23\n at cloudFunction (/Users/syedalirazabokhari/Desktop/Development/React/omanshopping/functions/node_modules/firebase-functions/lib/cloud-functions.js:134:23)\n at /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:590:16\n at runFunction (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:577:15)\n at runBackground (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:589:11)\n at processBackground (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:572:11)\n at invokeTrigger (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:647:19)\n at handleMessage (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:734:15)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)"
}
I tried to debug the issue but unable to resolve. I have also updated the firebase-admin to the latest version 9.5.0 as of now.
Removing the unnecessary import const { firestore } = require('firebase-admin') and then changing firestore.FieldValue.increment(1) to admin.firestore.FieldValue.increment(1) fixed the error.

Send notification to all user who have a specific location using Firebase Cloud Functions

I have a trigger that fires when an item is creating. Therefore, i want to see that when the item is created, all users who have a location that was saved in the item will receive a notification
import functions = require('firebase-functions');
import admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.firestore
.document('itens/{itenId}').onCreate((snap, context) => {
//You get the values of the newly created doc as follows:
const data = snap.data();
const name = data.name;
const location = data.location;
const payload = {
notification: {
title: "Avana - Está bater",
body: `Podes encontrar : ${name} em ${location}`, //Here we use value
sound: "default"
}
};
const options = {
priority: "high",
};
admin.messaging().sendToTopic("newItem", payload, options)
.then(function (response) {
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
console.log("Notification sent!");
return null;
});
your solution is Firebase Geofire:
https://firebase.googleblog.com/2013/09/geofire-location-queries-for-fun-and.html
https://medium.com/google-cloud/firebase-is-cool-geofire-is-just-awesome-b7f2be5e0f0f#.x78gjws28

I can't replace the sk_test key with the sk_live key on Stripe using Firebase cloud functions

I have a React Native application, running on a firebase backend. I have integrated with Stripe. The token is created by the client, and the firebase cloud function creates the charge with that token. I have built the app and tested payments using the test keys in Stripe.
I have now replaced the test keys with the live keys.
The live public key is working in the React Native application, and is creating a token successfully.
here is the function for creating the token code in the React Native application
import Stripe from 'react-native-stripe-api';
async payByCard() {
const { user } = this.props;
const uid = user.uid;
const { number, exp_month, exp_year, cvc } = this.state;
this.setState({ loading: true });
const apiKey = 'pk_live_#######################';
const client = new Stripe(apiKey);
try {
const token = await client.createToken({
number,
exp_month,
exp_year,
cvc,
});
this.props.addToken({ token }, uid);
} catch (error) {
this.setState({ error: error.message, loading: false });
}
}
The firebase cloud functions, however, is still using the secret test key.
here is the loud function for creating a charge.
import * as functions from 'firebase-functions';
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const stripe = require('stripe')(functions.config().stripe.testkey)
export const stripeCharge = functions.database
.ref('/payments/{userUid}/{paymentUid}')
.onWrite((change, context) => {
const payment = change.after.val();
const userUid = context.params.userUid;
const paymentUid = context.params.paymentUid;
if (!payment || payment.charge || !payment.pendingBasket) return;
return admin.database()
.ref(`/users/${userUid}`)
.once('value')
.then(snapshot => {
return snapshot.val();
})
.then(customer => {
const amount = Number(payment.pendingBasket.total * 100).toFixed(0)
const idempotency_key = paymentUid;
const source = payment.token.id;
const currency = 'gbp';
const description = `Athalens ${customer.address.FirstName} ${customer.address.LastName} - ${customer.address.PostCode}`
const charge = {amount, currency, description, source};
return stripe.charges.create(charge, { idempotency_key });
}).catch((error) => {
console.log('error 1 =' + error.message);
admin.database()
.ref(`/payments/${userUid}/${paymentUid}/status`)
.set(error.message)
})
.then(charge => {
admin.database()
.ref(`/payments/${userUid}/${paymentUid}/charge`)
.set(charge)
if (charge.status === "succeeded") {
customerOrders(userUid, paymentUid)
photographerUid(userUid, paymentUid)
clearBasket(userUid)
confirmation(userUid, paymentUid);
} else {
decline(userUid, paymentUid)
}
}).catch((error) => {
console.log('error 2 =' + error.message);
})
})
The process I am doing to upload the Secret key to firebase:
1. Williams-MBP:~ williamgoodhew$ cd /Users/williamgoodhew/projects/athalens/athalens_server_code/basket/functions
2. Williams-MBP:functions williamgoodhew$ firebase functions:config:set stripe.token=“sk_live_#################”
3. Williams-MBP:functions williamgoodhew$ firebase deploy --only functions
When I test the live payment system, a token is created, but no charge is created. and I receive the following error in the cloud functions log:
No such token: tok_############; a similar object exists in live mode, but a test mode key was used to make this request.
I have got in contact with Firebase and it was a silly error my end.
In my cloud function, I had initialized my test key "
const stripe = require('stripe')(functions.config().stripe.testkey)
" instead of using "stripe.token".
I changed stripe.testkey to stripe.token.and everything worked out fine.

Firestore Event Trigger Fire Occurred Error Unhandled Rejection

I'm changing real time database to Firestore.
Using cloud function trigger onUpdate() always failed with error message.
here's my cloud function index.js
const admin = require("firebase-admin");
const functions = require("firebase-functions");
const serviceAccount = require("./service_account.json");
const friendProcess = require("./friend_process");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://projec-name.firebaseio.com"
});
exports.friendProcess = functions.firestore.document("users/{userId}/friends/{requestId}").onUpdate(friendProcess);
and this code is friend_process.js
const admin = require("firebase-admin");
module.exports = function(event) {
const userId = event.params.userId;
const updatedData = event.data.data();
const requestId = updatedData.fromUid;
const previousData = event.data.previous.data();
console.log("update data", updatedData);
console.log("requestId", requestId);
console.log("userId", userId);
if (previousData.status === "request" && updatedData.status === false) {
console.log("updatedData.action ", updatedData);
console.log("ref", event.data.ref);
return admin
.firestore()
.collection("users")
.doc(requestId)
.collection("friends")
.doc(userId)
.get()
.then(doc => {
return console.log("doc ", doc);
})
.catch(error => {
return console.log("error ", error);
});
}
return;
};
here's my console log
firebase console log link
Error: Unexpected error while acquiring application default credentials: Could not load the default credentials. Browse to https://developers.google.com/accounts/docs/application-default-credentials for more information.
at GoogleAuth. (/user_code/node_modules/firebase-admin/node_modules/google-auth-library/build/src/auth/googleauth.js:229:31)
at step (/user_code/node_modules/firebase-admin/node_modules/google-auth-library/build/src/auth/googleauth.js:47:23)
at Object.next (/user_code/node_modules/firebase-admin/node_modules/google-auth-library/build/src/auth/googleauth.js:28:53)
at fulfilled (/user_code/node_modules/firebase-admin/node_modules/google-auth-library/build/src/auth/googleauth.js:19:58)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
my package.json
"firebase-admin": "^5.11.0",
"firebase-functions": "^0.9.1",

Resources