Files
odoo_source/addons/payment_paypal/tests/test_paypal.py
T
Anita (anko) e5c187ade8 [IMP] payment(_paypal): UX and payment flow improvements
UX was lacking comparing to other payment providers,
important fields were not always shown or were checkboxes
when they should be automatically true.

In order to make payment flow easier and more intitive, unnecessary fields
were removed, email is automatically filled. Now when user cancels transaction
on paypal before paying, it automatically cancels transaction on Odoo. Additionaly, quick
onboarding is only available if user already has paypal account and Stripe
no longer installs ond configures paypal if Stripe's onboarding get canceled.

task-2854184

closes odoo/odoo#104974

Related: odoo/upgrade#4025
Related: odoo/documentation#3063
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
2023-02-17 14:09:43 +01:00

172 lines
7.4 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from unittest.mock import patch
from werkzeug import urls
from odoo.exceptions import ValidationError
from odoo.tests import tagged
from odoo.tools import float_repr, mute_logger
from odoo.addons.payment.tests.http_common import PaymentHttpCommon
from odoo.addons.payment_paypal.controllers.main import PaypalController
from odoo.addons.payment_paypal.tests.common import PaypalCommon
@tagged('post_install', '-at_install')
class PaypalTest(PaypalCommon, PaymentHttpCommon):
def _get_expected_values(self):
return_url = self._build_url(PaypalController._return_url)
cancel_url = self._build_url(PaypalController._cancel_url)
cancel_url_params = {
'tx_ref': self.reference,
'access_token': self._generate_test_access_token(self.reference),
}
values = {
'address1': 'Huge Street 2/543',
'amount': str(self.amount),
'business': self.paypal.paypal_email_account,
'cancel_return': f'{cancel_url}?{urls.url_encode(cancel_url_params)}',
'city': 'Sin City',
'cmd': '_xclick',
'country': 'BE',
'currency_code': self.currency.name,
'email': 'norbert.buyer@example.com',
'first_name': 'Norbert',
'item_name': f'{self.paypal.company_id.name}: {self.reference}',
'item_number': self.reference,
'last_name': 'Buyer',
'lc': 'en_US',
'notify_url': self._build_url(PaypalController._webhook_url),
'return': return_url,
'rm': '2',
'zip': '1000',
}
if self.paypal.fees_active:
fees = self.currency.round(self.paypal._compute_fees(self.amount, self.currency, self.partner.country_id))
if fees:
# handling input is only specified if truthy
values['handling'] = float_repr(fees, self.currency.decimal_places)
return values
@mute_logger('odoo.addons.payment.models.payment_transaction')
def test_redirect_form_values(self):
tx = self._create_transaction(flow='redirect')
with patch(
'odoo.addons.payment.utils.generate_access_token', new=self._generate_test_access_token
):
processing_values = tx._get_processing_values()
form_info = self._extract_values_from_html_form(processing_values['redirect_form_html'])
self.assertEqual(
form_info['action'],
'https://www.sandbox.paypal.com/cgi-bin/webscr')
expected_values = self._get_expected_values()
self.assertDictEqual(
expected_values,
form_info['inputs'],
"Paypal: invalid inputs specified in the redirect form.",
)
@mute_logger('odoo.addons.payment.models.payment_transaction')
def test_redirect_form_with_fees(self):
self.paypal.write({
'fees_active': True,
'fees_dom_fixed': 1.0,
'fees_dom_var': 0.35,
'fees_int_fixed': 1.5,
'fees_int_var': 0.50,
})
expected_values = self._get_expected_values()
tx = self._create_transaction(flow='redirect')
with patch(
'odoo.addons.payment.utils.generate_access_token', new=self._generate_test_access_token
):
processing_values = tx._get_processing_values()
form_info = self._extract_values_from_html_form(processing_values['redirect_form_html'])
self.assertEqual(form_info['action'], 'https://www.sandbox.paypal.com/cgi-bin/webscr')
self.assertDictEqual(
expected_values, form_info['inputs'],
"Paypal: invalid inputs specified in the redirect form.")
def test_feedback_processing(self):
# Unknown transaction
with self.assertRaises(ValidationError):
self.env['payment.transaction']._handle_notification_data('paypal', self.notification_data)
# Confirmed transaction
tx = self._create_transaction('redirect')
self.env['payment.transaction']._handle_notification_data('paypal', self.notification_data)
self.assertEqual(tx.state, 'done')
self.assertEqual(tx.provider_reference, self.notification_data['txn_id'])
# Pending transaction
self.reference = 'Test Transaction 2'
tx = self._create_transaction('redirect')
payload = dict(
self.notification_data,
item_number=self.reference,
payment_status='Pending',
pending_reason='multi_currency',
)
self.env['payment.transaction']._handle_notification_data('paypal', payload)
self.assertEqual(tx.state, 'pending')
self.assertEqual(tx.state_message, payload['pending_reason'])
def test_fees_computation(self):
# If the merchant needs to keep 100€, the transaction will be equal to 103.30€.
# In this way, Paypal will take 103.30 * 2.9% + 0.30 = 3.30€
# And the merchant will take 103.30 - 3.30 = 100€
self.paypal.write({
'fees_active': True,
'fees_int_fixed': 0.30,
'fees_int_var': 0.029,
})
total_fee = self.paypal._compute_fees(100, self.paypal.main_currency_id, False)
self.assertEqual(round(total_fee, 2), 3.3, 'Wrong computation of the Paypal fees')
def test_parsing_pdt_validation_response_returns_notification_data(self):
""" Test that the notification data are parsed from the content of a validation response."""
response_content = 'SUCCESS\nkey1=val1\nkey2=val+2\n'
notification_data = PaypalController._parse_pdt_validation_response(response_content)
self.assertDictEqual(notification_data, {'key1': 'val1', 'key2': 'val 2'})
def test_fail_to_parse_pdt_validation_response_if_not_successful(self):
""" Test that no notification data are returned from parsing unsuccessful PDT validation."""
response_content = 'FAIL\ndoes-not-matter'
notification_data = PaypalController._parse_pdt_validation_response(response_content)
self.assertIsNone(notification_data)
@mute_logger('odoo.addons.payment_paypal.controllers.main')
def test_webhook_notification_confirms_transaction(self):
""" Test the processing of a webhook notification. """
tx = self._create_transaction('redirect')
url = self._build_url(PaypalController._webhook_url)
with patch(
'odoo.addons.payment_paypal.controllers.main.PaypalController'
'._verify_webhook_notification_origin'
):
self._make_http_post_request(url, data=self.notification_data)
self.assertEqual(tx.state, 'done')
@mute_logger('odoo.addons.payment_paypal.controllers.main')
def test_webhook_notification_triggers_origin_check(self):
""" Test that receiving a webhook notification triggers an origin check. """
self._create_transaction('redirect')
url = self._build_url(PaypalController._webhook_url)
with patch(
'odoo.addons.payment_paypal.controllers.main.PaypalController'
'._verify_webhook_notification_origin'
) as origin_check_mock, patch(
'odoo.addons.payment.models.payment_transaction.PaymentTransaction'
'._handle_notification_data'
):
self._make_http_post_request(url, data=self.notification_data)
self.assertEqual(origin_check_mock.call_count, 1)