You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

第三方支付回调后PHP Session变量丢失问题求助

第三方支付回调后PHP Session丢失问题解决

问题说明

错误截图

以下是第三方支付的回调响应处理代码,当前遇到的问题是:获取支付回调响应后,PHP Session变量被销毁,出现截图中的警告错误。已在发起支付网关请求前设置好PHP Session变量。

回调处理代码

session_start();
$servername = "localhost";
$username = "root";
$dbname = "srdb";
$password = "";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

if( isset($_SERVER['HTTPS'] ) ) {
   $host ='https';
}else{
    $host = 'http';
}
require_once 'TransactionResponseBean.php';

$parameters = file_get_contents("./parameters.json");
$data = json_decode($parameters, true);

$protocolType = 'http';
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
    $protocolType = 'https';
}

if(!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '80'){
    $hostStr = "$protocolType://$_SERVER[SERVER_NAME]$_SERVER[SCRIPT_NAME]";
}else{
    $hostStr = "$protocolType://$_SERVER[SERVER_NAME]:$_SERVER[SERVER_PORT]$_SERVER[SCRIPT_NAME]";
}
$resHost = explode('/', $hostStr);
array_pop($resHost);
$resHost = implode('/', $resHost);
?>
<html>
<head>
    <title>Payment Response</title>
    <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1" / >
    <link rel="stylesheet" href="<?php echo $resHost . '/assets/css/bootstrap.min.css';?>">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" type="text/javascript"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-print-css/css/bootstrap-print.min.css" media="print">
    <script src="<?php echo $resHost . '/assets/js/bootstrap.min.js';?>"></script>

    <script src="js/response.js"></script>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<?php include 'logotext.php';?>
    <div class="container">
    <?php include 'userdisplay.php';?>
    <?php include 'nav.php';?>
</div>
<?php
if ($_POST) {
    if (isset($_POST['msg'])) {
        $response = $_POST;
        if (is_array($response)) {
            $str = $response['msg'];
        } else if (is_string($response) && strstr($response, 'msg=')) {
            $outputstr = str_replace('msg=', '', $response);
            $outputArr = explode('&', $outputstr);
            $str = $outputArr[0];
        } else {
            $str = $response;
        }
        $transactionResponseBean = new TransactionResponseBean();
        $transactionResponseBean->setResponsePayload($str);
        $transactionResponseBean->key = $data['key'];
        $transactionResponseBean->iv = $data['iv'];
        $response = $transactionResponseBean->getResponsePayload();

        //Writing in Response Log
        $log  = "Date : ".date("F j, Y, g:i a")."; Response Data : ".$response.PHP_EOL;

        //Saving string to log by using "FILE_APPEND" to append.
        file_put_contents('logs/response/log_'.date("j.n.Y").'.log', $log, FILE_APPEND);

        $response_n = explode("|", $response);
        //print_r($response_n);
        display_response($response_n,$data);
    } else if (isset($_POST['response'])) {

        //Writing in Response Log
        $log  = "Date : ".date("F j, Y, g:i a")."; Response Data : ".$_POST['response'].PHP_EOL;
        
        //Saving string to log by using "FILE_APPEND" to append.
        file_put_contents('logs/response/log_'.date("j.n.Y").'.log', $log, FILE_APPEND);

        $response_n = explode("|", $_POST['response']);
        display_response($response_n,$data);
    }
} else {
    echo "No Response Received";
}
?>
</body>
</html>
<?php

function display_response($res, $parameters)
{
    $payment_array = array();
    $stat = $res[0];
    $mystatus = explode("=", $stat);
    $status = $mystatus[1];
    $message;
    echo '<div class="container" id="print-div">
    <div class="row">
        <div class="col-md-12">
           <form action="response_handler.php" method="POST">
            <table class="table table-bordered table-hover">
                <tr class="info">
                    <th width="100%" style="text-align:center" colspan="2">Transaction Acknowledgement</th>
                </tr>
                <tr> 
                 <td>Applicant Name</td><td>'.$_SESSION['appname'].'</td>
                </tr>
                <tr> 
                 <td>Applicant ID</td><td>'.$_SESSION['appid'].'</td>
                </tr>';
    foreach ($res as $val) {
        $response1 = explode("=", $val);
        array_push($payment_array,$response1[1]);
        if( $response1[0] == 'txn_err_msg' && $status == '0300'){
           
            continue;
        }

        $data = getdetails($response1[0], $parameters);

        if (!(empty($data))) {
            $colum_name = $data;
        } else {
            continue;
        }

        if (empty($response1[1])) {
            $response1[1] = "Not found";
        }

        echo "<tr>";
        echo "<td> $colum_name </td>";

        if($response1[1] == "0300" || $response1[1] == "success"){
            $message="success";
       
            echo "<td style='background-color: darkseagreen;color: aliceblue;'> $response1[1] </td>";
        }elseif ($response1[1] == "0399" || $response1[1] == "failure") {
            $message="failure";
            echo "<td style='background-color: red;color: white;'> $response1[1] </td>";
        }else{
            echo "<td> $response1[1] </td>";
        }
        
        echo "</tr>";
    }
    echo "</table>
                </div>
             
            </div>
        </div>";
        
       
        $sql_load_payment = "INSERT INTO payment_details VALUES('$session_appid','$payment_array[0]','$payment_array[1]','$payment_array[2]','$payment_array[3]','$payment_array[6]','$payment_array[8]','$payment_array[5]')";
        $conn->query($sql_load_payment);

        if($message === "success"){
        $sql_stat = "UPDATE final_status 
        SET payment='DONE'
        WHERE app_id='$session_appid'";
        $conn->query($sql_stat);
        }
       
       
        $conn->close();
         
        echo '<div class="container">
              <div class="row">
                 <div class="col-md-12">';

                 echo "<input type='button' name='print' value='save' id='save'/>";
        if($message == 'success'){
            echo "<input type='submit' name='pbtn' value='Proceed'/>";
        }
        if($message == 'failure'){
            echo "<input type='submit' name='rbtn' value='Retry Payment'/>";
        }
        echo '</form>
               </div>
                </div>
                </div>';
}

