Firebase:如何在实时数据库onCreate函数中触发HTTPs onRequest函数?

时间:2019-01-31 00:40:21

标签: firebase vuejs2 google-cloud-functions paypal-rest-sdk

在我的VueJS电子商务应用程序中单击“结帐”按钮后,将在我的Firebase“订单”子节点中创建一个包含订单参数的新“订单”字段。我创建了一个实时数据库onCreate'newBuyerOrder'函数,以便在创建新的“订单”字段后向用户发送一封电子邮件,通知该新订单。现在,我还要调用一个使用HTTPs onRequest函数构建的REST API'/ checkout',以通过Paypal REST SDK处理订单。我该怎么办?

我尝试过的一种解决方法是构建HTTPs onCall函数,客户端浏览器可以调用该函数以通过Paypal使用订单参数处理订单,并使用“ newBuyerOrder” onCreate函数单独发送电子邮件。但不幸的是,HTTPs onCall不允许客户端重定向。而且,瞧,在进行Paypal REST调用时需要客户端重定向,因此HTTPs onCall不适用于我的目的。

在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"
}

在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)
})

我希望一旦在实时数据库中创建了新的订单字段,并且客户端将重定向到Paypal批准页面,就会调用'/ checkout'API。

1 个答案:

答案 0 :(得分:1)

从另一个云功能中调用一个云功能几乎绝不是一个好主意。一方面,您将需要为两次调用付费,而只需一次即可完成工作。有更好的方法来重用代码。

例如,您可以将付款代码包含在Realtime Database触发的Cloud Function中?。

或者您可以提取该Cloud Function的业务功能,并将其放入常规的JavaScript函数中,以便从Realtime Database触发的函数中进行调用。


数据库触发器来自实时数据库到云功能。不涉及任何客户端应用程序代码,因此也无法重定向。

如果要在操作完成后将响应发送回客户端,则通常会将客户端的响应写回到客户端监视的位置的数据库中。例如,您可以将响应写到:// inflate the layout of the popup window LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE); if(inflater == null) { return; } //View popupView = inflater.inflate(R.layout.my_popup_layout, null); // this version gives a warning cause it doesn't like null as argument for the viewRoot, c.f. https://stackoverflow.com/questions/24832497 and https://stackoverflow.com/questions/26404951 View popupView = View.inflate(MyParentActivity.this, R.layout.my_popup_layout, null); // create the popup window final PopupWindow popupWindow = new PopupWindow(popupView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, true // lets taps outside the popup also dismiss it ); // do something with the stuff in your popup layout, e.g.: //((TextView)popupView.findViewById(R.id.textview_popup_helloworld)) // .setText("hello stackoverflow"); // dismiss the popup window when touched popupView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { popupWindow.dismiss(); return true; } }); // show the popup window // which view you pass in doesn't matter, it is only used for the window token popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0); //popupWindow.setOutsideTouchable(false); // doesn't seem to change anything for me View container = popupWindow.getContentView().getRootView(); if(container != null) { WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); WindowManager.LayoutParams p = (WindowManager.LayoutParams)container.getLayoutParams(); p.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND; p.dimAmount = 0.3f; if(wm != null) { wm.updateViewLayout(container, p); } } ,然后客户端可以wait for a value at this location