diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-11-30 15:27:59 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-11-30 15:27:59 +0100 |
| commit | ab084d580ff0edf9be1d12cec87aeffdd84459b7 (patch) | |
| tree | 6a19b4656315d94b65c88507bb471ac56d16f3ed /addons/payment_authorize | |
| parent | 3f66814a0d01a81bef5456a07da4b1ac8e2281e7 (diff) | |
| parent | 98539336a5d40de748764ff0a3c16d8cda77b02f (diff) | |
[MERGE] forward port branch saas-15 up to 98539336a5d
Diffstat (limited to 'addons/payment_authorize')
| -rw-r--r-- | addons/payment_authorize/models/authorize_request.py | 54 | ||||
| -rw-r--r-- | addons/payment_authorize/tests/test_authorize.py | 19 |
2 files changed, 69 insertions, 4 deletions
diff --git a/addons/payment_authorize/models/authorize_request.py b/addons/payment_authorize/models/authorize_request.py index 1ae0e71b6ed..f7aca95511d 100644 --- a/addons/payment_authorize/models/authorize_request.py +++ b/addons/payment_authorize/models/authorize_request.py @@ -29,6 +29,34 @@ def strip_ns(xml, ns): return it.root +def error_check(elem): + """Check if the response sent by Authorize.net contains an error. + + Errors can be a failure to try the transaction (in that case, the transasctionResponse + is empty, and the meaningful error message will be in message/code) or a failure to process + the transaction (in that case, the message/code content will be generic and the actual error + message is in transactionResponse/errors/error/errorText). + + :param etree._Element elem: the root element of the response that will be parsed + + :rtype: tuple (bool, str) + :return: tuple containnig a boolean indicating if the response should be considered + as an error and the most meaningful error message found in it. + """ + result_code = elem.find('messages/resultCode') + msg = 'No meaningful error message found, please check logs or the Authorize.net backend' + has_error = result_code is not None and result_code.text == 'Error' + if has_error: + # accumulate the most meangingful error + error = elem.find('transactionResponse/errors/error') + error = error if error is not None else elem.find('messages/message') + if error is not None: + code = error[0].text + text = error[1].text + msg = '%s: %s' % (code, text) + return (has_error, msg) + + class AuthorizeAPI(): """Authorize.net Gateway API integration. @@ -38,6 +66,9 @@ class AuthorizeAPI(): - Customer Profile/Payment Profile creation - Transaction authorization/capture/voiding """ + + AUTH_ERROR_STATUS = 3 + def __init__(self, acquirer): """Initiate the environment with the acquirer data. @@ -63,9 +94,6 @@ class AuthorizeAPI(): request.add_header('Content-Type', 'text/xml') response = urlopen(request).read() response = strip_ns(response, XMLNS) - if response.find('messages/resultCode').text == 'Error': - messages = map(lambda m: m.text, response.findall('messages/message/text')) - raise ValidationError(_('Authorize.net Error Message(s):\n %s') % '\n'.join(messages)) return response def _base_tree(self, requestType): @@ -190,6 +218,11 @@ class AuthorizeAPI(): etree.SubElement(order, "invoiceNumber").text = reference response = self._authorize_request(root) res = dict() + (has_error, error_msg) = error_check(response) + if has_error: + res['x_response_code'] = self.AUTH_ERROR_STATUS + res['x_response_reason_text'] = error_msg + return res res['x_response_code'] = response.find('transactionResponse/responseCode').text res['x_trans_id'] = response.find('transactionResponse/transId').text res['x_type'] = 'auth_capture' @@ -220,6 +253,11 @@ class AuthorizeAPI(): etree.SubElement(order, "invoiceNumber").text = reference response = self._authorize_request(root) res = dict() + (has_error, error_msg) = error_check(response) + if has_error: + res['x_response_code'] = self.AUTH_ERROR_STATUS + res['x_response_reason_text'] = error_msg + return res res['x_response_code'] = response.find('transactionResponse/responseCode').text res['x_trans_id'] = response.find('transactionResponse/transId').text res['x_type'] = 'auth_only' @@ -245,6 +283,11 @@ class AuthorizeAPI(): etree.SubElement(tx, "refTransId").text = transaction_id response = self._authorize_request(root) res = dict() + (has_error, error_msg) = error_check(response) + if has_error: + res['x_response_code'] = self.AUTH_ERROR_STATUS + res['x_response_reason_text'] = error_msg + return res res['x_response_code'] = response.find('transactionResponse/responseCode').text res['x_trans_id'] = response.find('transactionResponse/transId').text res['x_type'] = 'prior_auth_capture' @@ -265,6 +308,11 @@ class AuthorizeAPI(): etree.SubElement(tx, "refTransId").text = transaction_id response = self._authorize_request(root) res = dict() + (has_error, error_msg) = error_check(response) + if has_error: + res['x_response_code'] = self.AUTH_ERROR_STATUS + res['x_response_reason_text'] = error_msg + return res res['x_response_code'] = response.find('transactionResponse/responseCode').text res['x_trans_id'] = response.find('transactionResponse/transId').text res['x_type'] = 'void' diff --git a/addons/payment_authorize/tests/test_authorize.py b/addons/payment_authorize/tests/test_authorize.py index 50e4e95fdc4..35be8a99b17 100644 --- a/addons/payment_authorize/tests/test_authorize.py +++ b/addons/payment_authorize/tests/test_authorize.py @@ -209,7 +209,7 @@ class AuthorizeForm(AuthorizeCommon): 'acquirer_id': authorize.id, 'type': 'server2server', 'currency_id': self.currency_usd.id, - 'reference': 'test_ref_%s' % odoo.fields.Date.today(), + 'reference': 'test_ref_%s' % int(time.time()), 'payment_token_id': payment_token.id, 'partner_id': self.buyer_id, @@ -251,3 +251,20 @@ class AuthorizeForm(AuthorizeCommon): self.assertEqual(transaction.state, 'authorized') transaction.action_void() self.assertEqual(transaction.state, 'cancel') + + # try charging an unexisting profile + ghost_payment_token = payment_token.copy() + ghost_payment_token.authorize_profile = '99999999999' + # create normal s2s transaction + transaction = self.env['payment.transaction'].create({ + 'amount': 500, + 'acquirer_id': authorize.id, + 'type': 'server2server', + 'currency_id': self.currency_usd.id, + 'reference': 'test_ref_%s' % int(time.time()), + 'payment_token_id': ghost_payment_token.id, + 'partner_id': self.buyer_id, + + }) + transaction.authorize_s2s_do_transaction() + self.assertEqual(transaction.state, 'error') |
