Paystack is not working fine on it's callback function

402 Views Asked by At

I'm unable to use stripe for payment, because stripe payment ain't working in nigeria.

So i'm using Paystack, But the problem i'm facing now is that

When i deposit fund it's not increasing the balance

Please how will i go about itCheck out my code below

exports.depositFunds = async (req, res) => {
  const { amount, email, reference } = req.body;
  const user = req.user._id;
  const { _id } = user;
  const jwtToken = jwt.sign({ userId: _id }, process.env.JWT_SECRET);

  const transaction = await paystack.transaction
    .initialize({
      amount,
      email,
      reference,
      metadata: {
        sender: req.user._id,
        receiver: req.user._id,
        jwtToken: jwtToken,
      },
      callback_url: "http://localhost:8000/api/transactions/payment-callback",
    })
    .then((response) => {
      res.send(response.data);
    });

  res.json(transaction);

The callback

exports.paymentCallback = async (req, res) => {
  const reference = await req.query.reference;
  paystack.transaction.verify(reference, (error, body) => {
    if (error) {
      console.log(error);
      return res.redirect("/error");
    }
    const { data } = body;
    if (data.status === "success") {
      const token = data.metadata.jwtToken;
      const decodedToken = jwt.verify(token, process.env.JWT_SECRET);
      const userId = decodedToken.userId;
      if (!userId) {
        return res.status(401).json({ error: "Invalid token" });
      }
      console.log(" ~ userId:", userId);
      // You can perform any other necessary actions here
      const newTransaction = new Transactions({
        sender: userId,
        receiver: userId,
        amount: data.amount,
        type: "deposit",
        reference: "pay stack transaction",
        status: "success",
      });
      newTransaction.save();

      // increase the user's balance
      User.findByIdAndUpdate(userId, {
        $inc: { balance: data.amount },
      });
      console.log(" ~ userId:", userId);
      res.send({
        message: "Transaction successful",
        data: newTransaction,
        success: true,
      });
      // res.redirect("http://localhost:3000/user/transactions");
    } else {
      console.log("Payment was not successful");
    }
  });
};

Since i can't authorize the callback on it's own, I'm sending the authorization token and User id from the deposite function to callback yet i'm not getting it.

2

There are 2 best solutions below

0
Alta Rosso On

I see you are using paystack npm package. I found it easier to use API directly as they offer a more descriptive documentation. Paystack API

You can include the callback in the params. Something like:

const params = JSON.stringify({
    "email": "[email protected]",
    "amount": "20000",
    "callback_url": "http://localhost:8000/api/transactions/payment-callback"
})

const headers = {
    Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
    'Content-Type': 'application/json'
}

Then initialize the payment.

await axios.post("https://api.paystack.co/transaction/initialize",params, 
    {headers}).then((paystackResponse) => {
        console.log(paystackResponse.data.data)
        // the response will include the url 
})

I would recommend that you verify the transaction first before you increase the user's balance in the db. Verify the transaction

0
Akuya Ekorot On

I discovered the issue was with the async callback function. When you add the async modifier to the callback function it throws an error. If you work with promises however, it works just fine.