marvin wekesa
marvin wekesa

Reputation: 11

Saving MPesa Callback data

Am trying to save MPesa Callback data, when a user has paid with Lipa Na Mpesa, ineed to save the CheckoutRequestID, with a decoded username from token, then if the payment is successful the cllback URL needs to update the associated CheckoutRequestID from mysql with the amount, from there it needs to update the user's wallet with the new value. Currently the code works well, but I cannot save, when I try to access the username or any value the callback doesn't return any data. Here is the LipaNaMpesa code and the STK Callback code.

LipaNaMpesa code

router.get('/stk', middleware.access, middleware.checkToken, (req, res) => {
    let endpoint = "https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest"
    let auth = "Bearer " + req.access_token


    let datenow = new Date()
    //console.log(datenow.getUTCDate())
    const timestamp = datenow.getFullYear() +"" + addZero((datenow.getMonth()+1))+"" +addZero(datenow.getUTCDate())+ ""+ addZero(datenow.getHours())+"" +  addZero(datenow.getMinutes())+"" +  addZero(datenow.getSeconds())
   // console.log(timestamp)
    const password = (new Buffer.from('174379' + 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919' + timestamp).toString('base64'))

    request(
        {
            url: endpoint,
            method: "POST",
            headers: {
                "Authorization": auth
            },
            json: {

                "BusinessShortCode": 174379,
                "Password": password,
                //"MTc0Mzc5YmZiMjc5ZjlhYTliZGJjZjE1OGU5N2RkNzFhNDY3Y2QyZTBjODkzMDU5YjEwZjc4ZTZiNzJhZGExZWQyYzkxOTIwMjExMjExMDcyODAw"
                "Timestamp": timestamp,
                "TransactionType": "CustomerPayBillOnline",
                "Amount": 1,
                "PartyA": 254792482180,//254792482180,
                "PartyB": 174379,
                "PhoneNumber": 254792482180,//254704148972,
                "CallBackURL": "https://9b68-41-80-113-243.ngrok.io/mrequests/stk_confirm",
                "AccountReference": "GoChama",
                "TransactionDesc": "Wallet Deposit"
            }
        },
        function (error, response, body) {
            if (error) {
                console.log(error)
            }
            else {
             // console.log(body.CheckoutRequestID)
               //console.log(req.decoded.username) 
              res.status(200).json(body)
            }
        }
    )
})

STK CallBAck Code

router.post('/stk_confirm', (req, res) => {
    console.log('....................... stk_confirm .............')
    console.log("Payload Received", req.body.Body.stkCallback)
   /* const callbackData = req.body.Body.stkCallback
    console.log("Payload Received", callbackData)
    var resultCode = callbackData.ResultCode;
    var checkoutId = callbackData.CheckoutRequestID
    var username = req.decoded.username
    if(resultCode === 0){
        const details = callbackData.CallbackMetadata.Item

        var mReceipt;
        var mPhoneNumber;
        var mAmount;

        await details.forEach(entry =>{
            switch (entry.Name){
                case "MpesaReceiptNumber":
                mReceipt = entry.Value
                break;

                case "PhoneNumber":
                mPhoneNumber = entry.Value
                break;

                case "Amount":
                mAmount = entry.Value
                break;

                default:
                    break;
            }
        })
        

    }*/
    res.status(200).json(req.body)
    
})

The commented part f the code doesnt return any value when added. Is there something I am doing wrong?

Upvotes: 1

Views: 1034

Answers (2)

anville95
anville95

Reputation: 43

I had a similar problem earlier. You're not getting the callbackData because you have not parsed the json object. Just before you handle the callBackPost request from daraja, you need to use bodyParser.json() to parse it, like so...

//remember to import the module
//const bodyParser = require("body-parser")
router.use(bodyParser.json())
router.post("/stk_confirm", (req, res) => { 
    const callbackData = req.body.Body.stkCallback;/*Everything Should now work as anticipated*/
})

If you might not be having body-parser module installed yet, you may install it as follows: Navigate to your project folder(The one containing your server script) in the command line using the 'cd' command in Windows, run...

npm install body-parser

in Linux, run...

sudo npm install body-parser

Thank you for reading, for any further inquiry, you can contact me at [email protected], Good luck.

Upvotes: 0

davidkihara
davidkihara

Reputation: 533

This is how the Daraja API will work in reference to your problem. When you call the LipaNaMpesa Code and it executes the following response is returned.

{
 "MerchantRequestID": "7758-32589747-1",
 "CheckoutRequestID": "ws_CO_21072022121325565708374149",
 "ResponseCode": "0",
 "ResponseDescription": "Success. Request accepted for processing",
 "CustomerMessage": "Success. Request accepted for processing"
}

You will save the CheckoutRequestID to the database at this point together with the decoded username from the token and anything else you would like to save. The LipaNaMpesa Code sends a prompt to the customer's phone and returns the above response.

If the customer does not enter their PIN or has an insufficient balance or for whatever reason, the transaction does not go through, the Callback URL does not return anything.

If the customer enters the PIN and pays, the Callback URL returns the following response

{
"Body": 
{
    "stkCallback": 
    {
        "MerchantRequestID": "21605-295434-4",
        "CheckoutRequestID": "ws_CO_04112017184930742",
        "ResultCode": 0,
        "ResultDesc": "The service request is processed successfully.",
        "CallbackMetadata": 
        {
            "Item": 
            [
                {
                    "Name": "Amount",
                    "Value": 1
                },
                {
                    "Name": "MpesaReceiptNumber",
                    "Value": "LK451H35OP"
                },
                {
                    "Name": "Balance"
                },
                {
                    "Name": "TransactionDate",
                    "Value": 20171104184944
                },
                {
                    "Name": "PhoneNumber",
                    "Value": 254706506361
                }
            ]
        }
    }
}
}

At this point now, you can update the DB row where you inserted CheckoutRequestID from LipaNaMpesa Code response. The CheckoutRequestID from both responses is the same.

Upvotes: 2

Related Questions