2
votes

I am working on a project in CodeIgniter 3. A user can make an online payment via paytm payment gateway on the booking page.

After the user completes the payment process, he is redirected back to my website which is handled by a response controller where I am updating the booking details like the payment method and booking status using the booking id stored in the session. The session data is not available when I try to access it in this controller.

This is my session configuration:

 $config['sess_driver'] = 'files';
 $config['sess_cookie_name'] = 'ci_session';
 $config['sess_expiration'] = 7200;
 $config['sess_save_path'] = BASEPATH . 'cache/sessions/';
 $config['sess_match_ip'] = FALSE;
 $config['sess_time_to_update'] = 300;
 $config['sess_regenerate_destroy'] = FALSE;

This is the controller which handles the response sent by payment gateway

public function paytmResponse(){
    $this->load->model('booking_model');
    $this->load->model('user_model');
    $this->load->library('paytm');
    $paytmChecksum = isset($_POST["CHECKSUMHASH"]) ? $_POST["CHECKSUMHASH"] : ""; 
    $this->booking_model->updatePaymentType($_SESSION['bid'], 'online');
    $valid_checksum = $this->paytm->verifyChecksum($_POST, $paytmChecksum);
    if($valid_checksum){
        if($_POST["STATUS"] == "TXN_SUCCESS"){  
            $this->booking_model->savePaymentDetails($_SESSION['bid']);
            $this->booking_model->updateBookingStatus($_SESSION['bid'], 'pending');
            $status = 1; 
        }
        else{
            $this->booking_model->updateBookingStatus($_SESSION['bid'], 'failed');
            $status = 0;
        }
    }
    else{
        $this->booking_model->updateBookingStatus($_SESSION['bid'], 'failed');
        $status = 2;
    }       
    if($status == 1){        
        redirect('booking/success');
    }    
    else{  
        $_SESSION['booking_error'] = 'Payment failed';         
        redirect('booking/failure');
    }
}

I am using the codeigniter session library, php version 7.2

2
"The session data is not available when I try to access it in this controller.", edit your question with some essential code to sample your issue. Which CI, php version are you using, are you using native $_SESSION or $session->get() to retrieve the session data?, etc...Vickel

2 Answers

0
votes

This is an old issue but does not looks like it has been addressed appropriately. In CI 3.1.11 I did a redirect to a payment gateway and when the gateway finished the payment and returned control back to the session the session variables were "lost."

The fact is they were just not regenerated. After hours (days!!) looking into the matter and trying all the options listed here and other (none worked!) the answer lies in regenerating the session variables.

If your users only access the system through a LAN then you may get away with the first two steps:

  1. In system/libraries/Session/Session.php commented out lines 126 - 128 and 130.
//if (!isset($_SESSION['__ci_last_regenerate'])) {
//    $_SESSION['__ci_last_regenerate'] = time();
//} elseif ($_SESSION['__ci_last_regenerate'] < (time() - $regenerate_time)) {
            $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
//}

The reason for this is that $_SESSION['__ci_last_regenerate'] was not restored after session_start() in line 121. As a result $this->sess_regenerate() was never executed.

  1. The second step was to make sure that the logout function clears the cache properly to prevent a regenerate after logout:
function logout() {
    $this->session->sess_destroy();
    $this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate, no-transform, max-age=0, post-check=0, pre-check=0");
    $this->output->set_header("Pragma: no-cache");
    redirect('logout');
}

If your users will access through mobile or wifi neworks then you may need to do more. On the PHP function session_regenerate_id() in PHP documentation it gives a warning:

Warning Currently, session_regenerate_id does not handle an unstable network well, e.g. Mobile and WiFi network. Therefore, you may experience a lost session by calling session_regenerate_id.

So here is what I did:

  1. Find the session_id of the last session. If your session data is stored in a database then the following code may work well:
function latestSessionId() {
    $CI = & get_instance();
    $CI->db->reset_query();
    $CI->db->select("id")->from($this->_config['save_path'])->order_by('timestamp','desc');
    empty($this->config['match_ip']) OR $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);
    $result = $CI->db->get();
    empty($result) OR $result = $result->row();
    return empty($result) ? FALSE : $result->id;
}
  1. As recommended here then did the following at line 121 of session.php:
$session_id = $this->latestSessionId();
session_id($session_id);
session_start();
  1. Changed the sess_regenerate function to:
public function sess_regenerate($destroy = FALSE) {
    $_SESSION['__ci_last_regenerate'] = time(); 
    //session_regenerate_id($destroy);
    if (session_status() !== PHP_SESSION_ACTIVE) {
        $session_id = $this->latestSessionId();
        session_id($session_id);
        session_start();
    }
}
  1. Changed config.php to have the same values for paramaters sess_expiration and sess_time_to_update:
$config['sess_driver'] = 'database'; 
$config['sess_cookie_name'] = 'cisession';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = 'ci_sessions'; 
$config['sess_match_ip'] = TRUE;  
$config['sess_time_to_update'] = 7200;
-1
votes

The solution below works correctly for me in Codeigniter. If you are redirect for payment gateway with header("Location: $url");. Simply add exit(); after your header redirect. Because your session overrite with the payment gateway session and they start the new session for their payment gateway. After adding exit(); you session will remain same for your domain as long your session validity. Final code will be

header("Location: $url");exit();