From c3769b2290df8e9635d2ceed4f05f1ef528e0c22 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 8 Mar 2018 17:11:12 +0100 Subject: [PATCH] [FIX] payment_ogone: work around ingenico API bug As of today, Ingenico platform 4.125 has non-uniform handling of the PARAMPLUS parameters that can be passed as part of transaction metadata. This parameter is documented as being parsed[1] as a series of parameter-value pairs, to be passed as extra parameters to the feedback transaction. Based on this, it seems that the PARAMPLUS value should not be urlencoded globally, but each field value should be urlencoded, as the Ingenico side will have to be able to parse and re-emit these individual parameters. In one case we were missing this urlencoding step, so this commit fixes it. Without this, the querydirect.asp API would return invalid XML data when we retrieve the status of a transaction that used a PARAMPLUS value with an '=' sign! For example with PARAMPLUS passed as return_url=/payment/confirm?tx_id=123 the value returned by querydirect.asp would contain the following: (note the invalid extra quote character in the `return_url` param) ``` ``` Url-encoding the value of the return_url in PARAMPLUS fixes this nonsensical result. However, the Ingenico API then fails to decode the parameter value when passing it to the feedback URL, such as the ACCEPTURL we depend on. As a workaround, since we only pass a single parameter inside PARAMPLUS, we'll url-unquote it afterwards. [1] https://payment-services.ingenico.com/int/en/ogone/support/guides/integration%20guides/e-commerce#feedbackparameters_variablefeedbackparameters --- addons/payment_ogone/controllers/main.py | 3 ++- addons/payment_ogone/models/payment.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/payment_ogone/controllers/main.py b/addons/payment_ogone/controllers/main.py index 8680e99fda5..1d03a688630 100644 --- a/addons/payment_ogone/controllers/main.py +++ b/addons/payment_ogone/controllers/main.py @@ -2,6 +2,7 @@ import logging import pprint import werkzeug +from werkzeug.urls import url_unquote_plus from odoo import http from odoo.http import request @@ -26,7 +27,7 @@ class OgoneController(http.Controller): """ Ogone contacts using GET, at least for accept """ _logger.info('Ogone: entering form_feedback with post data %s', pprint.pformat(post)) # debug request.env['payment.transaction'].sudo().form_feedback(post, 'ogone') - return werkzeug.utils.redirect(post.pop('return_url', '/')) + return werkzeug.utils.redirect(url_unquote_plus(post.pop('return_url', '/'))) @http.route(['/payment/ogone/s2s/create_json'], type='json', auth='public', csrf=False) def ogone_s2s_create_json(self, **kwargs): diff --git a/addons/payment_ogone/models/payment.py b/addons/payment_ogone/models/payment.py index 691bc55c56e..b91acc0eb5d 100644 --- a/addons/payment_ogone/models/payment.py +++ b/addons/payment_ogone/models/payment.py @@ -150,6 +150,9 @@ class PaymentAcquirerOgone(models.Model): def ogone_form_generate_values(self, values): base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') ogone_tx_values = dict(values) + param_plus = { + 'return_url': ogone_tx_values.pop('return_url', False) + } temp_ogone_tx_values = { 'PSPID': self.ogone_pspid, 'ORDERID': values['reference'], @@ -167,7 +170,7 @@ class PaymentAcquirerOgone(models.Model): 'DECLINEURL': urls.url_join(base_url, OgoneController._decline_url), 'EXCEPTIONURL': urls.url_join(base_url, OgoneController._exception_url), 'CANCELURL': urls.url_join(base_url, OgoneController._cancel_url), - 'PARAMPLUS': 'return_url=%s' % ogone_tx_values.pop('return_url') if ogone_tx_values.get('return_url') else False, + 'PARAMPLUS': url_encode(param_plus), } if self.save_token in ['ask', 'always']: temp_ogone_tx_values.update({