waldokhalid
waldokhalid

Reputation: 49

Firebase cloud function onRequest() not being triggering

My firebase cloud function is not working as expected and this is causing a headache, for me and my freelance client(my first freelance job).

The following is my cloud function. It is supposed to receive payload payment data in json format. This data is to be extracted and saved in firestore document. I confirm if payment is successful or not using the data written in firestore document.

Note: It was working as expected until yesterday morning, when payments I could no longer confirm payment status. I could not confirm payment status because the data that is supposed to be written to the document, is not written.

The payload looks similar to this:

    {
 "Result": {
    "ResultType": 0,
    "ResultCode": 2001,
    "ResultDesc": "The initiator information is invalid.",
    "OriginatorConversationID": "29112-34801843-1",
    "ConversationID": "AG_20191219_00006c6fddb15123addf",
    "TransactionID": "NLJ0000000",
    "ReferenceData": {
      "ReferenceItem": {
          "Key": "QueueTimeoutURL",
          "Value": "https:\/\/internalsandbox.safaricom.co.ke\/mpesa\/b2cresults\/v1\/submit"
        }
    }
 }
}

My cloud function:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const serviceAccount = require('./service_account_key.json');

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: '<removed>'
});

console.log('WE ARE ABOUT TO BEGIN');
exports.paymentCallback = functions.https.onRequest(async (req, res) => {
    console.log('Checking if req body exists');
    console.log(req.body);

    try {
        // Check if the request body is undefined
        if (!req.body || !req.body.Result) {
            throw new Error('Request body is undefined.');
        }

        // Get the result from the request body
        const result = req.body.Result;

        console.log('Received payload: ', result);

        const responseCode = result.ResultCode;
        const mCheckoutRequestID = result.ConversationID;
        const mResultDesc = result.ResultDesc;

        if (responseCode === 0) {
            console.log('Successful transaction.');

            // Access the ResultParameters
            const resultParameters = result.ResultParameters.ResultParameter;

            let mReceipt;
            let mPhonePaidFrom;
            let mAmountPaid;

            resultParameters.forEach(entry => {
                switch (entry.Key) {
                    case 'MpesaReceiptNumber':
                        mReceipt = entry.Value;
                        break;
                    case 'PhoneNumber':
                        mPhonePaidFrom = entry.Value;
                        break;
                    case 'Amount':
                        mAmountPaid = entry.Value;
                        break;
                    default:
                        break;
                }
            });

            const mEntryDetails = {
                receipt: mReceipt,
                phone: mPhonePaidFrom,
                amount: mAmountPaid,
                result: mResultDesc
            };

            // Find the document initialized from the client device containing the CheckoutRequestID
            await new Promise(resolve => setTimeout(resolve, 5000));
            const docRef = admin.firestore().collection('user_payments/payment_info/response_code_zero').doc(mCheckoutRequestID);
            const doc = await docRef.get();

            if (doc.exists) {
                // Save transaction details in DB
                await docRef.update(mEntryDetails);
                console.log('Updated document: ', docRef.path);
            } else {
                console.log('No document found matching the CheckoutRequestID: ', mCheckoutRequestID);

                // Persist the data somewhere for reference.
                await admin.firestore().collection('user_payments/payment_info/response_code_zero').doc(mCheckoutRequestID).set(mEntryDetails);
            }
        } else {
            console.log('Failed transaction.');

            const mEntryDetails = {
                receipt: 'No receipt',
                result: 'Transaction failed'
            };

            // Find the document initialized from the client device containing the CheckoutRequestID
            await new Promise(resolve => setTimeout(resolve, 5000));
            const docRef = admin.firestore().collection('user_payments/payment_info/response_code_zero').doc(mCheckoutRequestID);
            const doc = await docRef.get();

            if (doc.exists) {
                // Save transaction details in DB
                await docRef.update(mEntryDetails);
                console.log('Updated document: ', docRef.path);
            } else {
                console.log('No document found matching the CheckoutRequestID: ', mCheckoutRequestID);

                // Persist the data somewhere for reference.
                await admin.firestore().collection('user_payments/payment_info/response_code_zero').doc(mCheckoutRequestID).set(mEntryDetails);
            }
        }

        // Send back a message that we've successfully processed the payment
        res.json({ result: `Payment for ${mCheckoutRequestID} response received.` });
    } catch (error) {
        console.error('Function error: ', error);
        // Retry the request using exponential backoff.
        if (!res.headersSent) {
            res.set('Retry-After', '30').status(500).send({ error: 'Internal server error.' });
        }
    }
});

Upon checking my logs, I get this:

{
insertId: "647076a10006a986947418b6"
labels: {1}
logName: "projects/<removed>/logs/cloudfunctions.googleapis.com%2Fcloud-functions"
receiveTimestamp: "2023-05-26T09:06:41.442233503Z"
resource: {2}
textPayload: "WE ARE ABOUT TO BEGIN"
timestamp: "2023-05-26T09:06:41.436614Z"
}

firebase.json

{
  "functions": [
    {
      "region": "europe-west2",
      "source": "functions",
      "codebase": "default",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log"
      ],
      "predeploy": [
        "npm --prefix \"$RESOURCE_DIR\" run lint"
      ]
    }
  ]
}

Project structure:

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         5/26/2023   3:26 PM                .dart_tool
d-----         1/19/2023  10:43 PM                .idea
d-----         3/27/2023   5:15 PM                .vscode
d-----         4/25/2023   4:16 PM                android
d-----         5/22/2023   1:56 PM                assets
d-----         5/26/2023   3:28 PM                build
d-----         5/26/2023   2:03 PM                functions
d-----         1/19/2023  10:43 PM                ios
d-----          3/7/2023  10:10 AM                lib
d-----         1/19/2023  10:43 PM                linux
d-----         1/19/2023  10:43 PM                macos
d-----         5/26/2023   1:30 AM                node_modules
d-----         1/19/2023  10:43 PM                test
d-----         5/13/2023   3:24 PM                web
d-----         1/19/2023  10:43 PM                windows

Test on firebase emulator:

Command I ran on terminal:

Invoke-RestMethod -Method POST -Uri "http://localhost:5001/<removed>/us-central1/paymentCallback" -ContentType "application/json" -InFile ".\payload.json"

result
------
Payment for exampleConversationID response recei... 

Results:

>  WE ARE ABOUT TO BEGIN
i  functions: Beginning execution of "us-central1-paymentCallback"
>  Checking if req body exists
>  {
>    Result: {
>      ResultCode: 0,
>      ConversationID: 'exampleConversationID',      
>      ResultDesc: 'exampleResultDesc',
>      ResultParameters: { ResultParameter: [Array] }
>    }
>  }
>  Received payload:  {
>    ResultCode: 0,
>    ConversationID: 'exampleConversationID',        
>    ResultDesc: 'exampleResultDesc',
>    ResultParameters: { ResultParameter: [ [Object], [Object], [Object] ] }
>  }
>  Successful transaction.
>  Updated document:  user_payments/payment_info/response_code_zero/exampleConversationID
i  functions: Finished "us-central1-paymentCallback" in 7408.2326ms

Upvotes: 0

Views: 388

Answers (0)

Related Questions