Okay so I traced the issue backwards beginning from where I can see the session timeout error begins. Normally hitting the "confirm order" button would lead us to the checkout success page and the order is inputted into the zen-cart system.
So looking at the "includes\modules\pages\checkout_success\header.php" file, referencing line 16...
if (!$_SESSION['customer_id']) {
zen_redirect(zen_href_link(FILENAME_TIME_OUT));
}
We get directed to the "Whoops, your session timed out" message when the session customer id variable is UNSET.
Now looking at the "includes\modules\payment\paypaldp.php" file, referencing line 1748...
function ec_delete_user($cid) {
global $db;
unset($_SESSION['customer_id']);
unset($_SESSION['customer_default_address_id']);
unset($_SESSION['customer_first_name']);
unset($_SESSION['customer_country_id']);
unset($_SESSION['customer_zone_id']);
unset($_SESSION['comments']);
unset($_SESSION['customer_guest_id']);
}
You can see that indeed a function exists within this module that UNSETS the customer_id variable of a current customer session...
Now here is the interesting thing about this function -- the comment for the function describes it as follows:
/**
- If the account was created only for temporary purposes to place the PayPal order, delete it.
*/
I can't think of any scenario where an account could only be temporarily created to place an order using their credit card inputted directly on the zen-cart website (Website Payments Pro method).
There is no possible way for this to happen, the customer must create a permanent account first, unless the zen-cart administrator implemented COWOA for their store?? But that's an entirely different module, which I'm not familiar with at all, and I don't think has anything to do with this particular function in question.
Furthermore, this function only UNSETS most of a session's variables, it doesn't actually delete the customer's account. If you reference the function as it's defined in the PayPal Express payments module (paypalwpp.php), that function definition actually deletes the customer entirely from the zen-cart database in addition to UNSETTing all the session variables. I haven't familiarized myself too much with PayPal express checkout, but I know in the PayPal express checkout module settings we can choose whether or not to automatically create accounts, so I'm assuming that it is indeed possible for customers to shop as guests, check out with PayPal and have their account details destroyed from the zen-cart database after checkout completes. That seems fine and a proper implementation for the flow of a PayPal Express Checkout transaction, but this simply isn't possible when we are talking about Website Payments Pro.
This leads me to believe that this function might just be old deprecated code that carried over somehow, and it does not really have any place in the way the paypaldp.php payment module should function.
Now to further work backwards, I took a look at what other function actually makes a call to "ec_delete_user()". It begins only a few lines down starting at 1770...
if ($kill_sess_vars) {
if (!empty($_SESSION['paypal_ec_temp'])) {
$this->ec_delete_user($_SESSION['customer_id']);
}
// Unregister the paypal session variables, making the user start over.
unset($_SESSION['paypal_ec_temp']);
unset($_SESSION['paypal_ec_token']);
unset($_SESSION['paypal_ec_payer_id']);
unset($_SESSION['paypal_ec_payer_info']);
unset($_SESSION['paypal_ec_final']);
unset($_SESSION['paypal_ec_markflow']);
// debug
$this->zcLog('termEC-1', 'Killed the session vars as requested');
}
I took a look at exactly how $kill_sess_vars could be defined as 'true' and it comes down to another variable called $gateway_mode being passed to the TerminateEC() function call.
So finally I looked at how $gateway_mode is defined and on line 1801 it is defined as...
$gateway_mode = (isset($response['PNREF']) && $response['PNREF'] != '');
I don't really have any understanding as to what the $response['PNREF'] response code from PayPal means, but I'm presuming that it is indeed possible for that response code to come back as defined which leads to a sequence of functions being executed that eventually leads the customer to the session timeout problem.
My best conjecture is that some specific triggers can lead to the PNREF response code from PayPal to unintentionally come back as not NULL which is the root of this problem, and my workaround was to comment out part of the "ec_delete_user()" function, because, as I had explained above, it doesn't appear as if this function has any place in the implementation of this payment module.
Specifically:
if ($kill_sess_vars) {
/* Begin RoboPhung Edit
if (!empty($_SESSION['paypal_ec_temp'])) {
$this->ec_delete_user($_SESSION['customer_id']);
}
End RoboPhung Edit */
// Unregister the paypal session variables, making the user start over.
unset($_SESSION['paypal_ec_temp']);
unset($_SESSION['paypal_ec_token']);
unset($_SESSION['paypal_ec_payer_id']);
unset($_SESSION['paypal_ec_payer_info']);
unset($_SESSION['paypal_ec_final']);
unset($_SESSION['paypal_ec_markflow']);
// debug
$this->zcLog('termEC-1', 'Killed the session vars as requested');
}
So far, this does not appear to have created any issues for my customer's transactions, and I myself, have not been able to trigger any session timeout problems after repeated tests. But of course, and it should go without saying, I should state a disclaimer that you should thoroughly test it out yourself before going "live" with the code change if you have the same problem as me and think that this might help solve it.