Upon clicking the 'checkout' button in my VueJS ecommerce app, a new 'order' field containing order params will be created in my firebase 'orders' child node. I've created a Realtime Database onCreate 'newBuyerOrder' function to send the user an email notifying him of this new order once a new 'order' field is created. Now I'd also like to call a REST API '/checkout' that I've built with the HTTPs onRequest function to process the order via Paypal REST SDK. How can I do that?
A workaround that I've tried is to build HTTPs onCall functions that the client browser can call to process the order via Paypal with order params and send the email separately with the 'newBuyerOrder' onCreate function. But unfortunately, HTTPs onCall does not allow client redirect. And, lo and behold, client redirect is required while making Paypal REST calls so HTTPs onCall does not work for my purpose.
in functions/package.json
"dependencies": {
"@sendgrid/mail": "^6.3.1",
"firebase-admin": "~6.0.0",
"firebase-functions": "^2.1.0",
"paypal-rest-sdk": "^1.8.1"
}
in functions/src/index.ts
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import * as sendgrid from '@sendgrid/mail'
import * as paypal from 'paypal-rest-sdk'
// init firebase admin
admin.initializeApp()
// set sendgrid api in function config
const SENDGRID_API_KEY = ...
// set paypal api in function config
paypal.configure({
...
});
// setup paypal payment object and redirect user to paypal payment
page
export const checkout = functions.https.onRequest((req, res) => {
// 1.Set up a payment information object, Build PayPal payment
request
const payReq = JSON.stringify({
...
})
// 2.Initialize the payment and redirect the user.
paypal.payment.create(payReq, (error, payment) => {
if (error) {
// handle error
} else {
// redirect to paypal approval link
for (let i = 0; i < payment.links.length; i++) {
if (payment.links[i].rel === 'approval_url') {
res.redirect(302, payment.links[i].href)
}
}
}
})
})
// send email and trigger paypal checkout api given new buyer order
export const newBuyerOrder = functions.database
.ref('users/{userId}/orders/{orderId}')
.onCreate((snapshot, context) =>
// expected solution to call 'checkout' REST API from above
// send email via sendgrid
const msg = {...}
return sendgrid.send(msg)
})
I expect the '/checkout' API to be called once a new order field is created in the Realtime Database and that the client gets redirected to the Paypal approval page.
Calling one Cloud Function from another Cloud Functions is almost never a good idea. For one thing, you'll be paying for two invocations, where the work could be done in just one. There are better ways to re-use the code.
For example, you could include the code for the payment in the Realtime Database triggered Cloud Function?.
Or you could extract the business functionality of that Cloud Function, and put that in a regular JavaScript function, so that you an call if from the Realtime Database triggered function.
A database trigger comes from the Realtime Database to Cloud Functions. No client-side application code is involved, so it also can't be redirected.
If you want to send a response back to the client when the operation has completed, you typically write the response for the client back into the database in a place that the client watches. For example, you could write the response to: /users/{userId}/order_results/{orderId}
and the client can then wait for a value at this location.
来源:https://stackoverflow.com/questions/54451738/firebase-how-to-trigger-https-onrequest-function-within-a-realtime-database-onc