Post by joeantropy » Tue Sep 22, 2020 6:40 pm

Hi all,

I'm looking into a puzzling bug we've had on a number of client websites recently and was wondering if anyone had any insight.
It's a classic case of orders not being properly taken out of Missing Orders upon payment callback, and looks to be something to do with the user's session expiring while they are on the payment page.


It usually goes more or less along these lines:

1) OpenCart sets the order_id in $this->session->data before passing control over to the payment extension.
2) The user's OpenCart session somehow expires or otherwise "gets reset" while they're on the payment page.
3) Pretty much every payment extension uses $this->session->data['order_id'] with $this->model_checkout_order->addOrderHistory to confirm an order in the callback routine. If this isn't found, addOrderHistory is called with an empty order_id, resulting in a Missing Order.
4) Chaos ensues!


I've verified this with extensive logging code added to the payment ext.s to detail every step of the checkout process. If it finds no order_id in $this->session->data in the callback function it prints the entire session data array, which is empty except for "language" and "currency", suggesting a new blank session.

Also several instances of "undefined index: order_id" in the OC error.log, with the filename and line number corresponding with an addOrderHistory($this->session->data['order_id'], ...) line in the payment extension controller.


We've seen this problem on sites running OC versions 1.5 and 2.x which uses PHP's built-in session wrangler. Version 3 seems unaffected since it uses the database for session management (backporting this to OC1+2 might be a good idea). Each site we've encountered this issue on uses a different payment provider, so it's not limited to one extension.

Sometimes it's possible to edit the relevant bits of the extension so it doesn't rely on session->data to put through an order, but usually this is impossible without e.g. anybody being able to hit the relevant URL and put through an order without paying (not enough data sent from the payment gateway in the callback to verify it's a legit request!). I've also cranked up the session lifetime on servers of affected sites but I'm not confident this will clear up the issue for good.


I was wondering if anyone's seen anything similar, missing orders or other glitches caused by sessions prematurely expiring? We've suddenly seen this cropping up a lot in the last couple of months, so I'm wondering if it's a recent change in how web browsers handle cookies, or a recent new version of PHP/apache/whatever that has subtly altered how sessions are handled and gc'd on the server side.

Thanks for reading, any insight or comments appreciated.

User avatar
Newbie

Posts

Joined
Mon Mar 02, 2020 10:19 pm

Post by ADD Creative » Wed Sep 23, 2020 1:05 am

It looks very much like the new cookie SameSite behaviour implemented in modern web browsers where Lax is the new default.
https://www.chromium.org/updates/same-site

With the new default of Lax, any payment gateway returning to your site whis a POST will not have the session cookie and therefore the session will be lost. The best way around this is to change how the payment module works (such as https://github.com/opencart/opencart/pull/8072), but as you have found this is not always possible.

Next option would be to set the session cookie to have the SameSite=None and Secure attributes. This would however lose the security advantages on the new behaviour.

For OpenCart 1.5.x, if you are using PHP 7.3+ then set the following in your php,ini or user.ini.

Code: Select all

session.cookie_secure=On
session.cookie_samesite="None"
For OpenCart 2.x you would also need to make the following changes to setting of the session cookie.
viewtopic.php?f=190&t=216579&start=20#p782590

For OpenCart 3.x it would be as follows.
viewtopic.php?f=202&t=219633#p797082

For PHP 7.2 and below you would have to inject the SameSite attributes into one of the other attributes, as done in this example.
viewtopic.php?f=202&t=219633#p797043

Your 1.5.x sites would have to use HTTPS everywhere.

There are also more changes coming (Chrome 88?) which could affect site that aren't HTTPS everywhere or are badly configured.
https://www.chromestatus.com/feature/5096179480133632

www.add-creative.co.uk


Guru Member

Posts

Joined
Sat Jan 14, 2012 1:02 am
Location - United Kingdom

Post by paulfeakins » Wed Sep 23, 2020 6:14 pm

Thanks very much for the above, ADD Creative as we've seen this issue cropping up recently on a few sites.

UK OpenCart Hosting | OpenCart Audits | OpenCart Support - please email info@antropy.co.uk


User avatar
Legendary Member
Online

Posts

Joined
Mon Aug 22, 2011 11:01 pm
Location - London Gatwick, United Kingdom

Post by joeantropy » Fri Sep 25, 2020 11:44 pm

Many thanks for your reply - we've applied those fixes to a couple of OpenCart 2.x websites and haven't seen any missing order issues since, so it looks like this was it! This has been a real head-scratcher recently, so thanks again!

We've packaged this fix as an extension for OpenCart 2.x in case anyone else is experiencing the same problem on their store:
https://www.opencart.com/index.php?rout ... n_id=40446

User avatar
Newbie

Posts

Joined
Mon Mar 02, 2020 10:19 pm

Post by hounw » Tue Nov 03, 2020 1:44 am

THANKS! I've been scratching my head with this issue for months...

I'll see if I can figure out a way around this for our specific situation...
ADD Creative wrote:
Wed Sep 23, 2020 1:05 am
It looks very much like the new cookie SameSite behaviour implemented in modern web browsers where Lax is the new default.
https://www.chromium.org/updates/same-site

With the new default of Lax, any payment gateway returning to your site whis a POST will not have the session cookie and therefore the session will be lost. The best way around this is to change how the payment module works (such as https://github.com/opencart/opencart/pull/8072), but as you have found this is not always possible.

Next option would be to set the session cookie to have the SameSite=None and Secure attributes. This would however lose the security advantages on the new behaviour.

For OpenCart 1.5.x, if you are using PHP 7.3+ then set the following in your php,ini or user.ini.

Code: Select all

session.cookie_secure=On
session.cookie_samesite="None"
For OpenCart 2.x you would also need to make the following changes to setting of the session cookie.
viewtopic.php?f=190&t=216579&start=20#p782590

For OpenCart 3.x it would be as follows.
viewtopic.php?f=202&t=219633#p797082

For PHP 7.2 and below you would have to inject the SameSite attributes into one of the other attributes, as done in this example.
viewtopic.php?f=202&t=219633#p797043

Your 1.5.x sites would have to use HTTPS everywhere.

There are also more changes coming (Chrome 88?) which could affect site that aren't HTTPS everywhere or are badly configured.
https://www.chromestatus.com/feature/5096179480133632

Newbie

Posts

Joined
Tue Nov 03, 2020 1:41 am
Who is online

Users browsing this forum: No registered users and 54 guests