-1

I have intigrated the sslcommerz payment gateway but when I am completing my transaction successfully, instead of redirecting me in the dashboard page, it is throwing the following error: UnhandledPromiseRejectionWarning: TypeError: Cannot read property '_id' of undefined Code for payment gateway is:

const express = require( 'express' );
const router = express.Router();
const SSLCommerzPayment = require( "sslcommerz" );
const User = require( '../models/user' );
const crypto = require( 'crypto' );


router.get( '/charge', isLoggedIn, ( req, res ) =>{
  User.findById( req.user._id, ( err, user ) => { res.render( 'payments/recharge', { user } ); } )
})

router.post( '/charge', isLoggedIn, async ( req, res ) =>
{

  const id = crypto.randomBytes( 16 ).toString( "hex" );
  const { amount } = req.body;
  console.log( id + " " + amount );
  const user = await User.findById( req.user._id )
  console.log( user.PhoneNumber );
  const data = {
    //transaction info
    total_amount: amount,
    currency: 'BDT',
    tran_id: id,
    cus_name: user.username,
    cus_email: user.email,
    cus_phone: user.PhoneNumber,

    //redirection urls
    success_url: `http://localhost:8000/payment/ssl-payment-success`,
    fail_url: `http://localhost:8000/payment/ssl-payment-fail`,
    cancel_url: `http://localhost:8000/payment/ssl-payment-cancel`,
    ipn_url: `http://localhost:8000/payment/ssl-payment-notification`,


    //will not be needed for our A2F but if we delete it sslcommerz will not work
    shipping_method: 'No',
    product_name: 'Computer.',
    product_category: 'Electronic',
    product_profile: 'general',
  };
  const sslcommerz = new SSLCommerzPayment( process.env.STORE_ID, process.env.STORE_PASSWORD, false ) //true for live default false for sandbox
  sslcommerz.init( data ).then( data =>
  {
    console.log( data.GatewayPageURL )
    if ( data.GatewayPageURL )
    {
      return res.status( 200 ).redirect( data.GatewayPageURL );
    }
    else
    {
      return res.status( 400 ).json( {
        message: "Session was not successful"
      } );
    }
  } );
} );

router.post("/ssl-payment-notification", async (req, res) => {

  return res.status(200).json(
    {
      data: req.body,
      message: 'Payment notification'
    }
  );
})

router.post("/ssl-payment-success", async (req, res) => {

  const user = await User.findById( req.user._id )
  user.wallet += Number(req.body.store_amount);
  user.save();
  return res.redirect( '/user/dashboard' );
})

router.post("/ssl-payment-fail", async (req, res) => {

  return res.status(200).json(
    {
      data: req.body,
      message: 'Payment failed'
    }
  );
})

router.post("/ssl-payment-cancel", async (req, res) => {

  return res.status(200).json(
    {
      data: req.body,
      message: 'Payment cancelled'
    }
  );
})

function isLoggedIn( req, res, next )
{
  // console.log(req.isAuthenticated());
  if ( req.isAuthenticated() )
  {
    return next();
  }
  res.redirect( '/user/login' );
}

module.exports = router;

Code of app.js:

//App creation
const express = require("express");
const app = express();

//port setup
require('dotenv').config();
const port = process.env.PORT || 8080;

//body parser configutation
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));

//morgan configuration
const morgan = require('morgan');
app.use(morgan('dev'));

const cookieParser = require('cookie-parser')
app.use(cookieParser(process.env.SESSION_SECRET));
app.use(require('express-session')({
    secret: process.env.SESSION_SECRET,
    cookie : 
    {
        expires: false
    },
    resave: true,
    saveUninitialized: true
}));

//passport configuration
const passport = require('passport');
app.use(passport.initialize());
app.use(passport.session());

const localStrategy = require('passport-local');
const User = require('./models/user');
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());


//router configuration
const userRoutes = require('./routes/user');
app.use('/user',userRoutes);
const loanRoutes = require('./routes/loan');
app.use('/loan',loanRoutes);
const adminRoutes = require('./routes/admin');
app.use('/admin',adminRoutes);
const paymentRoutes = require('./routes/payment');
app.use('/payment',paymentRoutes);

