Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 通过云功能访问Firestore_Node.js_Firebase_Google Cloud Firestore_Google Cloud Functions - Fatal编程技术网

Node.js 通过云功能访问Firestore

Node.js 通过云功能访问Firestore,node.js,firebase,google-cloud-firestore,google-cloud-functions,Node.js,Firebase,Google Cloud Firestore,Google Cloud Functions,因此,我在同一个文件中有两个云函数: exports.Auth = functions.region('europe-west1').https.onRequest((req, res) => 及 当在Auth函数的开头添加以下代码时,它会像预期的那样向Firestore添加一个新文档,但是,当我在IPN函数的开头添加相同的代码时(当前正在通过Paypal的IPN模拟器调用),它不会执行任何操作,也不会出错 let pin = RandomPIN(10, '0123456789abc

因此,我在同一个文件中有两个云函数:

exports.Auth = functions.region('europe-west1').https.onRequest((req, res) =>


当在Auth函数的开头添加以下代码时,它会像预期的那样向Firestore添加一个新文档,但是,当我在IPN函数的开头添加相同的代码时(当前正在通过Paypal的IPN模拟器调用),它不会执行任何操作,也不会出错

  let pin = RandomPIN(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
  var userRef = db.collection('Users').doc(pin);
  var setWithOptions = userRef.set({ Activated: false }, { merge: true });
  console.log("PIN: "+pin);
到底发生了什么事,我一定错过了什么

提前谢谢

更新:

exports.IPN = functions.region('europe-west1').https.onRequest((req, res) =>
{
  console.log("IPN Notification Event Received");

  let pin = RandomPIN(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
  var userRef = db.collection('Users').doc(pin);
  var setWithOptions = userRef.set({ Activated: false }, { merge: true });
  console.log("PIN: "+pin);

  if (req.method !== "POST")
  {
    console.error("Request method not allowed.");
    res.status(405).send("Method Not Allowed");
  }
  else
  {
    console.log("IPN Notification Event received successfully.");
    res.status(200).end();
  }

  let ipnTransactionMessage = req.body;
  // Convert JSON ipn data to a query string since Google Cloud Function does not expose raw request data.
  let formUrlEncodedBody = querystring.stringify(ipnTransactionMessage);
  // Build the body of the verification post message by prefixing 'cmd=_notify-validate'.
  let verificationBody = `cmd=_notify-validate&${formUrlEncodedBody}`;

  console.log(`Verifying IPN: ${verificationBody}`);

  let options = {
    method: "POST",
    uri: getPaypalURI(),
    body: verificationBody,
  };

  // POST verification IPN data to paypal to validate.
  request(options, function callback(error, response, body)
  {
    if(!error && response.statusCode === 200)
    {
      if(body === "VERIFIED")
      {
        console.log(`Verified IPN: IPN message for Transaction ID: ${ipnTransactionMessage.txn_id} is verified.`);
        SendPIN(ipnTransactionMessage.payer_email, pin);
      }
      else if(body === "INVALID")
        console.error(`Invalid IPN: IPN message for Transaction ID: ${ipnTransactionMessage.txn_id} is invalid.`);
      else
        console.error("Unexpected reponse body.");
    }
    else
    {
      console.error(error);
      console.log(body);
    }
  });
});
下面是日志,首先是有注释的中间两行,然后是未注释的。它似乎在默默地失败,我只是不确定是什么导致了它

具有完整功能的更新:

exports.IPN = functions.region('europe-west1').https.onRequest((req, res) =>
{
  console.log("IPN Notification Event Received");

  let pin = RandomPIN(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
  var userRef = db.collection('Users').doc(pin);
  var setWithOptions = userRef.set({ Activated: false }, { merge: true });
  console.log("PIN: "+pin);

  if (req.method !== "POST")
  {
    console.error("Request method not allowed.");
    res.status(405).send("Method Not Allowed");
  }
  else
  {
    console.log("IPN Notification Event received successfully.");
    res.status(200).end();
  }

  let ipnTransactionMessage = req.body;
  // Convert JSON ipn data to a query string since Google Cloud Function does not expose raw request data.
  let formUrlEncodedBody = querystring.stringify(ipnTransactionMessage);
  // Build the body of the verification post message by prefixing 'cmd=_notify-validate'.
  let verificationBody = `cmd=_notify-validate&${formUrlEncodedBody}`;

  console.log(`Verifying IPN: ${verificationBody}`);

  let options = {
    method: "POST",
    uri: getPaypalURI(),
    body: verificationBody,
  };

  // POST verification IPN data to paypal to validate.
  request(options, function callback(error, response, body)
  {
    if(!error && response.statusCode === 200)
    {
      if(body === "VERIFIED")
      {
        console.log(`Verified IPN: IPN message for Transaction ID: ${ipnTransactionMessage.txn_id} is verified.`);
        SendPIN(ipnTransactionMessage.payer_email, pin);
      }
      else if(body === "INVALID")
        console.error(`Invalid IPN: IPN message for Transaction ID: ${ipnTransactionMessage.txn_id} is invalid.`);
      else
        console.error("Unexpected reponse body.");
    }
    else
    {
      console.error(error);
      console.log(body);
    }
  });
});

实际上,这是承诺链接的问题,也是由于
请求
库引起的问题:
请求
本机支持回调接口,但不返回承诺,这是云函数中必须执行的操作

我建议您观看Doug:的官方Firebase视频,这些视频解释了这一关键概念

您可以使用
请求承诺
()和
rp()
方法,该方法“返回常规承诺/a+符合承诺”

尚不清楚
SendPIN()
在做什么。让我们假设它返回一个承诺。如果这是真的,您可以按照以下行调整代码:

//....
const rp = require('request-promise');
//....

exports.IPN = functions.region('europe-west1').https.onRequest((req, res) => {
  console.log('IPN Notification Event Received');

  let pin = RandomPIN(
    10,
    '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  );
  var userRef = db.collection('Users').doc(pin);

  if (req.method !== 'POST') {
    console.error('Request method not allowed.');
    res.status(405).send('Method Not Allowed');
  } else {
    let ipnTransactionMessage;
    userRef
      .set({ Activated: false }, { merge: true })
      .then(() => {
        console.log('PIN: ' + pin);
        ipnTransactionMessage = req.body;
        // Convert JSON ipn data to a query string since Google Cloud Function does not expose raw request data.
        let formUrlEncodedBody = querystring.stringify(ipnTransactionMessage);
        // Build the body of the verification post message by prefixing 'cmd=_notify-validate'.
        let verificationBody = `cmd=_notify-validate&${formUrlEncodedBody}`;

        console.log(`Verifying IPN: ${verificationBody}`);

        let options = {
          method: 'POST',
          uri: getPaypalURI(),
          body: verificationBody
        };
        // POST verification IPN data to paypal to validate.
        return rp(options);
      })
      .then(response => {
        //Not sure what you will get within the response object...
        console.log(
          `Verified IPN: IPN message for Transaction ID: ${
            ipnTransactionMessage.txn_id
          } is verified.`
        );
        return SendPIN(ipnTransactionMessage.payer_email, pin); //It is not clear what SendPIN is doing, let's make the assumption it returns a Promise...
      })
      .then(() => {
        res.send('Success');
        return null;
      })
      .catch(err => {
        console.error(
          `Invalid IPN: IPN message for Transaction ID: ${
            ipnTransactionMessage.txn_id
          } is invalid.`
        );
        res
          .status(500)
          .send(
            'Error: ' +
              err +
              ` - Invalid IPN: IPN message for Transaction ID: ${
                ipnTransactionMessage.txn_id
              } is invalid.`
          );
        return null;
      });
  }
});

“目前正在通过Paypal的IPN模拟器调用该函数”你确定该函数确实被调用了吗?是的,如果我注释掉中间的2个firestore行,它会验证模拟事务。请将此信息添加到您的问题中,以便我们可以清理注释痕迹。您是否返回
set()返回的承诺
方法?您应该将函数的整个代码添加到问题中,这可能是因为您没有返回并链接不同的承诺。请编辑问题,以显示整个函数没有按照您期望的方式工作,而不仅仅是其中的几行。感谢链接和您的帮助,SendPIN只是一个void函数,它使用nodeEmailer发送pin的电子邮件。我不确定它是否相关,但我得到一个错误@res.send('Success');“error Each then()应返回值或抛出承诺/始终返回”SendPIN是否异步并返回承诺?不,它只是一个同步的无效函数函数SendPIN(email,pin),它只调用nodeEmailer.createTransport,然后调用transporter.sendmail是否确定它不是异步的?请参阅:“如果未设置回调参数,则该方法返回一个承诺对象。NodeEmailer本身在内部不使用承诺,但为了方便起见,它将返回包装为承诺。”我通过添加
return null修改了答案
res.send('Success')之后。然而,我不是100%肯定这是解决你提到的问题的最好办法。在这一点上听听道格或弗兰克的意见是很有趣的。