Skip to content
Snippets Groups Projects
Commit 0e29f948 authored by Loan (LSE)'s avatar Loan (LSE)
Browse files

[FIX] payment_payulatam: Adapt rounding method if webhook

Before this commit:
 If a payulatam payment is received from the confirmation
 page (so, with the webhook). If the value have some decimals
 it might be rounded in the wrong way.
 As such, the generated signature to compare with is wrong
 and the payment validation cancelled

After this commit
 If we cross compare the signature generation documentation:
 https://developers.payulatam.com/latam/en/docs/integrations/webcheckout-integration/response-page.html#signature-validation
 https://developers.payulatam.com/latam/en/docs/integrations/webcheckout-integration/confirmation-page.html#signature-validation


 We notice that the `new_value` computation is slightly different
 depending on the return.
 The one we currently use for both method is the "return"
 one which is computed differently from the "confirm" one.

 With this change of code a "confirmation" page payment
 will be validated as intended.

I also changed the log level from warning to exception
so that the traceback and exception message is logged.
Before this commit there was just a generic warning message

opw-3018628

closes odoo/odoo#113768

Signed-off-by: default avatarLoan (LSE) <lse@odoo.com>
Signed-off-by: default avatarAntoine Vandevenne (anv) <anv@odoo.com>
parent 70f61994
Branches
Tags
No related merge requests found
......@@ -45,9 +45,10 @@ class PayuLatamController(http.Controller):
}
try:
request.env['payment.transaction'].sudo()._handle_feedback_data('payulatam', data)
request.env['payment.transaction'].sudo().with_context(payulatam_is_confirmation_page=True)\
._handle_feedback_data('payulatam', data)
except ValidationError:
_logger.warning(
_logger.exception(
'An error occurred while handling the confirmation from PayU with data:\n%s',
pprint.pformat(data))
return http.Response(status=200)
......@@ -3,7 +3,7 @@
from hashlib import md5
from odoo import api, fields, models
from odoo.tools.float_utils import float_repr
from odoo.tools.float_utils import float_split, float_repr
SUPPORTED_CURRENCIES = ('ARS', 'BRL', 'CLP', 'COP', 'MXN', 'PEN', 'USD')
......@@ -46,16 +46,27 @@ class PaymentAcquirer(models.Model):
:rtype: str
"""
if incoming:
# "Confirmation" and "Response" pages have a different way to calculate what they call the `new_value`
if self.env.context.get('payulatam_is_confirmation_page'):
# https://developers.payulatam.com/latam/en/docs/integrations/webcheckout-integration/confirmation-page.html#signature-validation
# For confirmation page, PayU Latam round to the first digit if the second one is a zero
# to generate their signature.
# e.g:
# 150.00 -> 150.0
# 150.26 -> 150.26
# This happens to be Python 3's default behavior when casting to `float`.
new_value = "%d.%d" % float_split(float(values.get('TX_VALUE')), 2)
else:
# https://developers.payulatam.com/latam/en/docs/integrations/webcheckout-integration/response-page.html#signature-validation
# PayU Latam use the "Round half to even" rounding method
# to generate their signature. This happens to be Python 3's
# default rounding method.
new_value = float_repr(float(values.get('TX_VALUE')), 1)
data_string = '~'.join([
self.payulatam_api_key,
self.payulatam_merchant_id,
values['referenceCode'],
# http://developers.payulatam.com/en/web_checkout/integration.html
# Section: 2. Response page > Signature validation
# PayU Latam use the "Round half to even" rounding method
# to generate their signature. This happens to be Python 3's
# default rounding method.
float_repr(float(values.get('TX_VALUE')), 1),
new_value,
values['currency'],
values.get('transactionState'),
])
......
......@@ -31,6 +31,9 @@ class PayULatamTest(PayULatamCommon, HttpCase):
'value': str(cls.amount)
}
cls.payulatam_post_confirmation_approved_data_webhook = cls.payulatam_post_confirmation_approved_data.copy()
cls.payulatam_post_confirmation_approved_data_webhook["sign"] = 'e227f90e64808320953dbbcb5ee96c9f'
def test_compatibility_with_supported_currencies(self):
""" Test that the PayULatam acquirer is compatible with all supported currencies. """
for supported_currency_code in SUPPORTED_CURRENCIES:
......@@ -168,7 +171,7 @@ class PayULatamTest(PayULatamCommon, HttpCase):
self.assertEqual(tx.state, 'draft')
res = self.url_open(PayuLatamController._webhook_url,
self.payulatam_post_confirmation_approved_data)
self.payulatam_post_confirmation_approved_data_webhook)
self.assertEqual(res.status_code, 200, 'Should be OK')
self.assertEqual(res.text, '', "Body should be empty")
self.assertEqual(tx.state, 'done')
......@@ -194,7 +197,7 @@ class PayULatamTest(PayULatamCommon, HttpCase):
post_data = self.payulatam_post_confirmation_approved_data
post_data['state_pol'] = '6'
post_data['response_message_pol'] = 'DECLINED'
post_data['sign'] = '98af78d27847dcb5120b1dabd9208a43'
post_data['sign'] = '28a1a45b1362a4096cf71357204e0256'
res = self.url_open(PayuLatamController._webhook_url,
post_data)
self.assertEqual(res.status_code, 200, 'Should be OK')
......@@ -209,7 +212,7 @@ class PayULatamTest(PayULatamCommon, HttpCase):
post_data = self.payulatam_post_confirmation_approved_data
post_data['state_pol'] = '5'
post_data['response_message_pol'] = 'EXPIRED'
post_data['sign'] = 'bde4704e76963d2a8cb6f7bce84b1391'
post_data['sign'] = '4d43432f81d68c046a14d44fa7e235da'
res = self.url_open(PayuLatamController._webhook_url,
post_data)
self.assertEqual(res.status_code, 200, 'Should be OK')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment