从付款网关将用户重定向回网站后,CodeIgniter会话数据丢失

时间:2020-04-02 11:55:18

标签: php session codeigniter-3

我正在使用CodeIgniter 3开发一个项目。用户可以通过预订页面上的paytm付款网关进行在线付款。

用户完成付款过程后,他将被重定向回我的网站,该网站由响应控制器处理,我将使用会话中存储的预订ID更新预订详细信息,例如付款方式和预订状态。当我尝试在此控制器中访问会话数据时,该会话数据不可用。

这是我的会话配置:

 $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;

这是处理付款网关发送的响应的控制器

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');
    }
}

我正在使用php版本7.2的codeigniter会话库

2 个答案:

答案 0 :(得分:0)

这是一个旧问题,但看起来似乎已得到适当解决。在CI 3.1.11中,我重定向到了支付网关,当网关完成支付并将控制权返回给会话时,会话变量“丢失”。

事实是它们只是没有再生。数小时(几天!!)后,调查此事并尝试here中列出的所有选项以及其他(无济于事!),答案就在于重新生成会话变量。

如果您的用户仅通过局域网访问系统,那么您可以跳过前两个步骤:

  1. 在system / libraries / Session / Session.php中,注释掉了第126-128和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'));
//}

这样做的原因是在第121行中的$_SESSION['__ci_last_regenerate']之后没有恢复session_start()。结果是从未执行过$this->sess_regenerate()

  1. 第二步是确保注销功能正确清除缓存,以防止注销后重新生成:
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');
}

如果您的用户将通过移动或wifi neworks访问,则可能需要做更多的事情。在PHP文档中的PHP函数session_regenerate_id()上给出警告:

警告当前,session_regenerate_id不能处理不稳定 网络连接良好,例如移动和WiFi网络。因此,您可能 通过致电session_regenerate_id体验会话丢失。

这就是我所做的:

  1. 找到上一个会话的session_id。如果您的会话数据存储在数据库中,那么以下代码可能会很好地工作:
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. 按照建议here,然后在session.php的第121行执行以下操作:
$session_id = $this->latestSessionId();
session_id($session_id);
session_start();
  1. sess_regenerate函数更改为:
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. config.phpsess_expirationsess_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 :(得分:-1)

下面的解决方案在Codeigniter中对我来说正常工作。如果您使用header("Location: $url");重定向到付款网关。只需在标头重定向后添加exit();。因为您的会话会覆盖支付网关会话,所以他们会为其支付网关启动新会话。添加exit();后,只要会话有效期,您的域的会话将保持不变。最终代码为

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