I am currently working on integrating the M-Pesa Daraja API into my Node.js application to initiate an STK push for mobile payments. The STK push itself is working fine; however, I am encountering issues with the callback functionality.
Here is a simplified version of my code for initiating the STK push:
const express = require('express');
const axios = require('axios');
const app = express();
require("dotenv").config();
const cors = require('cors');
app.listen(process.env.PORT, () => {
console.log(`Server is running on port ${process.env.PORT}`);
});
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something went wrong!');
});
app.get('/', (req, res) => {
res.send('Hello World');
});
// app.get('/token', async (req, res) => {
// generateToken();
// });
const generateToken = async (req, res, next) => {
const auth = new Buffer.from(`${process.env.SAFARICOM_CONSUMER_KEY}:${process.env.SAFARICOM_CONSUMER_SECRET}`).toString('base64');
await axios.get("https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials", {
headers: {
authorization: `Basic ${auth}`
},
}
).then((response) => {
// console.log(data.data.access_token);
token = response.data.access_token;
next();
}).catch((err) => {
console.log(err);
})
}
app.post ("/stk", generateToken, async(req, res) => {
const phone = req.body.phone;
const amount = req.body.amount;
const date = new Date();
const timestamp =
date.getFullYear().toString() +
("0" + (date.getMonth() + 1)).slice(-2) +
("0" + date.getDate()).slice(-2) +
("0" + date.getHours()).slice(-2) +
("0" + date.getMinutes()).slice(-2) +
("0" + date.getSeconds()).slice(-2);
const password = new Buffer.from(process.env.BUSINESS_SHORT_CODE + process.env.PASS_KEY + timestamp).toString('base64');
await axios.post (
"https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest",
{
BusinessShortCode: process.env.BUSINESS_SHORT_CODE,
Password: password,
Timestamp: timestamp,
TransactionType: "CustomerPayBillOnline",
Amount: amount,
PartyA: phone, // Use the tenant's phone number here
PartyB: process.env.BUSINESS_SHORT_CODE,
PhoneNumber: phone,
CallBackURL: 'https://e3a9-41-80-113-159.ngrok-free.app/callback',
AccountReference: "Moja Nexus",
TransactionDesc: "Paid online"
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
).then ((data) => {
res.status(200).json(data.data);
}).catch((err) => {
console.log(err.message);
})
})
app.post('/callback', (req, res) => {
const callbackData = req.body;
// Log the callback data to the console
console.log(callbackData);
// Send a response back to the M-Pesa
res.json({ status: 'success' });
});
The STK push is successfully initiated, but when the payment is completed, the callback URL specified in the request does not seem to be triggered. I have verified that the callback URL is correct and accessible.
I have also checked the logs on my server, and there are no incoming requests hitting the callback URL endpoint when a payment is completed.
Could someone please guide me on how to troubleshoot and resolve this issue with the M-Pesa Daraja API callback not working? Are there any specific configurations or additional steps I need to take to ensure that the callback functionality functions as expected?
Any help or insights would be greatly appreciated. Thank you!