From aa343d17f700d33b4e11b3ee9bb3b9b2b0353874 Mon Sep 17 00:00:00 2001 From: Joren Van Onder Date: Thu, 13 Feb 2020 18:40:46 +0000 Subject: [PATCH] [FIX] payment_authorize: always send an amount with the correct decimals We cannot assume reading the value of a monetary field has the decimals specified by the currency in decimal_places. Right after creating a record with a monetary field it may have a different amount of decimals. To reproduce this: >>> tx = env['payment.transaction'].create({ 'amount': 10.87, 'acquirer_id': env['payment.acquirer'].search([], limit=1).id, 'currency_id': env.ref('base.USD').id, 'reference': 'test' }) >>> tx.id 130 >>> tx.amount 10.870000000000001 >>> env['payment.transaction'].browse(130).amount 10.87 Authorize requires us to send a correctly rounded amount. The following response is returned when sending 10.870000000000001: {'messages': {'message': [{'code': 'E00027', 'text': 'The transaction was unsuccessful.'}], 'resultCode': 'Error'}, 'transactionResponse': {'SupplementalDataQualificationIndicator': 0, 'accountNumber': '', 'accountType': '', 'authCode': '', 'avsResultCode': 'P', 'cavvResultCode': '', 'cvvResultCode': '', 'errors': [{'errorCode': '5', 'errorText': 'A valid amount is ' 'required.'}], 'refTransID': '', 'responseCode': '3', 'testRequest': '0', 'transHash': '', 'transHashSha2': '', 'transId': '0'}} To work around the issue always round when we read amount. Lower level solutions were considered in #45248 but for now we'll stick with this higher level and lower risk patch. opw-2188889 closes odoo/odoo#45362 X-original-commit: 7485927f0eb152086efcaaf4a30260e503267c41 Signed-off-by: Nicolas Martinelli (nim) --- addons/payment_authorize/models/payment.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/payment_authorize/models/payment.py b/addons/payment_authorize/models/payment.py index 93403af7104..d6e08fda0e5 100644 --- a/addons/payment_authorize/models/payment.py +++ b/addons/payment_authorize/models/payment.py @@ -253,15 +253,15 @@ class TxAuthorize(models.Model): 'Please make sure the token has a valid acquirer reference.')) if not self.acquirer_id.capture_manually: - res = transaction.auth_and_capture(self.payment_token_id, self.amount, self.reference) + res = transaction.auth_and_capture(self.payment_token_id, round(self.amount, self.currency_id.decimal_places), self.reference) else: - res = transaction.authorize(self.payment_token_id, self.amount, self.reference) + res = transaction.authorize(self.payment_token_id, round(self.amount, self.currency_id.decimal_places), self.reference) return self._authorize_s2s_validate_tree(res) def authorize_s2s_capture_transaction(self): self.ensure_one() transaction = AuthorizeAPI(self.acquirer_id) - tree = transaction.capture(self.acquirer_reference or '', self.amount) + tree = transaction.capture(self.acquirer_reference or '', round(self.amount, self.currency_id.decimal_places)) return self._authorize_s2s_validate_tree(tree) def authorize_s2s_void_transaction(self):