test_sips.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. import json
  3. from unittest.mock import patch
  4. from freezegun import freeze_time
  5. from werkzeug.exceptions import Forbidden
  6. from odoo.exceptions import ValidationError
  7. from odoo.tests import tagged
  8. from odoo.tools import mute_logger
  9. from odoo.addons.payment.tests.http_common import PaymentHttpCommon
  10. from odoo.addons.payment_sips.controllers.main import SipsController
  11. from odoo.addons.payment_sips.models.payment_provider import SUPPORTED_CURRENCIES
  12. from odoo.addons.payment_sips.tests.common import SipsCommon
  13. @tagged('post_install', '-at_install')
  14. class SipsTest(SipsCommon, PaymentHttpCommon):
  15. def test_compatible_providers(self):
  16. for curr in SUPPORTED_CURRENCIES:
  17. currency = self._prepare_currency(curr)
  18. providers = self.env['payment.provider']._get_compatible_providers(
  19. self.company.id, self.partner.id, self.amount, currency_id=currency.id
  20. )
  21. self.assertIn(self.sips, providers)
  22. unsupported_currency = self._prepare_currency('VEF')
  23. providers = self.env['payment.provider']._get_compatible_providers(
  24. self.company.id, self.partner.id, self.amount, currency_id=unsupported_currency.id
  25. )
  26. self.assertNotIn(self.sips, providers)
  27. # freeze time for consistent singularize_prefix behavior during the test
  28. @freeze_time("2011-11-02 12:00:21")
  29. def test_reference(self):
  30. tx = self._create_transaction(flow="redirect", reference="")
  31. self.assertEqual(tx.reference, "tx20111102120021",
  32. "Payulatam: transaction reference wasn't correctly singularized.")
  33. def test_redirect_form_values(self):
  34. self.patch(self, 'base_url', lambda: 'http://127.0.0.1:8069')
  35. self.patch(type(self.env['base']), 'get_base_url', lambda _: 'http://127.0.0.1:8069')
  36. tx = self._create_transaction(flow="redirect")
  37. with mute_logger('odoo.addons.payment.models.payment_transaction'):
  38. processing_values = tx._get_processing_values()
  39. form_info = self._extract_values_from_html_form(processing_values['redirect_form_html'])
  40. form_inputs = form_info['inputs']
  41. self.assertEqual(form_info['action'], self.sips.sips_test_url)
  42. self.assertEqual(form_inputs['InterfaceVersion'], self.sips.sips_version)
  43. return_url = self._build_url(SipsController._return_url)
  44. notify_url = self._build_url(SipsController._webhook_url)
  45. self.assertEqual(
  46. form_inputs['Data'],
  47. f'amount=111111|currencyCode=978|merchantId=dummy_mid|normalReturnUrl={return_url}|'
  48. f'automaticResponseUrl={notify_url}|transactionReference={self.reference}|'
  49. f'statementReference={self.reference}|keyVersion={self.sips.sips_key_version}|'
  50. f'returnContext={json.dumps(dict(reference=self.reference))}',
  51. )
  52. self.assertEqual(
  53. form_inputs['Seal'], '99d1d2d46a841de7fe313ac0b2d13a9e42cad50b444d35bf901879305818d9b2'
  54. )
  55. def test_feedback_processing(self):
  56. # Unknown transaction
  57. with self.assertRaises(ValidationError):
  58. self.env['payment.transaction']._handle_notification_data(
  59. 'sips', self.notification_data
  60. )
  61. # Confirmed transaction
  62. tx = self._create_transaction('redirect')
  63. self.env['payment.transaction']._handle_notification_data('sips', self.notification_data)
  64. self.assertEqual(tx.state, 'done')
  65. self.assertEqual(tx.provider_reference, self.reference)
  66. # Cancelled transaction
  67. old_reference = self.reference
  68. self.reference = 'Test Transaction 2'
  69. tx = self._create_transaction('redirect')
  70. payload = dict(
  71. self.notification_data,
  72. Data=self.notification_data['Data'].replace(old_reference, self.reference)
  73. .replace('responseCode=00', 'responseCode=12')
  74. )
  75. self.env['payment.transaction']._handle_notification_data('sips', payload)
  76. self.assertEqual(tx.state, 'cancel')
  77. @mute_logger('odoo.addons.payment_sips.controllers.main')
  78. def test_webhook_notification_confirms_transaction(self):
  79. """ Test the processing of a webhook notification. """
  80. tx = self._create_transaction('redirect')
  81. url = self._build_url(SipsController._return_url)
  82. with patch(
  83. 'odoo.addons.payment_sips.controllers.main.SipsController'
  84. '._verify_notification_signature'
  85. ):
  86. self._make_http_post_request(url, data=self.notification_data)
  87. self.assertEqual(tx.state, 'done')
  88. @mute_logger('odoo.addons.payment_sips.controllers.main')
  89. def test_webhook_notification_triggers_signature_check(self):
  90. """ Test that receiving a webhook notification triggers a signature check. """
  91. self._create_transaction('redirect')
  92. url = self._build_url(SipsController._webhook_url)
  93. with patch(
  94. 'odoo.addons.payment_sips.controllers.main.SipsController'
  95. '._verify_notification_signature'
  96. ) as signature_check_mock, patch(
  97. 'odoo.addons.payment.models.payment_transaction.PaymentTransaction'
  98. '._handle_notification_data'
  99. ):
  100. self._make_http_post_request(url, data=self.notification_data)
  101. self.assertEqual(signature_check_mock.call_count, 1)
  102. def test_accept_notification_with_valid_signature(self):
  103. """ Test the verification of a notification with a valid signature. """
  104. tx = self._create_transaction('redirect')
  105. self._assert_does_not_raise(
  106. Forbidden, SipsController._verify_notification_signature, self.notification_data, tx
  107. )
  108. @mute_logger('odoo.addons.payment_sips.controllers.main')
  109. def test_reject_notification_with_missing_signature(self):
  110. """ Test the verification of a notification with a missing signature. """
  111. tx = self._create_transaction('redirect')
  112. payload = dict(self.notification_data, Seal=None)
  113. self.assertRaises(Forbidden, SipsController._verify_notification_signature, payload, tx)
  114. @mute_logger('odoo.addons.payment_sips.controllers.main')
  115. def test_reject_notification_with_invalid_signature(self):
  116. """ Test the verification of a notification with an invalid signature. """
  117. tx = self._create_transaction('redirect')
  118. payload = dict(self.notification_data, Seal='dummy')
  119. self.assertRaises(Forbidden, SipsController._verify_notification_signature, payload, tx)