I'm making an iOS app like Airbnb using Stripe and Firebase as backend. I'm following the this document. https://medium.com/firebase-developers/go-serverless-manage-payments-in-your-apps-with-cloud-functions-for-firebase-3528cfad770.
As the document says, here's the workflow I made so far.(let's say a user wants to purchase something)
1. A user sends payment information to Firebase realtime database such as amount currency and card token)
2. Firebase triggers a function which sends charge request(stripe.charge.create) to Stripe.
3. After getting response, write it back to Firebase database. if the response failed, write the error message to database (see userFacingMessage functions in index.js)
4. In client side(Swift), observe the Firebase database to check the response.
5. If the response is successful, display successful message to the user. If there're are any errors such as ( payment failed because a credit card expires), display failed message to the user( also display 'please try again" message)
I guess this is not right approach because I think the user should know response (if succeeded or failed) as soon as firebase gets the response from Stripe. In another word, the client side(Swift) should get the response right after getting response before writing back to the Firebase database? Does anyone know how to send response to the client side?
Any help would be appreciated
ChargeViewController.swift (client-side)
func didTapPurchase(for amountCharge: String, for cardId: String) {
print("coming from purchas button", amountCharge, cardId)
guard let uid = Auth.auth().currentUser?.uid else {return}
guard let cardId = defaultCardId else {return}
let amount = amountCharge
let currency = "usd"
let value = ["source": cardId, "amount": amount, "currency": currency] as [String: Any]
let ref = Database.database().reference().child("users").child(uid).child("charges")
ref.childByAutoId().updateChildValues(value) { (err, ref) in
if let err = err {
print("failed to inserted charge into db", err)
}
print("successfully inserted charge into db")
//Here, I want to get the response and display messages to user whether the response was successful or not.
}
}
index.js(Cloud Functions) Language: node.js
exports.createStripeCharge = functions.database
.ref(‘users/{userId}/charges/{id}’)
.onCreate(async (snap, context) => {
const val = snap.data();
try {
// Look up the Stripe customer id written in createStripeCustomer
const snapshot = await admin.database()
.ref(`users/stripe/${context.params.userId}/stripe_customer_id`)
.once('value');
const snapval = snapshot.data();
const customer = snapval.stripe_customer_id;
// Create a charge using the pushId as the idempotency key
// protecting against double charges
const amount = val.amount;
const idempotencyKey = context.params.id;
const charge = {amount, currency, customer};
if (val.source !== null) {
charge.source = val.source;
}
const response = await stripe.charges
.create(charge, {idempotency_key: idempotencyKey});
// If the result is successful, write it back to the database
//*I want to send this response to the client side but not sure how if I can do it nor not*
return snap.ref.set(response);
} catch(error) {
await snap.ref.set(error: userFacingMessage(error));
}
});
// Sanitize the error message for the user
function userFacingMessage(error) {
return error.type ? error.message : 'An error occurred, developers have been alerted';
}