【问题标题】:How to dispatch a Paypal IPN to a Google Cloud function?如何将 Paypal IPN 发送到 Google Cloud 功能?
【发布时间】:2019-08-13 08:05:50
【问题描述】:

我已阅读here ,可以将 IPN 直接发送到 Google 云功能。我的 Google Cloud 功能在 Firebase 上的 index.js 文件上运行。

我已设置我的 Paypal 按钮以将 IPN 发送到我的 web 应用上的页面。

这是我在 Google Cloud Functions/Firebase 上运行的功能之一的示例:

// UPDATE ROOMS INS/OUTS
exports.updateRoomIns = functions.database.ref('/doors/{MACaddress}').onWrite((change, context) => {
    const beforeData = change.before.val(); 
    const afterData = change.after.val(); 
    const roomPushKey = afterData.inRoom; 
    const insbefore = beforeData.ins; 
    const insafter = afterData.ins; 
    if ((insbefore === null || insbefore === undefined) && (insafter === null || insafter === undefined) || insbefore === insafter) {
        return 0;
    } else {
        const updates = {};
        Object.keys(insafter).forEach(key => {
            updates['/rooms/' + roomPushKey + '/ins/' + key] = true;
        });
        return admin.database().ref().update(updates); // do the update} 
    }   
    return 0;
});

现在的问题:

1) 我想添加另一个功能来处理来自 Paypal 的 IPN,一旦我有交易。我该怎么办?

如果解决了第一个问题,我会将答案标记为正确。

2) 谷歌云功能会是什么样子?

如果你能解决这个问题,我会创建另一个问题。

注意我使用的是 Firebase(没有其他数据库也没有 PHP)。

【问题讨论】:

    标签: firebase-realtime-database paypal google-cloud-functions paypal-ipn


    【解决方案1】:

    IPN 只是一个试图到达给定端点的服务器。

    首先,您必须确保您的 firebase 计划支持 3rd 方请求(免费计划中不可用)。

    之后,您需要创建一个 http 端点,如下所示:

    exports.ipn = functions.http.onRequest((req, res) => {
        // req and res are instances of req and res of Express.js
        // You can validate the request and update your database accordingly.
    });
    

    它将在https://www.YOUR-FIREBASE-DOMAIN.com/ipn 中提供

    【讨论】:

    • 我正在制定 Blaze 计划。它支持第 3 方请求。我必须安装 express.JS npm 包吗?您能否提供一个有关如何使用/调试该 req/res 实例的示例?我是否必须将 paypal 按钮的 notify_url 参数指向 MY-FIREBASE-DOMAIN.com/ipn?
    • Cloud Functions 正在使用 express.js,因此您不必再次安装它。如果需要,您可以安装这些类型。对于您的第二个问题 - 不。只有 Paypal 才能访问该端点。我认为您应该再次查看 Paypal 的文档以了解数据应该如何流动。
    【解决方案2】:

    基于@Eliya Cohen 的回答:

    在你的 firebase 函数上创建一个函数,例如:

    exports.ipn = functions.https.onRequest((req, res) => {
        var reqBody = req.body;
        console.log(reqBody);
        // do something else with the req.body i.e: updating a firebase node with some of that info
        res.sendStatus(200);
    });
    

    当您部署函数时,请转到您的 firebase 控制台项目并检查您的函数。你应该有这样的东西:

    复制该网址,转到贝宝,编辑触发购买的按钮,向下滚动到第 3 步并在底部键入:

    notify_url= 在此处粘贴该网址

    保存更改。

    您现在可以测试您的按钮并检查您的 Firebase 云功能日志选项卡上的 req.body。

    【讨论】:

      【解决方案3】:

      感谢这里的答案,尤其是这个要点:https://gist.github.com/dsternlicht/fdef0c57f2f2561f2c6c477f81fa348e,

      ..终于想出了一个解决方案,在云 func 中验证 IPN 请求:

      let CONFIRM_URL_SANDBOX = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr';
      
      exports.ipn = functions.https.onRequest((req, res) => {
      
          let body = req.body;
          logr.debug('body: ' + StringUtil.toStr(body));
      
          let postreq = 'cmd=_notify-validate';
      
          // Iterate the original request payload object
          // and prepend its keys and values to the post string
          Object.keys(body).map((key) => {
              postreq = `${postreq}&${key}=${body[key]}`;
              return key;
          });
      
          let request = require('request');
      
          let options = {
              method: 'POST',
              uri   : CONFIRM_URL_SANDBOX,
              headers: {
                  'Content-Length': postreq.length,
              },
              encoding: 'utf-8',
              body: postreq
          };
      
          res.sendStatus(200);
      
          return new Promise((resolve, reject) => {
      
              // Make a post request to PayPal
              return request(options, (error, response, resBody) => {
      
                  if (error || response.statusCode !== 200) {
                      reject(new Error(error));
                      return;
                  }
      
                  let bodyResult = resBody.substring(0, 8);
                  logr.debug('bodyResult: ' + bodyResult);
      
                  // Validate the response from PayPal and resolve / reject the promise.
                  if (resBody.substring(0, 8) === 'VERIFIED') {
                      return resolve(true);
                  } else if (resBody.substring(0, 7) === 'INVALID') {
                      return reject(new Error('IPN Message is invalid.'));
                  } else {
                      return reject(new Error('Unexpected response body.'));
                  }
              });
      
          });
      
      });
      

      还要感谢:

      要从 PayPal 接收 IPN 消息数据,您的侦听器必须遵循以下请求-响应流程:

      您的侦听器侦听 PayPal 随每个事件发送的 HTTPS POST IPN 消息。 在收到来自 PayPal 的 IPN 消息后,您的侦听器会向 PayPal 返回一个空的 HTTP 200 响应。否则,PayPal 将重新发送 IPN 消息。 您的听众使用 HTTPS POST 将完整的消息发送回 PayPal。

      使用 cmd=_notify-validate 变量为返回的消息添加前缀,但不要更改消息字段、字段顺序或原始消息的字符编码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-11
        • 2011-08-09
        • 2016-12-09
        • 2021-04-21
        • 2016-06-10
        • 2013-04-24
        • 2016-05-27
        • 2023-04-04
        相关资源
        最近更新 更多