Files
odoo_source/addons/payment_authorize/tests/test_authorize.py
T
qdp-odoo 01216345e2 [REF] account,payment(_*),sale*: downgrade transactions into debug items
It was very confusing for the user to distinct account.payment and payment.transaction. From now on, the transactions are
technical objects and, in the backend, we only refer to it in log messages (Front end will be adapted in the same fashion
later on). They are hidden in debug mode in accounting\configuration\payments as their purpose is now purely technical/log

This commit also aims to reduce the gap between the accounting app and the transactions: account.payment objects are
created/validated upon completion of transaction.

To ease the capture/voiding of pending transactions, the related buttons are now displayed directly on the SO/invoice
instead of the transactions.

Was task: https://www.odoo.com/web#id=35857&view_type=form&model=project.task&action=333&active_id=967&menu_id=4720
Was PR #24043

[FIX] add domain based on journal to payment tokens

Was opw: https://www.odoo.com/web?debug#id=1828206&view_type=form&model=project.task&menu_id=5200
2018-05-23 15:44:55 +02:00

282 lines
11 KiB
Python

# -*- coding: utf-8 -*-
import hashlib
import hmac
import time
from werkzeug import urls
from lxml import objectify
import odoo
from odoo.addons.payment.models.payment_acquirer import ValidationError
from odoo.addons.payment.tests.common import PaymentAcquirerCommon
from odoo.addons.payment_authorize.controllers.main import AuthorizeController
from odoo.tools import mute_logger
@odoo.tests.tagged('post_install', '-at_install')
class AuthorizeCommon(PaymentAcquirerCommon):
def setUp(self):
super(AuthorizeCommon, self).setUp()
# authorize only support USD in test environment
self.currency_usd = self.env['res.currency'].search([('name', '=', 'USD')], limit=1)[0]
# get the authorize account
self.authorize = self.env.ref('payment.payment_acquirer_authorize')
# Be sure to be in 'capture' mode
# self.authorize.auto_confirm = 'confirm_so'
@odoo.tests.tagged('post_install', '-at_install', '-standard', 'external')
class AuthorizeForm(AuthorizeCommon):
def _authorize_generate_hashing(self, values):
data = '^'.join([
values['x_login'],
values['x_fp_sequence'],
values['x_fp_timestamp'],
values['x_amount'],
]) + '^'
return hmac.new(values['x_trans_key'].encode('utf-8'), data.encode('utf-8'), hashlib.md5).hexdigest()
def test_10_Authorize_form_render(self):
self.assertEqual(self.authorize.environment, 'test', 'test without test environment')
# ----------------------------------------
# Test: button direct rendering
# ----------------------------------------
base_url = self.env['ir.config_parameter'].get_param('web.base.url')
form_values = {
'x_login': self.authorize.authorize_login,
'x_trans_key': self.authorize.authorize_transaction_key,
'x_amount': '56.16',
'x_show_form': 'PAYMENT_FORM',
'x_type': 'AUTH_CAPTURE',
'x_method': 'CC',
'x_fp_sequence': '%s%s' % (self.authorize.id, int(time.time())),
'x_version': '3.1',
'x_relay_response': 'TRUE',
'x_fp_timestamp': str(int(time.time())),
'x_relay_url': urls.url_join(base_url, AuthorizeController._return_url),
'x_cancel_url': urls.url_join(base_url, AuthorizeController._cancel_url),
'return_url': None,
'x_currency_code': 'USD',
'x_invoice_num': 'SO004',
'x_first_name': 'Norbert',
'x_last_name': 'Buyer',
'x_company': 'Big Company',
'x_address': 'Huge Street 2/543',
'x_city': 'Sin City',
'x_zip': '1000',
'x_country': 'Belgium',
'x_phone': '0032 12 34 56 78',
'x_email': 'norbert.buyer@example.com',
'x_state': None,
'x_ship_to_first_name': 'Norbert',
'x_ship_to_last_name': 'Buyer',
'x_ship_to_address': 'Huge Street 2/543',
'x_ship_to_city': 'Sin City',
'x_ship_to_zip': '1000',
'x_ship_to_country': 'Belgium',
'x_ship_to_phone': '0032 12 34 56 78',
'x_ship_to_email': 'norbert.buyer@example.com',
'x_ship_to_state': None,
}
form_values['x_fp_hash'] = self._authorize_generate_hashing(form_values)
# render the button
res = self.authorize.render('SO004', 56.16, self.currency_usd.id, values=self.buyer_values)
# check form result
tree = objectify.fromstring(res)
data_set = tree.xpath("//input[@name='data_set']")
self.assertEqual(len(data_set), 1, 'Authorize: Found %d "data_set" input instead of 1' % len(data_set))
self.assertEqual(data_set[0].get('data-action-url'), 'https://test.authorize.net/gateway/transact.dll', 'Authorize: wrong data-action-url POST url')
for el in tree.iterfind('input'):
values = list(el.attrib.values())
if values[1] in ['submit', 'x_fp_hash', 'return_url', 'x_state', 'x_ship_to_state', 'data_set']:
continue
self.assertEqual(
values[2],
form_values[values[1]],
'Authorize: wrong value for input %s: received %s instead of %s' % (values[1], values[2], form_values[values[1]])
)
@mute_logger('odoo.addons.payment_authorize.models.payment', 'ValidationError')
def test_20_authorize_form_management(self):
# be sure not to do stupid thing
self.assertEqual(self.authorize.environment, 'test', 'test without test environment')
# typical data posted by authorize after client has successfully paid
authorize_post_data = {
'return_url': u'/shop/payment/validate',
'x_MD5_Hash': u'7934485E1C105940BE854208D10FAB4F',
'x_account_number': u'XXXX0027',
'x_address': u'Huge Street 2/543',
'x_amount': u'320.00',
'x_auth_code': u'E4W7IU',
'x_avs_code': u'Y',
'x_card_type': u'Visa',
'x_cavv_response': u'2',
'x_city': u'Sun City',
'x_company': u'',
'x_country': u'Belgium',
'x_cust_id': u'',
'x_cvv2_resp_code': u'',
'x_description': u'',
'x_duty': u'0.00',
'x_email': u'norbert.buyer@example.com',
'x_fax': u'',
'x_first_name': u'Norbert',
'x_freight': u'0.00',
'x_invoice_num': u'SO004',
'x_last_name': u'Buyer',
'x_method': u'CC',
'x_phone': u'0032 12 34 56 78',
'x_po_num': u'',
'x_response_code': u'1',
'x_response_reason_code': u'1',
'x_response_reason_text': u'This transaction has been approved.',
'x_ship_to_address': u'Huge Street 2/543',
'x_ship_to_city': u'Sun City',
'x_ship_to_company': u'',
'x_ship_to_country': u'Belgium',
'x_ship_to_first_name': u'Norbert',
'x_ship_to_last_name': u'Buyer',
'x_ship_to_state': u'',
'x_ship_to_zip': u'1000',
'x_state': u'',
'x_tax': u'0.00',
'x_tax_exempt': u'FALSE',
'x_test_request': u'false',
'x_trans_id': u'2217460311',
'x_type': u'auth_capture',
'x_zip': u'1000'
}
# should raise error about unknown tx
with self.assertRaises(ValidationError):
self.env['payment.transaction'].form_feedback(authorize_post_data, 'authorize')
tx = self.env['payment.transaction'].create({
'amount': 320.0,
'acquirer_id': self.authorize.id,
'currency_id': self.currency_usd.id,
'reference': 'SO004-1',
'partner_name': 'Norbert Buyer',
'partner_country_id': self.country_france.id})
tx._set_transaction_done()
# validate it
self.env['payment.transaction'].form_feedback(authorize_post_data, 'authorize')
# check state
self.assertEqual(tx.state, 'done', 'Authorize: validation did not put tx into done state')
self.assertEqual(tx.acquirer_reference, authorize_post_data.get('x_trans_id'), 'Authorize: validation did not update tx payid')
tx = self.env['payment.transaction'].create({
'amount': 320.0,
'acquirer_id': self.authorize.id,
'currency_id': self.currency_usd.id,
'reference': 'SO004-2',
'partner_name': 'Norbert Buyer',
'partner_country_id': self.country_france.id})
tx._set_transaction_done()
# simulate an error
authorize_post_data['x_response_code'] = u'3'
self.env['payment.transaction'].form_feedback(authorize_post_data, 'authorize')
# check state
self.assertEqual(tx.state, 'cancel', 'Authorize: erroneous validation did not put tx into error state')
@odoo.tests.tagged('post_install', '-at_install', '-standard', 'external')
class AuthorizeForm(AuthorizeCommon):
def test_30_authorize_s2s(self):
# be sure not to do stupid thing
authorize = self.authorize
self.assertEqual(authorize.environment, 'test', 'test without test environment')
# add credential
# FIXME: put this test in master-nightly on odoo/odoo + create sandbox account
authorize.write({
'authorize_transaction_key': '',
'authorize_login': '',
})
self.assertTrue(authorize.authorize_test_credentials, 'Authorize.net: s2s authentication failed')
# create payment meethod
payment_token = self.env['payment.token'].create({
'acquirer_id': authorize.id,
'partner_id': self.buyer_id,
'cc_number': '4111 1111 1111 1111',
'cc_expiry': '02 / 26',
'cc_brand': 'visa',
'cc_cvc': '111',
'cc_holder_name': 'test',
})
# 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': payment_token.id,
'partner_id': self.buyer_id,
})
transaction.authorize_s2s_do_transaction()
self.assertEqual(transaction.state, 'done',)
# switch to 'authorize only'
# create authorize only s2s transaction & capture it
self.authorize.capture_manually = True
transaction = self.env['payment.transaction'].create({
'amount': 500,
'acquirer_id': authorize.id,
'type': 'server2server',
'currency_id': self.currency_usd.id,
'reference': 'test_%s' % int(time.time()),
'payment_token_id': payment_token.id,
'partner_id': self.buyer_id,
})
transaction.authorize_s2s_do_transaction()
self.assertEqual(transaction.state, 'authorized')
transaction.action_capture()
self.assertEqual(transaction.state, 'done')
# create authorize only s2s transaction & void it
self.authorize.capture_manually = True
transaction = self.env['payment.transaction'].create({
'amount': 500,
'acquirer_id': authorize.id,
'type': 'server2server',
'currency_id': self.currency_usd.id,
'reference': 'test_%s' % int(time.time()),
'payment_token_id': payment_token.id,
'partner_id': self.buyer_id,
})
transaction.authorize_s2s_do_transaction()
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, 'cancel')