如何使用Firebase Cloud Firestore创建M-Pesa回调URL?
我正在尝试用Safaricom的“Lipa Na m-Pesa”(一个肯尼亚的东西)制作一个应用程序,可以将付款发送到账单号码。该调用是对URL的如何使用Firebase Cloud Firestore创建M-Pesa回调URL?,firebase,google-cloud-firestore,callbackurl,mpesa,Firebase,Google Cloud Firestore,Callbackurl,Mpesa,我正在尝试用Safaricom的“Lipa Na m-Pesa”(一个肯尼亚的东西)制作一个应用程序,可以将付款发送到账单号码。该调用是对URL的POST请求: https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest 带标题: { 'Host': 'sandbox.safaricom.co.ke', 'Authorization': 'Bearer ${await mpesaAccessTo
POST
请求:
https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest
带标题:
{
'Host': 'sandbox.safaricom.co.ke',
'Authorization': 'Bearer ${await mpesaAccessToken}',
'Content-Type': 'application/json',
}
和机构:
{
"BusinessShortCode": "$businessShortCode",
"Password": "${generateLnmPassword(timeStamp)}",
"Timestamp": "$timeStamp",
"TransactionType": "CustomerPayBillOnline",
"Amount": "10",
"PartyA": "$userPhoneNumber",
"PartyB": "$businessShortCode",
"PhoneNumber": "$userPhoneNumber",
"CallBackURL": "?????????????????????????????",
"AccountReference": "account",
"TransactionDesc": "test",
}
我收到了一个访问令牌,生成了一个密码并成功地拨打了电话,除了CallBackURL的事情。。。M-Pesa文档对其回调的描述如下:
回调URL
这是您希望传递事务结果的端点。注册URL API回调也适用相同的规则
来自事务性请求的所有API回调都是POST请求,不要期望回调的GET请求。此外,数据未格式化为application/x-www-form-urlencoded格式,它是application/json,因此不要期望数据出现在您语言的常用POST字段/变量中,直接从传入的输入流读取结果
(此处有更多信息,但您可能需要登录:请参阅“Lipa na M-Pesa”)
我的应用程序托管在Firebase Cloud Firestore上。我有没有办法与他们一起创建一个回调URL,将他们的回调作为Firestore集合中的文档接收
或者这是不可能的,因为他们需要授权令牌和其他东西来完成这项工作。。。我不能影响M-Pesa将发送的标题和正文
(顺便说一句,我用flatter/Dart编码,所以请不要用Javascript或任何东西回答!我会不知所措的…:p flatter/Dart或纯文本就可以了。谢谢!)
我有没有办法用它们创建一个回调URL
将其回调作为Firestore集合中的文档接收
在Firebase生态系统中,最常见的方法是编写一个将由Safaricom服务调用的
在云功能中,您将能够根据POST请求的内容更新Firestore文档
比如:
exports.safaricom = functions.https.onRequest((req, res) => {
// Get the header and body through the req variable
// See https://firebase.google.com/docs/functions/http-events#read_values_from_the_request
return admin.firestore().collection('...').doc('...').update({ foo: bar })
.then(() => {
res.status(200).send("OK");
})
.catch(error => {
// ...
// See https://www.youtube.com/watch?v=7IkUgCLr5oA&t=1s&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=3
})
});
我确实注意到,您要求我们不要“用Javascript或任何东西回答”,而是使用Flutter/Dart,但我认为您无法在Flutter中实现这一点:您需要在您完全控制并公开API端点的环境中实现此webhook,如您自己的服务器或云函数
云函数乍一看可能很复杂,但实现HTTPS云函数并没有那么复杂。我建议您阅读并观看Firebase中关于“JavaScript承诺”的三个视频,如果您遇到任何问题,请就此提出新问题。云函数不是基于Dart的 见下面的解决方案
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const parse = require("./parse");
admin.initializeApp();
exports.lmno_callback_url = functions.https.onRequest(async (req, res) => {
const callbackData = req.body.Body.stkCallback;
const parsedData = parse(callbackData);
let lmnoResponse = admin.firestore().collection('lmno_responses').doc('/' + parsedData.checkoutRequestID + '/');
let transaction = admin.firestore().collection('transactions').doc('/' + parsedData.checkoutRequestID + '/');
let wallets = admin.firestore().collection('wallets');
if ((await lmnoResponse.get()).exists) {
await lmnoResponse.update(parsedData);
} else {
await lmnoResponse.set(parsedData);
}
if ((await transaction.get()).exists) {
await transaction.update({
'amount': parsedData.amount,
'confirmed': true
});
} else {
await transaction.set({
'moneyType': 'money',
'type': 'deposit',
'amount': parsedData.amount,
'confirmed': true
});
}
let walletId = await transaction.get().then(value => value.data().toUserId);
let wallet = wallets.doc('/' + walletId + '/');
if ((await wallet.get()).exists) {
let balance = await wallet.get().then(value => value.data().moneyBalance);
await wallet.update({
'moneyBalance': parsedData.amount + balance
})
} else {
await wallet.set({
'moneyBalance': parsedData.amount
})
}
res.send("Completed");
});
解析函数
const moment = require("moment");
function parse(responseData) {
const parsedData = {};
parsedData.merchantRequestID = responseData.MerchantRequestID;
parsedData.checkoutRequestID = responseData.CheckoutRequestID;
parsedData.resultDesc = responseData.ResultDesc;
parsedData.resultCode = responseData.ResultCode;
if (parsedData.resultCode === 0) {
responseData.CallbackMetadata.Item.forEach(element => {
switch (element.Name) {
case "Amount":
parsedData.amount = element.Value;
break;
case "MpesaReceiptNumber":
parsedData.mpesaReceiptNumber = element.Value;
break;
case "TransactionDate":
parsedData.transactionDate = moment(
element.Value,
"YYYYMMDDhhmmss"
).unix();
break;
case "PhoneNumber":
parsedData.phoneNumber = element.Value;
break;
}
});
}
return parsedData;
}
module.exports = parse;
哇!你让它听起来完全可行!:)是的,我确实在某个地方读到云函数只接受JavaScript。。。这就是为什么我当时没有进一步调查的原因。好吧,如果需要的话,现在可能是时候了(我想投票支持你的答案,但我没有足够的声誉。无论如何,非常感谢!)@KarolinaHagegård很高兴我能帮助你!你可以接受答案。啊!现在发现了那个小记号。。。小东西!哇,我们为你感到高兴你在用颤振吗?