为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
慕的地6264312 2022-12-03 10:18:38
我正在使用 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
查看完整描述

3 回答

?
守着星空守着你

TA贡献1799条经验 获得超8个赞

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


事实上,他们只是没有重生。数小时(数天!!)后调查此事并尝试此处列出的所有选项和其他选项(均无效!),答案在于重新生成会话变量。


如果您的用户仅通过 LAN 访问系统,那么您可能无需执行前两个步骤:


在 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()从未执行过。


第二步是确保注销函数正确清除缓存以防止注销后重新生成:

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 网络访问,那么您可能需要做更多的事情。在 PHP 文档中的 PHP 函数session_regenerate_id() 上,它给出了警告:


警告 目前,session_regenerate_id 不能很好地处理不稳定的网络,例如移动和 WiFi 网络。因此,您可能会通过调用 session_regenerate_id 遇到会话丢失的情况。


所以这就是我所做的:


找到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;

}

按照此处的建议,然后在 session.php 的第 121 行执行以下操作:

$session_id = $this->latestSessionId();

session_id($session_id);

session_start();

将功能更改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();

    }

}

更改config.php为参数sess_expiration和具有相同的值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;


查看完整回答
反对 回复 2022-12-03
?
跃然一笑

TA贡献1826条经验 获得超6个赞

这个错误可能是我在 codigniter 4 版本中遇到的


在你的 .env 文件中


 cookie.prefix = ''

 cookie.expires = 0

 cookie.path = '/'

 cookie.domain = ''

 cookie.secure = true

 cookie.httponly = false

 cookie.samesite = 'None'

 cookie.raw = false

此错误将解决


查看完整回答
反对 回复 2022-12-03
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

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

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


查看完整回答
反对 回复 2022-12-03
  • 3 回答
  • 0 关注
  • 125 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信