From a5bdad89f2c3197b4d99f8a313e588e6a29692e2 Mon Sep 17 00:00:00 2001 From: "Antoine Vandevenne (anv)" Date: Fri, 9 Jul 2021 07:52:57 +0000 Subject: [PATCH] [REM] payment_ogone: remove the FlexCheckout API Before this commit, the FlexCheckout API was used to process validation operations only. It proved itself to be: - unusable without making small payments with immediate refunds - badly suited to PSD2 due to its Merchant Initiated Transactions (MIT) - not worth the maintenance cost tied to its complexity given the simple flow that it implements - inconvenient to integrate to standard payment flows - poorly customizable in regard to the hosted tokenization page This commit thus removes it entirely and drops Ogone's support for validation operations with it. task-2494916 --- addons/payment_ogone/controllers/main.py | 91 +------- addons/payment_ogone/models/const.py | 22 +- .../payment_ogone/models/payment_acquirer.py | 42 +--- .../models/payment_transaction.py | 221 +++++------------- addons/payment_ogone/tests/test_ogone.py | 45 +--- 5 files changed, 83 insertions(+), 338 deletions(-) diff --git a/addons/payment_ogone/controllers/main.py b/addons/payment_ogone/controllers/main.py index c24e52d220d..c74039c1e68 100644 --- a/addons/payment_ogone/controllers/main.py +++ b/addons/payment_ogone/controllers/main.py @@ -1,25 +1,20 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -import base64 import logging import pprint import re -import markupsafe import werkzeug from odoo import _, http from odoo.exceptions import ValidationError from odoo.http import request -from odoo.tools import ustr _logger = logging.getLogger(__name__) class OgoneController(http.Controller): - _hosted_payment_page_return_url = '/payment/ogone/hostedpaymentpage' - _flexcheckout_return_url = '/payment/ogone/flexcheckout' - _directlink_return_url = '/payment/ogone/directlink' + _return_url = '/payment/ogone/return' _backward_compatibility_urls = [ '/payment/ogone/accept', '/payment/ogone/test/accept', '/payment/ogone/decline', '/payment/ogone/test/decline', @@ -31,84 +26,11 @@ class OgoneController(http.Controller): ] # Facilitates the migration of users who registered the URLs in Ogone's backend prior to 14.3 @http.route( - _hosted_payment_page_return_url, type='http', auth='public', methods=['GET', 'POST'], - csrf=False - ) # 'GET' or 'POST' depending on the configuration in Ogone backend - def ogone_return_from_hosted_payment_page(self, **feedback_data): - """ Process the data returned by Ogone after redirection to the Hosted Payment Page. - - :param dict feedback_data: The feedback data - """ - # Check the source and integrity of the data - data = self._homogenize_data(feedback_data) - self._verify_signature(feedback_data, data) - - # Handle the feedback data - data['FEEDBACK_TYPE'] = 'hosted_payment_page' - _logger.info("entering _handle_feedback_data with data:\n%s", pprint.pformat(data)) - request.env['payment.transaction'].sudo()._handle_feedback_data('ogone', data) - return werkzeug.utils.redirect('/payment/status') - - @http.route( - _flexcheckout_return_url, type='http', auth='public', methods=['GET', 'POST'], csrf=False - ) # 'GET' or 'POST' depending on the configuration in Ogone backend - def ogone_return_from_flexcheckout(self, **feedback_data): - """ Process the data returned by Ogone after redirection to Flexcheckout. - - :param dict feedback_data: The feedback data - """ - # Check the source and integrity of the data - data = self._homogenize_data(feedback_data) - self._verify_signature(feedback_data, data) - - # Create a token from the feedback data - data['FEEDBACK_TYPE'] = 'flexcheckout' - _logger.info("entering _handle_feedback_data with data:\n%s", pprint.pformat(data)) - tx_sudo = request.env['payment.transaction'].sudo()._handle_feedback_data('ogone', data) - - # Process the payment through the token - tree = tx_sudo._ogone_send_order_request(request_3ds_authentication=True) - feedback_data = { - 'FEEDBACK_TYPE': 'directlink', - 'ORDERID': tree.get('orderID'), - 'tree': tree, - } - _logger.info( - "entering _handle_feedback_data with data:\n%s", pprint.pformat(feedback_data) - ) - request.env['payment.transaction'].sudo()._handle_feedback_data('ogone', feedback_data) - - # Handle the response - redirect_html_element = tree.find('HTML_ANSWER') - if redirect_html_element: - # Ogone has inserted an HTML_ANSWER element in its response XML tree. This means that a - # redirection to DirectLink's authentication page is required, as FlexCheckout is not - # capable of handling authentications... - # As per the documentation, the HTML must be inserted as-is into the current page, and - # consists of a
bundled with a script to auto-submit the form once its inserted. - # The content of the HTML is not sanitized to preserve the redirection in the script. - # After redirection, the customer comes back to the directlink return URL and we proceed - # with the (now authenticated) payment request. - redirect_html = markupsafe.Markup(ustr(base64.b64decode(redirect_html_element.text))) - return request.render( - 'payment_ogone.directlink_feedback', {'redirect_html': redirect_html} - ) - else: - if tx_sudo.state in ('cancel', 'error'): - tx_sudo.token_id.active = False # The initial payment failed, archive the token - return request.redirect('/payment/status') - - @http.route( - [_directlink_return_url] + _backward_compatibility_urls, type='http', auth='public', + [_return_url] + _backward_compatibility_urls, type='http', auth='public', methods=['GET', 'POST'], csrf=False ) # 'GET' or 'POST' depending on the configuration in Ogone backend - def ogone_return_from_directlink(self, **feedback_data): - """ Process the data returned by Ogone after redirection to Directlink authentication page. - - A redirection to Directlink can happen if a 3DS1 authentication is requested when sending - the request for a new order. This should normally only happen for the first payment of a - token as this is the only case where we specifically request the authentication if necessary - and handle the redirection request if one is returned. + def ogone_return_from_redirect(self, **feedback_data): + """ Process the data returned by Ogone after redirection to the Hosted Payment Page. This route can also accept S2S notifications from Ogone if it is configured as a webhook in Ogone's backend. @@ -120,11 +42,8 @@ class OgoneController(http.Controller): self._verify_signature(feedback_data, data) # Handle the feedback data - data['FEEDBACK_TYPE'] = 'directlink' _logger.info("entering _handle_feedback_data with data:\n%s", pprint.pformat(data)) - tx_sudo = request.env['payment.transaction'].sudo()._handle_feedback_data('ogone', data) - if tx_sudo.state in ('cancel', 'error'): - tx_sudo.token_id.active = False # The initial payment failed, archive the token + request.env['payment.transaction'].sudo()._handle_feedback_data('ogone', data) return request.redirect('/payment/status') def _homogenize_data(self, data): diff --git a/addons/payment_ogone/models/const.py b/addons/payment_ogone/models/const.py index ba900d1737c..b842dfe2354 100644 --- a/addons/payment_ogone/models/const.py +++ b/addons/payment_ogone/models/const.py @@ -1,27 +1,8 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -# See https://epayments-support.ingenico.com/en/integration/all-sales-channels/flexcheckout/guide#flexcheckout_integration_guides_sha_out -FLEXCHECKOUT_KEYS = [ - 'ALIAS.ALIASID', - 'ALIAS.NCERROR', - 'ALIAS.NCERRORCARDNO', - 'ALIAS.NCERRORCN', - 'ALIAS.NCERRORCVC', - 'ALIAS.NCERRORED', - 'ALIAS.ORDERID', - 'ALIAS.STATUS', - 'ALIAS.STOREPERMANENTLY', - 'CARD.BIC', - 'CARD.BIN', - 'CARD.BRAND', - 'CARD.CARDHOLDERNAME', - 'CARD.CARDNUMBER', - 'CARD.CVC', - 'CARD.EXPIRYDATE' -] # See https://epayments-support.ingenico.com/en/integration-solutions/integrations/directlink#directlink_integration_guides_request_a_new_order # See https://epayments-support.ingenico.com/en/integration-solutions/integrations/directlink#directlink_integration_guides_order_response -DIRECTLINK_KEYS = [ +VALID_KEYS = [ 'AAVADDRESS', 'AAVCHECK', 'AAVMAIL', @@ -86,7 +67,6 @@ DIRECTLINK_KEYS = [ 'TRXDATE', 'VC', ] -VALID_KEYS = DIRECTLINK_KEYS + FLEXCHECKOUT_KEYS # See https://epayments-support.ingenico.com/en/get-started/transaction-status-full/ diff --git a/addons/payment_ogone/models/payment_acquirer.py b/addons/payment_ogone/models/payment_acquirer.py index dd4da827084..630dffd6af3 100644 --- a/addons/payment_ogone/models/payment_acquirer.py +++ b/addons/payment_ogone/models/payment_acquirer.py @@ -5,7 +5,7 @@ from hashlib import sha1 import requests -from odoo import _, fields, models +from odoo import _, api, fields, models from odoo.exceptions import ValidationError from .const import VALID_KEYS @@ -31,37 +31,22 @@ class PaymentAcquirer(models.Model): ogone_shakey_out = fields.Char( string="SHA Key OUT", size=32, required_if_provider='ogone', groups='base.group_system') - def _get_validation_amount(self): - """ Override of payment to return the amount for Ogone validation operations. + @api.model + def _get_compatible_acquirers(self, *args, is_validation=False, **kwargs): + """ Override of payment to unlist Ogone acquirers for validation operations. """ + acquirers = super()._get_compatible_acquirers(*args, is_validation=is_validation, **kwargs) - :return: The validation amount - :rtype: float - """ - res = super()._get_validation_amount() - if self.provider != 'ogone': - return res + if is_validation: + acquirers = acquirers.filtered(lambda a: a.provider != 'ogone') - return 1.0 - - def _get_redirect_form_view(self, is_validation=False): - """ Override of payment to return the FlexCheckout form for validation operations. - - :param bool is_validation: Whether the operation is a validation - :return: The redirect form template - :rtype: record of `ir.ui.view` - """ - res = super()._get_redirect_form_view() - if self.provider != 'ogone' or not is_validation: - return res # self.redirect_form_view_id - - return self.env.ref('payment_ogone.redirect_form_validation') + return acquirers def _ogone_get_api_url(self, api_key): """ Return the appropriate URL of the requested API for the acquirer state. Note: self.ensure_one() - :param str api_key: The API whose URL to get: 'flexcheckout' or 'directlink' + :param str api_key: The API whose URL to get: 'hosted_payment_page' or 'directlink' :return: The API URL :rtype: str """ @@ -70,16 +55,12 @@ class PaymentAcquirer(models.Model): if self.state == 'enabled': api_urls = { 'hosted_payment_page': 'https://secure.ogone.com/ncol/prod/orderstandard_utf8.asp', - 'flexcheckout': 'https://secure.ogone.com/Tokenization/HostedPage', 'directlink': 'https://secure.ogone.com/ncol/prod/orderdirect_utf8.asp', - 'maintenancedirect': 'https://secure.ogone.com/ncol/prod/maintenancedirect_utf8.asp', } else: # 'test' api_urls = { 'hosted_payment_page': 'https://ogone.test.v-psp.com/ncol/test/orderstandard_utf8.asp', - 'flexcheckout': 'https://ogone.test.v-psp.com/Tokenization/HostedPage', 'directlink': 'https://ogone.test.v-psp.com/ncol/test/orderdirect_utf8.asp', - 'maintenancedirect': 'https://ogone.test.v-psp.com/ncol/test/maintenancedirect_utf8.asp', } return api_urls.get(api_key) @@ -110,12 +91,11 @@ class PaymentAcquirer(models.Model): shasign = sha1(signing_string.encode()).hexdigest() return shasign - def _ogone_make_request(self, api_key, payload=None, method='POST'): + def _ogone_make_request(self, payload=None, method='POST'): """ Make a request to one of Ogone APIs. Note: self.ensure_one() - :param str api_key: The API to which the request is made: 'flexcheckout' or 'directlink' :param dict payload: The payload of the request :param str method: The HTTP method of the request :return The content of the response @@ -124,7 +104,7 @@ class PaymentAcquirer(models.Model): """ self.ensure_one() - url = self._ogone_get_api_url(api_key) + url = self._ogone_get_api_url('directlink') try: response = requests.request(method, url, data=payload, timeout=60) response.raise_for_status() diff --git a/addons/payment_ogone/models/payment_transaction.py b/addons/payment_ogone/models/payment_transaction.py index 6a60f048b24..cce902281fa 100644 --- a/addons/payment_ogone/models/payment_transaction.py +++ b/addons/payment_ogone/models/payment_transaction.py @@ -61,57 +61,37 @@ class PaymentTransaction(models.Model): if self.acquirer_id.provider != 'ogone': return res - base_url = self.acquirer_id.get_base_url() - if self.operation == 'online_redirect': - return_url = urls.url_join(base_url, OgoneController._hosted_payment_page_return_url) - rendering_values = { - 'PSPID': self.acquirer_id.ogone_pspid, - 'ORDERID': self.reference, - 'AMOUNT': payment_utils.to_minor_currency_units(self.amount, None, 2), - 'CURRENCY': self.currency_id.name, - 'LANGUAGE': self.partner_lang or 'en_US', - 'EMAIL': self.partner_email or '', - 'OWNERADDRESS': self.partner_address or '', - 'OWNERZIP': self.partner_zip or '', - 'OWNERTOWN': self.partner_city or '', - 'OWNERCTY': self.partner_country_id.code or '', - 'OWNERTELNO': self.partner_phone or '', - 'OPERATION': 'SAL', # direct sale - 'USERID': self.acquirer_id.ogone_userid, - 'ACCEPTURL': return_url, - 'DECLINEURL': return_url, - 'EXCEPTIONURL': return_url, - 'CANCELURL': return_url, - } - if self.tokenize: - rendering_values.update({ - 'ALIAS': payment_utils.singularize_reference_prefix(prefix='ODOO-ALIAS'), - 'ALIASUSAGE': _("Storing your payment details is necessary for future use."), - }) + return_url = urls.url_join(self.acquirer_id.get_base_url(), OgoneController._return_url) + rendering_values = { + 'PSPID': self.acquirer_id.ogone_pspid, + 'ORDERID': self.reference, + 'AMOUNT': payment_utils.to_minor_currency_units(self.amount, None, 2), + 'CURRENCY': self.currency_id.name, + 'LANGUAGE': self.partner_lang or 'en_US', + 'EMAIL': self.partner_email or '', + 'OWNERADDRESS': self.partner_address or '', + 'OWNERZIP': self.partner_zip or '', + 'OWNERTOWN': self.partner_city or '', + 'OWNERCTY': self.partner_country_id.code or '', + 'OWNERTELNO': self.partner_phone or '', + 'OPERATION': 'SAL', # direct sale + 'USERID': self.acquirer_id.ogone_userid, + 'ACCEPTURL': return_url, + 'DECLINEURL': return_url, + 'EXCEPTIONURL': return_url, + 'CANCELURL': return_url, + } + if self.tokenize: rendering_values.update({ - 'SHASIGN': self.acquirer_id._ogone_generate_signature( - rendering_values, incoming=False - ).upper(), - 'api_url': self.acquirer_id._ogone_get_api_url('hosted_payment_page'), - }) - else: # validation - return_url = urls.url_join(base_url, OgoneController._flexcheckout_return_url) - rendering_values = { - 'ACCOUNT_PSPID': self.acquirer_id.ogone_pspid, - 'ALIAS_ALIASID': payment_utils.singularize_reference_prefix(prefix='ODOO-ALIAS'), - 'ALIAS_ORDERID': self.reference, - 'ALIAS_STOREPERMANENTLY': 'Y' if self.tokenize else 'N', - 'CARD_PAYMENTMETHOD': 'CreditCard', - 'LAYOUT_LANGUAGE': self.partner_lang, - 'PARAMETERS_ACCEPTURL': return_url, - 'PARAMETERS_EXCEPTIONURL': return_url, - } - rendering_values.update({ - 'SHASIGNATURE_SHASIGN': self.acquirer_id._ogone_generate_signature( - rendering_values, incoming=False, format_keys=True - ).upper(), - 'api_url': self.acquirer_id._ogone_get_api_url('flexcheckout'), + 'ALIAS': payment_utils.singularize_reference_prefix(prefix='ODOO-ALIAS'), + 'ALIASUSAGE': _("Storing your payment details is necessary for future use."), }) + rendering_values.update({ + 'SHASIGN': self.acquirer_id._ogone_generate_signature( + rendering_values, incoming=False + ).upper(), + 'api_url': self.acquirer_id._ogone_get_api_url('hosted_payment_page'), + }) return rendering_values def _send_payment_request(self): @@ -129,25 +109,8 @@ class PaymentTransaction(models.Model): if not self.token_id: raise UserError("Ogone: " + _("The transaction is not linked to a token.")) - tree = self._ogone_send_order_request() - feedback_data = { - 'FEEDBACK_TYPE': 'directlink', - 'ORDERID': tree.get('orderID'), - 'tree': tree, - } - _logger.info("entering _handle_feedback_data with data:\n%s", pprint.pformat(feedback_data)) - self._handle_feedback_data('ogone', feedback_data) - - def _ogone_send_order_request(self, request_3ds_authentication=False): - """ Make a new order request to Ogone and return the lxml etree parsed from the response. - - :param bool request_3ds_authentication: Whether a 3DS authentication should be requested if - necessary to process the payment - :return: The lxml etree - :raise: ValidationError if the response can not be parsed to an lxml etree - """ + # Make the payment request base_url = self.acquirer_id.get_base_url() - return_url = urls.url_join(base_url, OgoneController._directlink_return_url) data = { # DirectLink parameters 'PSPID': self.acquirer_id.ogone_pspid, @@ -166,14 +129,8 @@ class PaymentTransaction(models.Model): 'OPERATION': 'SAL', # direct sale # Alias Manager parameters 'ALIAS': self.token_id.acquirer_ref, - 'ALIASPERSISTEDAFTERUSE': 'Y' if self.token_id.active else 'N', + 'ALIASPERSISTEDAFTERUSE': 'Y', 'ECI': 9, # Recurring (from eCommerce) - # 3DS parameters - 'ACCEPTURL': return_url, - 'DECLINEURL': return_url, - 'EXCEPTIONURL': return_url, - 'LANGUAGE': self.partner_lang or 'en_US', - 'FLAG3D': 'Y' if request_3ds_authentication else 'N', } data['SHASIGN'] = self.acquirer_id._ogone_generate_signature(data, incoming=False) @@ -181,16 +138,20 @@ class PaymentTransaction(models.Model): "making payment request:\n%s", pprint.pformat({k: v for k, v in data.items() if k != 'PSWD'}) ) # Log the payment request data without the password - response_content = self.acquirer_id._ogone_make_request('directlink', data) + response_content = self.acquirer_id._ogone_make_request(data) try: tree = objectify.fromstring(response_content) except etree.XMLSyntaxError: raise ValidationError("Ogone: " + "Received badly structured response from the API.") + + # Handle the feedback data _logger.info( "received payment request response as an etree:\n%s", etree.tostring(tree, pretty_print=True, encoding='utf-8') ) - return tree + feedback_data = {'ORDERID': tree.get('orderID'), 'tree': tree} + _logger.info("entering _handle_feedback_data with data:\n%s", pprint.pformat(feedback_data)) + self._handle_feedback_data('ogone', feedback_data) @api.model def _get_tx_from_feedback_data(self, provider, data): @@ -221,111 +182,49 @@ class PaymentTransaction(models.Model): :param dict data: The feedback data sent by the provider :return: None - :raise: ValidationError if inconsistent data were received """ super()._process_feedback_data(data) if self.provider != 'ogone': return - feedback_type = data.get('FEEDBACK_TYPE') - if feedback_type == 'flexcheckout': - self._ogone_tokenize_from_feedback_data( - data.get('CARDNUMBER'), - data['ALIASID'], - not self.tokenize, # Immediately archive the token if it was not requested - ) - elif feedback_type in ('hosted_payment_page', 'directlink'): - if 'tree' in data: - data = data['tree'] + if 'tree' in data: + data = data['tree'] - self.acquirer_reference = data.get('PAYID') - payment_status = int(data.get('STATUS', '0')) - if payment_status in const.PAYMENT_STATUS_MAPPING['pending']: - self._set_pending() - elif payment_status in const.PAYMENT_STATUS_MAPPING['done']: - has_token_data = 'ALIAS' in data - if self.tokenize and has_token_data: - self._ogone_tokenize_from_feedback_data( - data.get('CARDNO'), data['ALIAS'], False - ) - if self.token_id: - self.token_id.verified = True # Validity of the token has been confirmed - self._set_done() - elif payment_status in const.PAYMENT_STATUS_MAPPING['cancel']: - self._set_canceled() - else: # Classify unknown payment statuses as `error` tx state - _logger.info("received data with invalid payment status: %s", payment_status) - self._set_error( - "Ogone: " + _("Received data with invalid payment status: %s", payment_status) - ) - else: - raise ValidationError( - "Ogone: " + _("Received feedback data with unknown type: %s", feedback_type) + self.acquirer_reference = data.get('PAYID') + payment_status = int(data.get('STATUS', '0')) + if payment_status in const.PAYMENT_STATUS_MAPPING['pending']: + self._set_pending() + elif payment_status in const.PAYMENT_STATUS_MAPPING['done']: + has_token_data = 'ALIAS' in data + if self.tokenize and has_token_data: + self._ogone_tokenize_from_feedback_data(data) + self._set_done() + elif payment_status in const.PAYMENT_STATUS_MAPPING['cancel']: + self._set_canceled() + else: # Classify unknown payment statuses as `error` tx state + _logger.info("received data with invalid payment status: %s", payment_status) + self._set_error( + "Ogone: " + _("Received data with invalid payment status: %s", payment_status) ) - def _ogone_tokenize_from_feedback_data(self, card_number, acquirer_ref, is_one_shot_payment): + def _ogone_tokenize_from_feedback_data(self, data): """ Create a token from feedback data. - :param str card_number: The obfuscated number of the card - :param str acquirer_ref: The acquirer reference of the payment - :param bool is_one_shot_payment: Whether the token was created for a one-shot payment + :param dict data: The feedback data sent by the provider :return: None """ - token_name = card_number or payment_utils.build_token_name() # Not requested in the backend + token_name = data.get('CARDNO') or payment_utils.build_token_name() token = self.env['payment.token'].create({ 'acquirer_id': self.acquirer_id.id, 'name': token_name, # Already padded with 'X's 'partner_id': self.partner_id.id, - 'acquirer_ref': acquirer_ref, - 'verified': False, # Set to True as soon as a payment is authorized - 'active': not is_one_shot_payment, # Archive immediately if used for one-shot payment + 'acquirer_ref': data['ALIAS'], + 'verified': True, # The payment is authorized, so the payment method is valid }) self.write({ 'token_id': token.id, 'tokenize': False, }) - - def _send_refund_request(self): - """ Override of payment to send a refund request to Authorize. - - Note: self.ensure_one() - - :return: None - :raise: ValidationError if a badly structured response is received - """ - super()._send_refund_request() - if self.provider != 'ogone': - return - - data = { - 'PSPID': self.acquirer_id.ogone_pspid, - 'ORDERID': self.reference, - 'PAYID': self.acquirer_reference, - 'USERID': self.acquirer_id.ogone_userid, - 'PSWD': self.acquirer_id.ogone_password, - 'AMOUNT': payment_utils.to_minor_currency_units(self.amount, None, 2), - 'CURRENCY': self.currency_id.name, - 'OPERATION': 'RFS', # refund - } - data['SHASIGN'] = self.acquirer_id._ogone_generate_signature(data, incoming=False) - _logger.info( - "making refund request:\n%s", - pprint.pformat({k: v for k, v in data.items() if k != 'PSWD'}) - ) # Log the refund request data without the password - response_content = self.acquirer_id._ogone_make_request('maintenancedirect', data) - try: - tree = objectify.fromstring(response_content) - except etree.XMLSyntaxError: - raise ValidationError("Ogone: " + "Received badly structured response from the API.") - _logger.info( - "received refund request response as an etree:\n%s", - etree.tostring(tree, pretty_print=True, encoding='utf-8') + "created token with id %s for partner with id %s", token.id, self.partner_id.id ) - feedback_data = { - 'FEEDBACK_TYPE': 'directlink', - 'ORDERID': tree.get('orderID'), - 'tree': tree, - } - _logger.info("entering _handle_feedback_data with data:\n%s", pprint.pformat(feedback_data)) - self._handle_feedback_data('ogone', feedback_data) diff --git a/addons/payment_ogone/tests/test_ogone.py b/addons/payment_ogone/tests/test_ogone.py index 99520f6157b..e45c095f6b0 100644 --- a/addons/payment_ogone/tests/test_ogone.py +++ b/addons/payment_ogone/tests/test_ogone.py @@ -15,9 +15,11 @@ from ..controllers.main import OgoneController @tagged('post_install', '-at_install') class OgoneTest(OgoneCommon): - def test_validation_amount(self): - """ Test the value of the validation amount. """ - self.assertEqual(self.ogone._get_validation_amount(), 1.0) + def test_incompatibility_with_validation_operation(self): + acquirers = self.env['payment.acquirer']._get_compatible_acquirers( + self.company.id, self.partner.id, is_validation=True + ) + self.assertNotIn(self.ogone, acquirers) @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior def test_reference_is_singularized(self): @@ -49,7 +51,7 @@ class OgoneTest(OgoneCommon): @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior def test_redirect_form_values(self): """ Test the values of the redirect form inputs for online payments. """ - return_url = self._build_url(OgoneController._hosted_payment_page_return_url) + return_url = self._build_url(OgoneController._return_url) expected_values = { 'PSPID': self.ogone.ogone_pspid, 'ORDERID': self.reference, @@ -94,38 +96,3 @@ class OgoneTest(OgoneCommon): value, f"received value {inputs[form_key]} for input {form_key} (expected {value})" ) - - @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior - def test_redirect_form_validation_values(self): - """ Test the values of the redirect form inputs for validation. """ - return_url = self._build_url(OgoneController._flexcheckout_return_url) - expected_values = { - 'ACCOUNT_PSPID': self.ogone.ogone_pspid, - 'ALIAS_ALIASID': payment_utils.singularize_reference_prefix(prefix='ODOO-ALIAS'), - 'ALIAS_ORDERID': self.reference, - 'ALIAS_STOREPERMANENTLY': 'N', # 'Y' if self.tokenize - 'CARD_PAYMENTMETHOD': 'CreditCard', - 'LAYOUT_LANGUAGE': self.partner.lang, - 'PARAMETERS_ACCEPTURL': return_url, - 'PARAMETERS_EXCEPTIONURL': return_url, - } - expected_values['SHASIGNATURE_SHASIGN'] = self.ogone._ogone_generate_signature( - expected_values, incoming=False, format_keys=True - ).upper() - - tx = self.create_transaction(flow='dummy', operation='validation') - with mute_logger('odoo.addons.payment.models.payment_transaction'): - processing_values = tx._get_processing_values() - - form_info = self._extract_values_from_html_form(processing_values['redirect_form_html']) - - self.assertEqual(form_info['action'], 'https://ogone.test.v-psp.com/Tokenization/HostedPage') - inputs = form_info['inputs'] - self.assertEqual(len(expected_values), len(inputs)) - for rendering_key, value in expected_values.items(): - form_key = rendering_key.replace('_', '.') - self.assertEqual( - inputs[form_key], - value, - f"received value {inputs[form_key]} for input {form_key} (expected {value})" - )