[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)

```
<?xml version="1.0"?>
<ncresponse
(...)
ED="1234"
return_url="/payment/confirm?tx_id="123"
SCORING=""
SCO_CATEGORY="G">
</ncresponse>
```

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
This commit is contained in:
Olivier Dony
2018-03-08 17:11:12 +01:00
parent 247f7db088
commit c3769b2290
2 changed files with 6 additions and 2 deletions
+2 -1
View File
@@ -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):
+4 -1
View File
@@ -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({