Upload stripeCharge function to Firebase cloud function not working - node.js

I tried deploying this function to Firebase
Also, Im using Cloud Firestore as the database
const stripe = require("stripe")("STRIPE_API_KEY");
exports.stripeCharge = functions.firestore
.document("/payments/{userId}/{paymentId}")
.onWrite(event => {
const payment = event.data.val();
const userId = event.params.userId;
const paymentId = event.params.paymentId;
// checks if payment exists or if it has already been charged
if (!payment || payment.charge) return;
return admin
.firestore()
.doc(`/users/${userId}`)
.once("value")
.then(snapshot => {
return snapshot.val();
})
.then(customer => {
const amount = payment.amount;
const idempotency_key = paymentId; // prevent duplicate charges
const source = payment.token.id;
const currency = "eur";
const charge = { amount, currency, source };
return stripe.charges.create(charge, { idempotency_key });
})
.then(charge => {
admin
.firestore()
.doc(`/payments/${userId}/${paymentId}/charge`)
.set(charge),
{ merge: true };
});
});
I followed this tutorial
Process Stripe Payments with Firebase Cloud Functions - Part 2
YouTube · 14 000+ views · 2017/07/11 · by Fireship - AngularFirebase
When I run firebase deploy --only functions
This appears in the terminal
! functions: failed to create function stripeCharge
HTTP Error: 400, The request has errors
Functions deploy had errors with the following functions:
stripeCharge
To try redeploying those functions, run:
firebase deploy --only functions:stripeCharge
To continue deploying other features (such as database), run:
firebase deploy --except functions
Error: Functions did not deploy properly.
And I get this error in the Firebase log
Firebase Log error
Anybody have a clue with what could be wrong?

At least one of your problem is that you use the syntax of the Firebase SDK for Cloud Functions for version < 1.0.0 and your package.json shows that you use a version that is >= 2.2.0.
You should use the new syntax:
exports.stripeCharge = functions.firestore
.document("/payments/{userId}/{paymentId}")
.onWrite((change, context) => {
const payment = change.after.data();
const userId = event.params.userId;
const paymentId = event.params.paymentId;
...
});

Related

Is Firestore Local persistence available for Windows/

I am running the following code:
const { initializeApp } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
const {firestore} = require("firebase-admin");
const QuerySnapshot = firestore.QuerySnapshot;
initializeApp()
const db = getFirestore();
const initializeListener = (collectionName) => {
console.log('called function');
const query = db.collection(collectionName);
query.onSnapshot((querySnapshot) => {
querySnapshot.docs().
console.log('snapshot received');
querySnapshot.docChanges().forEach((change) => {
console.log('doc change found');
if (change.type === "added") {
console.log("New " + collectionName, change.doc.data());
}
});
}, (erry) => {
console.log(`Encountered error: ${err}`);
});
}
initializeListener('my_collection');
If running whilst offline I don't see the 'snapshot received' message until I go online. If offline persistence should be available here, how do I access it?
You are using the Firebase Admin SDK (a wrapper around the Google Cloud backend SDK), which does not have any sort of persistence on any platform. Offline persistence is only available for the web and client SDKs provided by Firebase. As you can see from the linked documentation:
Note: Offline persistence is supported only in Android, Apple, and web apps.

Why this callable cloud function is failing with "app":"MISSING"?

I am calling a cloud function which runs a transaction, however it is returning an error to console which says:
Callable request verification passed {"verifications":{"auth":"VALID","app":"MISSING"}}
Googling it led me to App Check which is a new thing in Firebase. I am using React-Native firebase npm packages and following its documentation about App Check is extremely difficult due to lack of proper explanation and examples.
Below I have the code which I am trying to execute in the function:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const firestore_ = admin.firestore();
// const { CustomProvider } = require("#react-native-firebase/app-check");
const appCheckForDefaultApp = admin.appCheck();
const GeoPoint = admin.firestore.GeoPoint;
const FieldValue = admin.firestore.FieldValue;
const _geofirestore_ = require("geofirestore");
const GeoFirestore = _geofirestore_.initializeApp(firestore_);
exports.createNew = functions.runWith({
allowInvalidAppCheckToken: true // Opt-out: Requests with invalid App
// Check tokens continue to your code.
}).region('europe-west6').https.onCall(async (data, context) => {
try {
//Checking that the user calling the Cloud Function is authenticated
if (!context.auth) {
return "The user is not authenticated: " + context.auth;
// throw new UnauthenticatedError('The user is not authenticated. Only authenticated Admin users can create new users.');
}
const longitude = data.longitude;
const latitude = data.latitude;
const thirty_mins_old = data.thirty_mins_old;
const currenttime = data.currenttime;
const GeoFirestore_ = new _geofirestore_.GeoFirestore(firestore_);
const sfDocRef = GeoFirestore_.collection('mycollection')
.limit(1)
.near({ center: new GeoPoint(latitude, longitude), radius: 0.05 });
GeoFirestore.runTransaction((transaction) => {
const geotransaction = new _geofirestore_.GeoTransaction(transaction, new GeoPoint(latitude, longitude));
return geotransaction.get(sfDocRef._collectionPath).then((sfDoc) => {
...
});
});
} catch (error) {
if (error.type === 'UnauthenticatedError') {
throw new functions.https.HttpsError('unauthenticated', error.message);
} else if (error.type === 'NotAnAdminError' || error.type === 'InvalidRoleError') {
throw new functions.https.HttpsError('failed-precondition', error.message);
} else {
throw new functions.https.HttpsError('internal', error.message);
}
}
});
EDIT:
I am debugging the app so I am not working on production. Does debugging still requires this to be configured?
The log message you are seeing is not an error - it's informational.
On each request, your callable functions will verify any auth or appcheck token included in the request. When these tokens are not present, the execution is passed to your handler - it's your responsibility to handle requests with missing tokens if necessary. It looks like you are already handling the case for missing auth token.
When executing functions in your auth emulator, auth/appcheck tokens are minimally verified - i.e. they should be valid JWT token but we don't actually verify the signature to ensure that it's signed by Firebase Auth/AppCheck backend.
If your function is erroring in your development environment, I suspect that the error is elsewhere.

