PayPal IPN - 无法访问会话数据?

all. I'm having issues with PayPal IPN integration where it seems I cannot get my solution to read session variables.

Basically, in my shop module script, I store the customer's details as provided by PayPal to an orders table. However, I also wish to save products ordered in a transaction to a separate table linked by the order ID.

However, it's the second part of the script that's not working, where I loop through the products in the session and then save them to the orders_products table.

Is there a reason why the session data not being read?

The code within shop.php is as follows:

if ($paypal->validate_ipn()) {
    $name = $paypal->ipn_data['address_name'];
    $street_1 = $paypal->ipn_data['address_street'];
    $street_2 = "";
    $city = $paypal->ipn_data['address_city'];
    $state = $paypal->ipn_data['address_state'];
    $zip = $paypal->ipn_data['address_zip'];
    $country = $paypal->ipn_data['address_country'];
    $txn_id = $paypal->ipn_data['txn_id'];
    $sql = "INSERT INTO orders (name, street_1, street_2, city, state, zip, country, txn_id)
            VALUES (:name, :street_1, :street_2, :city, :state, :zip, :country, :txn_id)";
    $smt = $this->pdo->prepare($sql);
    $smt->bindParam(':name', $name, PDO::PARAM_STR);
    $smt->bindParam(':street_1', $street_1, PDO::PARAM_STR);
    $smt->bindParam(':street_2', $street_2, PDO::PARAM_STR);
    $smt->bindParam(':city', $city, PDO::PARAM_STR);
    $smt->bindParam(':state', $state, PDO::PARAM_STR);
    $smt->bindParam(':zip', $zip, PDO::PARAM_STR);
    $smt->bindParam(':country', $country, PDO::PARAM_STR);
    $smt->bindParam(':txn_id', $txn_id, PDO::PARAM_INT);
    $smt->execute();
    // save products to orders relationship
    $order_id = $this->pdo->lastInsertId();
    // $cart = $this->session->get('cart');
    $cart = $this->session->get('cart');
    foreach ($cart as $product_id => $item) {
        $quantity = $item['quantity'];
        $sql = "INSERT INTO orders_products (order_id, product_id, quantity) VALUES ('$order_id', '$product_id', '$quantity')";
        $res = $this->pdo->query($sql);
    }
    $this->session->del('cart');
    mail('martin@mcbwebdesign.co.uk', 'IPN result', 'IPN was successful on wrestling-wear.com');
} else {
    mail('martin@mcbwebdesign.co.uk', 'IPN result', 'IPN failed on wrestling-wear.com');
}

And I'm using the PayPal IPN class for PHP as found here: http://www.micahcarrick.com/04-19-2005/php-paypal-ipn-integration-class.html, but the contents of the validate_ipn() method is as follows:

public function validate_ipn()
{
    $url_parsed = parse_url($this->paypal_url);
    $post_string = '';
    foreach ($_POST as $field => $value) {
        $this->ipn_data[$field] = $value;
        $post_string.= $field.'='.urlencode(stripslashes($value)).'&';
    }
    $post_string.= "cmd=_notify-validate"; // append IPN command
    // open the connection to PayPal
    $fp = fsockopen($url_parsed[host], "80", $err_num, $err_str, 30);
    if (!$fp) {
        // could not open the connection. If logging is on, the error message will be in the log
        $this->last_error = "fsockopen error no. $errnum: $errstr";
        $this->log_ipn_results(false);
        return false;
    } else {
        // post the data back to PayPal
        fputs($fp, "POST $url_parsed[path] HTTP/1.1
");
        fputs($fp, "Host: $url_parsed[host]
");
        fputs($fp, "Content-type: application/x-www-form-urlencoded
");
        fputs($fp, "Content-length: ".strlen($post_string)."
");
        fputs($fp, "Connection: close

");
        fputs($fp, $post_string . "

");
        // loop through the response from the server and append to variable
        while (!feof($fp)) {
            $this->ipn_response.= fgets($fp, 1024);
        }
        fclose($fp); // close connection
    }
    if (eregi("VERIFIED", $this->ipn_response)) {
        // valid IPN transaction
        $this->log_ipn_results(true);
        return true;
    } else {
        // invalid IPN transaction; check the log for details
        $this->last_error = 'IPN Validation Failed.';
        $this->log_ipn_results(false);
        return false;
    }
}

If I recall correctly, PayPal IPN sends a notification to your script directly. Since the notification is coming from PayPal - NOT the customer that placed the order - their session doesn't exist in this context. Therefore, all their cart data doesn't exist in the session.

When I've used IPN in the past, I stored everything about their order in the database and generated a TransactionID. This is one of the pass-through variables that I can send off with the rest of the order to PayPal and they will pass it back. Once I received the IPN from PayPal I re-hydrated their order based on the TransactionID and proceeded with whatever business rules I had to follow - send an email, create passwords, etc.

I am currently working on this -- say you are trying to get the session user_id in insert into your transaction tables, it may be best to sent the user_id to Paypal along with the order. Because if you write to the DB as soon as they are redirected to Paypal you have no guarantee they actually completed the order. In addition, I think PayPal send back the product/order information in a string delimited by a comma, so you would want to look through the count of however many unique items you sold, and dynamically get item_id1, item_id2, item_id3 ...so your query is always changing. Correct me if I'm wrong, I'm about to start implementing this but without using classes.