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%肯定这是解决你提到的问题的最好办法。在这一点上听听道格或弗兰克的意见是很有趣的。