function getdetails($code, $parameters)
{
    if($parameters['showAllResponse'] == "ON"){        
        $column_value = [
            "txn_status"            => "Transaction Status",
            "txn_msg"               => "Message",
            "txn_err_msg"           => "Error Message",
            "clnt_txn_ref"          => "Transaction ID",
            "tpsl_bank_cd"          => "TPSL Bank Code",
            "tpsl_txn_id"           => "TPSL Transaction ID",
            "txn_amt"               => "Amount",
            "tpsl_txn_time"         => "Transaction Time",
            "tpsl_rfnd_id"          => "TPSL Refund ID",
            "bal_amt"               => "Balance Amount",
            "REFUND_DETAILS"        => "Refund details",
            "rqst_token"            => "Request Token",
            "bank_name"             => "Bank Name",
            "card_id"               => "Card ID",
            "alias_name"            => "Alias Name",
            "card_Type"             => "Card Type",
            "Card_Expiry"           => "Card Expiry",
            "hash"                  => "Hash",
            "BANK_TYPE"             => "Bank Type",
            "auth"                  => "Auth"
        ];
    }
    else{
        $column_value = [
            "txn_status"            => "Transaction Status",
            "txn_msg"               => "Message",
            "txn_err_msg"           => "Error Message",
            "clnt_txn_ref"          => "Transaction ID",
            "tpsl_bank_cd"          => "TPSL Bank Code",
            "tpsl_txn_id"           => "TPSL Transaction ID",
            "txn_amt"               => "Amount",
            "REFUND_DETAILS"        => "Refund details",
            "bank_name"             => "Bank Name"
        ];
    }
    if (in_array($code, array_keys($column_value))) {
        return $column_value[$code];
    }
}

?>

解决方案

1. 确保Session初始化无输出干扰

把session_start();放在PHP脚本的最开头,确保它在任何HTML输出、空格甚至UTF-8 BOM字符之前执行。隐性输出会破坏Session的初始化流程,修改后开头应为:

<?php
session_start();
// 后续代码...

2. 解决第三方回调的Session隔离问题

支付网关的回调是服务器端发起的请求,不会携带用户浏览器的Session Cookie,因此当前用户的Session无法直接复用。解决办法:

  • 发起支付时,将用户的session_id()或关键标识(比如$_SESSION['appid'])作为自定义参数传递给支付网关(具体参考支付网关文档,多数支持传递自定义回调参数)。
  • 回调时,从POST参数中获取该标识:
    • 如果是Session ID,执行session_id($received_session_id);后再调用session_start();恢复Session。
    • 如果是appid,直接从数据库查询用户信息,替代Session变量的使用(更安全可靠)。

3. 修复代码中的变量错误

  • display_response函数中使用了未定义的$session_appid,替换为$_SESSION['appid'](或从回调参数中获取的appid)。
  • $conn变量在函数内未定义,由于函数有独立作用域,需将$conn作为参数传入函数,或在函数内重新初始化数据库连接(推荐传参)。修改后的函数定义及调用示例:
// 修改函数定义
function display_response($res, $parameters, $conn, $appid)
{
    // 用$appid替代原$session_appid
    $sql_load_payment = "INSERT INTO payment_details VALUES('$appid','$payment_array[0]','$payment_array[1]','$payment_array[2]','$payment_array[3]','$payment_array[6]','$payment_array[8]','$payment_array[5]')";
    $conn->query($sql_load_payment);
    // 后续代码...
}

// 调用时传入参数
display_response($response_n,$data, $conn, $_SESSION['appid']);

4. 检查Session配置

查看php.ini中的相关配置项:

  • session.cookie_domain:设置为当前域名,避免Cookie跨域无法传递。
  • session.cookie_secure:若网站使用HTTPS,设置为On,确保Cookie仅通过HTTPS传输。
  • session.cookie_lifetime:设置合理的有效期,避免Session过早过期。

内容的提问来源于stack exchange,提问作者kapil joshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 04:55:55