Reputation: 672
I'm making a react-redux app with firetore as database. Now, I wanted to use firebase cloud functions for handling stripe payments.
Here is the setup:
Below is the action method for checkout, after receiving token and amount from react side.
export const checkoutFunc = (token, amount) => {
return (dispatch, getState, { getFirebase, getFirestore }) => {
const uid = getState().firebase.auth.uid;
const ref = database.ref();
ref.child(`payments/${uid}`).push({
token: token,
amount: amount
});
};
};
This function creates a payment and saves token and amount.
Now, here is the cloud function which should "charge" the payment, after the above payment is created.
exports.stripeCharge = functions.database
.ref("/payments/{userId}/{paymentId}")
.onWrite((change, context) => {
const payment = change.after.val();
const userId = context.params.userId;
const paymentId = context.params.paymentId;
if (!payment || payment.charge) return;
return admin
.database()
.ref(`/teachers/${userId}`)
.once("value")
.then(snap => {
return snap.val();
})
.then(customer => {
const amount = payment.amount;
const idempotency_key = paymentId;
const source = payment.token.id;
const currency = "usd";
const charge = { amount, currency, source };
return stripe.charges.create(charge, { idempotency_key });
})
.then(charge => {
admin
.database()
.ref(`/payments/${userId}/${paymentId}/charge`)
.set(charge)
.then(charge => {
return true;
});
});
});
The creation of payment works and the token and amount is saved in payments table. But, the cloud function is not doing its job of charging the token.
Expected Result:
https://i.ibb.co/Fq9Zfhq/image.png
Actual result:
https://i.ibb.co/Krk7cGL/image.png
Upvotes: 1
Views: 377
Reputation: 672
Though the answer provided by @Doug Stevenson is helpful, it was not the main problem. So, I am writing the solution here for other people struggling with it. I was using the wrong public key and secret key pair in my app, that when I used correctly, it worked.
Upvotes: 1
Reputation: 317372
You're not returning the promise returned from set() using the Admin SDK. The function is terminating and cleaning up before that async work is complete.
.then(charge => {
return admin // add a return here
.database()
.ref(`/payments/${userId}/${paymentId}/charge`)
.set(charge)
.then(charge => {
return true;
});
});
FYI these promise chains are easier to visualize if you use async/await syntax instead of then/catch.
Upvotes: 0