cloud functions firebase v9 runTransaction

this is my cloud function:
const { getFirestore, runTransaction, FieldValue } = require('firebase-admin/firestore')
exports.purchasesStatistics = functions.firestore
.document('transactions/{purchaseId}')
.onUpdate((snap, context ) => {
if (snap.before.data().status === 'RECEIVED') {
return '0'
}
let purchasePaid = snap.after.data().status === 'RECEIVED' ? true : false
if (purchasePaid === false) {
return '0'
}
let allPurchase = snap.after.data()
functions.logger.log('allPurchase', allPurchase)
let ref = getFirestore().collection('statistics').doc('checkout')
return runTransaction(ref, (transaction) => {
return transaction.get(ref).then((doc) => {
functions.logger.log('documento atualizado:', doc.data())
return '0'
})
})
})
Buy, it's returning "runTransaction is not a function". What i'm doing wrong ? Didn't find proper way to use runTransaction on firebase v9
It appears that you are using the admin SDK for NodeJS. This SDK is initialized differently from the Web SDK V9 and the way you use the functions is also different. Here is a detailed guide on how to initialize the admin SDK from scratch. After trying to add or import the runTransaction() function as your sample code, I also received the same error message. I followed the get started guide in addition to the documentation example to properly use this function, by using it from the firestore object that is created:
const { initializeApp, applicationDefault, cert } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
const serviceAccount = require('/path-to-service-account'); //Path to your service account, depends on implementation
initializeApp({
credential: cert(serviceAccount)
});
const fireDB = getFirestore();
fireDB.runTransaction(); //Use the relevant args
This additional page contains a different example for using transactions.

Error upon Cloud Function for Firebase deployment

I've been trying to deploy a Cloud Function to my Firebase project.
It's my first time doing so, also my first time programming with JavaScript.
Here's my code in Node.JS:
'use strict'
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const firebaseTriggers = functions.region('europe-west1').firestore;
const db = admin.firestore();
exports.postNotification = firebaseTriggers
.document('/post notifications/{notificatioId}').onWrite((snap, context) => {
const notifcationRecieverId = snap.data().mReciever;
const payload = {
data: {
notification_type: 'POST',
title: snap.data().mTitle,
body: snap.data().mDescription,
sender_id: snap.data().mSender,
reciever_id: snap.data().mReciever,
notification_id: context.params.notificatioId
}
};
return db.collection('dog owners')
.document(notifcationRecieverId)
.get()
.then(recieverDoc => {
console.log('Retrieving FCM tokens');
const tokens = recieverDoc.data().mTokens;
console.log('Sending notification payload');
return admin.message().sendToDevice(tokens, payload);
});
});
Upong deployment, I'm getting the following error:
Can someone help me understand why?
Firstly you have got space in your colleciton name. This is bad convetion.
post notifications => postNotifications

Function returned undefined, expected Promise or value- NodeJS

I have an angular app that is using firestore as the DB and Google cloud functions to handle the backend. When I run my app and click on pay to make the call to the Stripe API I get the following message on the log for the cloud functions.
Function returned undefined, expected Promise or value
I have been reading several stackoverflow questions and they talk about me returning whatever in the Promise .then() but I keep getting the same error. The good thing is that the actual value gets store in Firestore with no problem, so it seems to be more like a warning rather than an error since nothing breaks.
What am I missing?
exports.stripeCharges = functions.firestore
.document("/payments/users/TAMO/{paymentId}")
.onWrite((event, context) => {
const payment = event.after.data();
const paymentId = context.params.paymentId;
if (!payment || payment.charge) return;
return admin
.firestore()
.doc(`/payments/users/TAMO/${paymentId}`)
.get()
.then(snapshot => {
return snapshot.data();
})
.then(customer => {
const amount = payment.amount * 100;
const idempotency_key = paymentId;
const source = payment.token.id;
const currency = "usd";
const description = "Test Charge";
const charges = {
amount,
currency,
description,
source
};
return stripe.charges.create(charges, { idempotency_key });
})
.then(charges => {
return admin
.firestore()
.doc(`/payments/users/TAMO/${paymentId}`)
.set(
{
charge: charges
},
{
merge: true
}
);
});
});
Looks like either you don't have payment or payment.charge.
if (!payment || payment.charge) return;
I solved this warning by doing the following:
if (!payment || payment.charge) return null;
The line above checks if payment exists or if it has already been charged

Resources