When buying a product on website shop, after the payment with SIPS, the
page is redirected to an Error message: "We are not able to find your
payment, but don't worry. You should receive an email confirming your
payment in a few minutes. If the payment hasn't been confirmed you can
contact us."
To reproduce the error:
1. In Payment Acquirers, enable Sips
2. Go on website shop
3. Add a product to the cart, Checkout
4. Pay with Sips
- Visa card number: 4100000000000000
5. Back to Web-shop, if the payment has been successfully processed,
repeat steps 2 -> 4
Error: The message "Your payment has been successfully processed. Thank
you!" is not displayed. Instead, the message "We are not able [...] you
can contact us." is displayed.
This message is displayed when:
https://github.com/odoo/odoo/blob/5945806c151b13d9d4cc13aa0a6c96a6b1bbad5f/addons/payment/controllers/portal.py#L65-L69
i.e., when the transactions list is empty. Here is how to get the list:
https://github.com/odoo/odoo/blob/5945806c151b13d9d4cc13aa0a6c96a6b1bbad5f/addons/payment/controllers/portal.py#L38-L42
It uses the session of the request. The cookie `session_id` is used to
identify the current session. However, after the payment on SIPS, the
page is redirected to `/payment/sips/dpn` with a POST request. Since the
session cookie has the attribute `SameSite=Lax` and the HTTP request is
a POST, the cookie will be filtered out:
https://drive.google.com/file/d/1xfx3YWkfonO3nK-8Rew45uSoR4lkpjpY/view?usp=sharing
(Browser information: This cookie didn't specify a "SameSite" attribute
when it was stored and was defaulted to "SameSite=Lax," and was blocked
because the request was made from a different site and was not initiated
by a top-level navigation. The cookie had to have been set with
"SameSite=None" to enable cross-site usage)
As a result, the server creates a new one. This is the reason why the
transactions list is empty: the list is based on a new session.
Adding the attribute `save_session = False` to the route will prevent
the server from creating a new session cookie and add it in the POST
response.
OPW-2518377
closes odoo/odoo#72611
X-original-commit: 9637a287923c6b82acfd487ed32d6bbc1fdf74b6
Signed-off-by: Antoine Vandevenne (anv) <AntoineVDV@users.noreply.github.com>
Signed-off-by: Adrien Widart <adwid@users.noreply.github.com>
64 lines
2.8 KiB
Python
64 lines
2.8 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
# Original Copyright 2015 Eezee-It, modified and maintained by Odoo.
|
|
|
|
import logging
|
|
import pprint
|
|
|
|
import werkzeug
|
|
|
|
from odoo import http
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.http import request
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class SipsController(http.Controller):
|
|
_return_url = '/payment/sips/dpn/'
|
|
_notify_url = '/payment/sips/ipn/'
|
|
|
|
@http.route(_return_url, type='http', auth='public', methods=['POST'], csrf=False, save_session=False)
|
|
def sips_dpn(self, **post):
|
|
""" Sips DPN
|
|
The session cookie created by Odoo has not the attribute SameSite. Most of browsers will force this attribute
|
|
with the value 'Lax'. After the payment, Sips will perform a POST request on this route. For all these reasons,
|
|
the cookie won't be added to the request. As a result, if we want to save the session, the server will create
|
|
a new session cookie. Therefore, the previous session and all related information will be lost, so it will lead
|
|
to undesirable behaviors. This is the reason why `save_session=False` is needed.
|
|
"""
|
|
_logger.info("beginning Sips DPN _handle_feedback_data with data %s", pprint.pformat(post))
|
|
try:
|
|
if self._sips_validate_data(post):
|
|
request.env['payment.transaction'].sudo()._handle_feedback_data('sips', post)
|
|
except ValidationError:
|
|
pass
|
|
return werkzeug.utils.redirect('/payment/status')
|
|
|
|
@http.route(_notify_url, type='http', auth='public', methods=['POST'], csrf=False)
|
|
def sips_ipn(self, **post):
|
|
""" Sips IPN. """
|
|
_logger.info("beginning Sips IPN _handle_feedback_data with data %s", pprint.pformat(post))
|
|
if not post:
|
|
# SIPS sometimes sends empty notifications, the reason why is unclear but they tend to
|
|
# pollute logs and do not provide any meaningful information; log as a warning instead
|
|
# of a traceback.
|
|
_logger.warning("received empty notification; skip.")
|
|
else:
|
|
try:
|
|
if self._sips_validate_data(post):
|
|
request.env['payment.transaction'].sudo()._handle_feedback_data('sips', post)
|
|
except ValidationError:
|
|
pass # Acknowledge the notification to avoid getting spammed
|
|
return ''
|
|
|
|
def _sips_validate_data(self, post):
|
|
tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_feedback_data('sips', post)
|
|
acquirer_sudo = tx_sudo.acquirer_id
|
|
security = acquirer_sudo._sips_generate_shasign(post['Data'])
|
|
if security == post['Seal']:
|
|
_logger.debug('validated data')
|
|
return True
|
|
else:
|
|
_logger.warning('data are tampered')
|
|
return False
|