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

我正在使用 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');

    }

}

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


慕的地6264312
浏览 128回答 3
3回答

守着星空守着你

这是一个老问题,但看起来没有得到适当的解决。在 CI 3.1.11 中,我重定向到支付网关,当网关完成支付并将控制权返回给会话时,会话变量“丢失”了。事实上,他们只是没有重生。数小时(数天!!)后调查此事并尝试此处列出的所有选项和其他选项(均无效!),答案在于重新生成会话变量。如果您的用户仅通过 LAN 访问系统,那么您可能无需执行前两个步骤:在 system/libraries/Session/Session.php 中注释掉第 126 - 128 和 130 行。//if (!isset($_SESSION['__ci_last_regenerate'])) {//&nbsp; &nbsp; $_SESSION['__ci_last_regenerate'] = time();//} elseif ($_SESSION['__ci_last_regenerate'] < (time() - $regenerate_time)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));//}原因是它在第 121 行$_SESSION['__ci_last_regenerate']之后没有恢复。session_start()因此$this->sess_regenerate()从未执行过。第二步是确保注销函数正确清除缓存以防止注销后重新生成:function logout() {&nbsp; &nbsp; $this->session->sess_destroy();&nbsp; &nbsp; $this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate, no-transform, max-age=0, post-check=0, pre-check=0");&nbsp; &nbsp; $this->output->set_header("Pragma: no-cache");&nbsp; &nbsp; redirect('logout');}如果您的用户将通过移动或 wifi 网络访问,那么您可能需要做更多的事情。在 PHP 文档中的 PHP 函数session_regenerate_id() 上,它给出了警告:警告 目前,session_regenerate_id 不能很好地处理不稳定的网络,例如移动和 WiFi 网络。因此,您可能会通过调用 session_regenerate_id 遇到会话丢失的情况。所以这就是我所做的:找到session_id上次会话的。如果您的会话数据存储在数据库中,那么以下代码可能会很好地工作:function latestSessionId() {&nbsp; &nbsp; $CI = & get_instance();&nbsp; &nbsp; $CI->db->reset_query();&nbsp; &nbsp; $CI->db->select("id")->from($this->_config['save_path'])->order_by('timestamp','desc');&nbsp; &nbsp; empty($this->config['match_ip']) OR $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);&nbsp; &nbsp; $result = $CI->db->get();&nbsp; &nbsp; empty($result) OR $result = $result->row();&nbsp; &nbsp; return empty($result) ? FALSE : $result->id;}按照此处的建议,然后在 session.php 的第 121 行执行以下操作:$session_id = $this->latestSessionId();session_id($session_id);session_start();将功能更改sess_regenerate为:public function sess_regenerate($destroy = FALSE) {&nbsp; &nbsp; $_SESSION['__ci_last_regenerate'] = time();&nbsp;&nbsp; &nbsp; //session_regenerate_id($destroy);&nbsp; &nbsp; if (session_status() !== PHP_SESSION_ACTIVE) {&nbsp; &nbsp; &nbsp; &nbsp; $session_id = $this->latestSessionId();&nbsp; &nbsp; &nbsp; &nbsp; session_id($session_id);&nbsp; &nbsp; &nbsp; &nbsp; session_start();&nbsp; &nbsp; }}更改config.php为参数sess_expiration和具有相同的值sess_time_to_update:$config['sess_driver'] = 'database';&nbsp;$config['sess_cookie_name'] = 'cisession';$config['sess_expiration'] = 7200;$config['sess_save_path'] = 'ci_sessions';&nbsp;$config['sess_match_ip'] = TRUE;&nbsp;&nbsp;$config['sess_time_to_update'] = 7200;

跃然一笑

这个错误可能是我在 codigniter 4 版本中遇到的在你的 .env 文件中&nbsp;cookie.prefix = ''&nbsp;cookie.expires = 0&nbsp;cookie.path = '/'&nbsp;cookie.domain = ''&nbsp;cookie.secure = true&nbsp;cookie.httponly = false&nbsp;cookie.samesite = 'None'&nbsp;cookie.raw = false此错误将解决

慕妹3242003

下面的解决方案在 Codeigniter 中对我来说是正确的。如果您使用 重定向到支付网关header("Location: $url");。只需exit();在标题重定向后添加即可。因为您的会话被支付网关会话覆盖,他们会为其支付网关启动新会话。添加exit();您的会话后,只要您的会话有效,您的域就会保持不变。最终代码将是header("Location: $url");exit();
打开App,查看更多内容
随时随地看视频慕课网APP