Aron Rotteveel
Aron Rotteveel

Reputation: 83173

How to re-initialize a session in PHP?

I am attempting to integrate an existing payment platform into my webshop. After making a succesful transaction, the payment platform sends a request to an URL in my application with the transaction ID included in the query parameters.

However, I need to do some post-processing like sending an order confirmation, etc. In order to do this, I'd need access to the user's session, since a lot of order-related information is stored there. To do this, I include the session_id in the intial request XML and do the following after the transaction is complete:

$sessionId = 'foo'; // the sessionId is succesfully retrieved from the XML response
session_id($sessionId);
session_start();

The above code works fine, but $_SESSION is still empty. Am I overlooking something or this simply not possible?

EDIT:

Thanks for all the answers. The problem has not been solved yet. As said, the strange thing is that I can succesfully start a new session using the session_id that belongs to the user that placed the order. Any other ideas?

Upvotes: 3

Views: 2901

Answers (7)

Aron Rotteveel
Aron Rotteveel

Reputation: 83173

Many thanks for all the replies.

Smazurov's answer got me thinking and made me overlook my PHP configuration once more.

PHP's default behaviour is not to encrypt the session-related data, which should make it possible to read out the session data after restarting an old session from another client. However, I use Suhosin to patch and prevent some security issues. Suhosin's default behaviour is to encrypt session data based on the User Agent, making it a lot harder to read out other people's sessions.

This was also the cause of my problems; disabling this behaviour has solved the issue.

Upvotes: 1

Chris Boulton
Chris Boulton

Reputation:

Make sure you're closing the current session before you attempt to start the new one. So you should be doing:

$id = 'abc123';
session_write_close();
session_id($id);
session_start();

Upvotes: 0

Stepan Mazurov
Stepan Mazurov

Reputation: 1374

I will venture to guess that since domains are different from where the session is set to where you are trying to read it, php is playing it safe and not retrieving session data set by a different domain. It does so in an effort to preserve security in case somebody were to guess session ID and hijack the data.

Workaround for this, assuming the exchange happens on the same physical disk, is to temporary write order data to a serialized (and possibly encrypted depending on wether or not full credit card number is being tracked, which is a whole another story) file that once read by the receiving end is promptly removed.

In essence all that does is duplicates the functionality that you are trying to get out of sessions without annoying security side-effects.

Upvotes: 3

Jay
Jay

Reputation: 833

I'm not sure the exact length of time between your transaction and your check; but it certainly seems that your session cookie has expired. Sessions expire usually after 45 minutes or so by default. This is to free up more uniqid's for php to use and prevent potential session hijacking.

I'm not sure if you have a custom session handler and whether it's stored in the database but guessing from your posts and comments on this page I would assume it is stored in server side cookies.

Now the solution to your problem, would be to bite the bullet and store the necessary data in the database and access it via the session id, even if it means creating another table to sit along side your orders table.

If however you are doing the action immediately then the other explanation is that either the user logged out or committed an action which destroyed their session (removing the server side cookie).

You will see these cookies in your servers /tmp folder, try have a look for your cookie, it should be named 'sess' + $session_id.

Upvotes: -1

Dennis C
Dennis C

Reputation: 24747

How about do it in another PHP page, and you do a iframe include / redirect user to the second page?

Upvotes: -1

jishi
jishi

Reputation: 24624

Not really what you ask for, but don't you need to persist the order into database before you send the customer to the payment-service? It's better to rely on persisted data in your post-processing of the order when you receive the confirmation of the payment.

Relying on sessions is not reliable since you will have no idea on how long this confirmation will take (usually it's instant, but in rare cases this will have a delay).

Also, in the event of your webserver restarting during this time span, will make you lose relevant data.

A third issue is if you have a load-balancing solution, with individual session-managment (very common) then you will have no guarantee that the payment-server and your client will reach the same webserver (since stickiness is usually source-ip based).

Upvotes: 4

benlumley
benlumley

Reputation: 11382

Dirty, but has worked for me:

Tell the payment gateway to use

http://yourdomain.com/callbackurl.php?PHPSESSID=SESSIONIDHERE

PHP uses that method of passing a session around itself if you set certain config vars (session.use_trans_sid), and it seems to work even if PHP has been told not to do that. Its certainly always worked for me.

Edit:

Your problem may be that you have session.auto_start set to true - so the session is starting automatically using whatever ID it generates, before your code runs.

Upvotes: -1

Related Questions