//database connection
const mongoose = require('mongoose');
mongoose.connect("mongodb+srv://sifat:12345@cluster0.xtknfmw.mongodb.net/test", function(err) {
    if (err) {
        console.log("Database Not Connected", err);
    } else {
        console.log("Database Connected")
    }
});
mongoose.set('useFindAndModify', false);






//Other usage for application
app.use(express.static("public"));

app.use((req,res,next)=>{
    res.locals.currentUser = req.user;
    next();
});
app.set('view engine','ejs');

//Home page
app.get('/',(req,res)=>{res.render('home');})

//Server Start
app.listen(port, () => {console.log(`Server is running on port ${port}`);});

I think the problem is in the express session that I am using. I have set the cookie parser in my code but its still throwing the error

2 Answers2

0

You have to update the app.js requires like:

   const  express = require("express"),
          session = require('express-session'),
          env = require('dotenv'),
          bodyParser = require('body-parser'),
          morgan = require('morgan'),
          ...
          ...;
    const app = express();
    env.Config();
    // Express session
    app.use(
     session({
      secret: process.env.SESSION_SECRET,
      resave: true,
      saveUninitialized: true,
      cookie: { maxAge: 24 * 60 * 60 * 1000 },
    })
   )

   app.use((req,res,next) => {
    res.set('Cache-Control','no-cache, private, no-store, must 
    revalidate, max-stale=0, post-check=0, pre-check=0')
    res.locals.currentUser = req.user;
    next();
   });

Hope this help.

Imran Azim
  • 154
  • 1
  • 8
  • not solved the problem – Sifat Sikder Feb 28 '23 at 10:35
  • https://sandbox.sslcommerz.com/EasyCheckOut/testcde90ebecfdef880027105d7003b3236a25 POST /payment/charge 302 2347.215 ms - 210 (node:23328) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '_id' of undefined at router.post (/home/sifatsikder/HopefullyFinal-20230228T040242Z-001/HopefullyFinal/A2F-v5-20230227T144932Z-001/A2F-v5/routes/payment.js:71:46) – Sifat Sikder Feb 28 '23 at 10:37
  • I have edited my answer, updated your `app.use((req, res, next)=>{})` please see and try again. – Imran Azim Feb 28 '23 at 11:14
  • when i am running this code, my transaction is successful for the 1st time and the session is Session { cookie: { path: '/', _expires: 2023-03-03T18:48:16.429Z, originalMaxAge: 86399999, httpOnly: true }, passport: { user: 'Sifat Sikder' } } – Sifat Sikder Mar 02 '23 at 18:51
  • but when I am trying to do my 2nd transaction it is showing the error and the session is Session { cookie: { path: '/', _expires: 2023-03-03T18:48:42.049Z, originalMaxAge: 86400000, httpOnly: true } } – Sifat Sikder Mar 02 '23 at 18:52
  • 1
    I think I have got the problem. When I am logging in My cookie is being saved as my localhost requests are http but when I am making a payment transaction through an API call,the request is then https.As a result,my cookie is not saved and hence the req.user becomes undefiend – Sifat Sikder Mar 03 '23 at 06:13
0

From your code snippet, the problem is here:

router.post( '/charge', isLoggedIn, async ( req, res ) =>
{

  const id = crypto.randomBytes( 16 ).toString( "hex" );
  const { amount } = req.body;
  console.log( id + " " + amount );
  const user = await User.findById( req.user._id )
...

TypeError: Cannot read property '_id' of undefined means that your req.user object is undefined, so there is a problem in your login logic, because req.user hasn't been initialized.

M. Hicks
  • 76
  • 3
  • 7
  • 1
    I think I have got the problem. When I am logging in My cookie is being saved as my localhost requests are http but when I am making a payment transaction through an API call,the request is then https.As a result,my cookie is not saved and hence the req.user becomes undefiend – Sifat Sikder Mar 03 '23 at 06:09