summaryrefslogtreecommitdiff
path: root/addons/payment_stripe/tests
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/payment_stripe/tests
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/payment_stripe/tests')
-rw-r--r--addons/payment_stripe/tests/__init__.py2
-rw-r--r--addons/payment_stripe/tests/stripe_mocks.py31
-rw-r--r--addons/payment_stripe/tests/test_stripe.py318
3 files changed, 351 insertions, 0 deletions
diff --git a/addons/payment_stripe/tests/__init__.py b/addons/payment_stripe/tests/__init__.py
new file mode 100644
index 00000000..228d5775
--- /dev/null
+++ b/addons/payment_stripe/tests/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+from . import test_stripe
diff --git a/addons/payment_stripe/tests/stripe_mocks.py b/addons/payment_stripe/tests/stripe_mocks.py
new file mode 100644
index 00000000..6364fbf1
--- /dev/null
+++ b/addons/payment_stripe/tests/stripe_mocks.py
@@ -0,0 +1,31 @@
+checkout_session_signature = 't=1591264652,v1=1f0d3e035d8de956396b1d91727267fbbf483253e7702e46357b4d2bfa078ba4,v0=20d76342f4704d49f8f89db03acff7cf04afa48ca70a22d608b4649b332c1f51'
+checkout_session_body = b'{\n "id": "evt_1GqFpHAlCFm536g8NYSLoccF",\n "object": "event",\n "api_version": "2019-05-16",\n "created": 1591264651,\n "data": {\n "object": {\n "id": "cs_test_SI8yz61JCZ4gxd7Z5oGfQSn9ZbubC6SZF3bJTxvy2PVqSd3dzbDV1kyd",\n "object": "checkout.session",\n "billing_address_collection": null,\n "cancel_url": "https://httpbin.org/post",\n "client_reference_id": null,\n "customer": "cus_HP3xLqXMIwBfTg",\n "customer_email": null,\n "display_items": [\n {\n "amount": 1500,\n "currency": "usd",\n "custom": {\n "description": "comfortable cotton t-shirt",\n "images": null,\n "name": "t-shirt"\n },\n "quantity": 2,\n "type": "custom"\n }\n ],\n "livemode": false,\n "locale": null,\n "metadata": {\n },\n "mode": "payment",\n "payment_intent": "pi_1GqFpCAlCFm536g8HsBSvSEt",\n "payment_method_types": [\n "card"\n ],\n "setup_intent": null,\n "shipping": null,\n "shipping_address_collection": null,\n "submit_type": null,\n "subscription": null,\n "success_url": "https://httpbin.org/post"\n }\n },\n "livemode": false,\n "pending_webhooks": 2,\n "request": {\n "id": null,\n "idempotency_key": null\n },\n "type": "checkout.session.completed"\n}'
+
+checkout_session_object = {'billing_address_collection': None,
+ 'cancel_url': 'https://httpbin.org/post',
+ 'client_reference_id': "tx_ref_test_handle_checkout_webhook",
+ 'customer': 'cus_HOgyjnjdgY6pmY',
+ 'customer_email': None,
+ 'display_items': [{'amount': 1500,
+ 'currency': 'usd',
+ 'custom': {'description': 'comfortable '
+ 'cotton '
+ 't-shirt',
+ 'images': None,
+ 'name': 't-shirt'},
+ 'quantity': 2,
+ 'type': 'custom'}],
+ 'id': 'cs_test_sbTG0yGwTszAqFUP8Ulecr1bUwEyQEo29M8taYvdP7UA6Qr37qX6uA6w',
+ 'livemode': False,
+ 'locale': None,
+ 'metadata': {},
+ 'mode': 'payment',
+ 'object': 'checkout.session',
+ 'payment_intent': 'pi_1GptaRAlCFm536g8AfCF6Zi0',
+ 'payment_method_types': ['card'],
+ 'setup_intent': None,
+ 'shipping': None,
+ 'shipping_address_collection': None,
+ 'submit_type': None,
+ 'subscription': None,
+ 'success_url': 'https://httpbin.org/post'}
diff --git a/addons/payment_stripe/tests/test_stripe.py b/addons/payment_stripe/tests/test_stripe.py
new file mode 100644
index 00000000..2ac28193
--- /dev/null
+++ b/addons/payment_stripe/tests/test_stripe.py
@@ -0,0 +1,318 @@
+# -*- coding: utf-8 -*-
+import odoo
+from odoo import fields
+from odoo.exceptions import ValidationError
+from odoo.addons.payment.tests.common import PaymentAcquirerCommon
+from unittest.mock import patch
+from . import stripe_mocks
+from ..models.payment import STRIPE_SIGNATURE_AGE_TOLERANCE
+from odoo.tools import mute_logger
+
+
+class StripeCommon(PaymentAcquirerCommon):
+
+ @classmethod
+ def setUpClass(cls, chart_template_ref=None):
+ super().setUpClass(chart_template_ref=chart_template_ref)
+ cls.stripe = cls.env.ref('payment.payment_acquirer_stripe')
+ cls.stripe.write({
+ 'stripe_secret_key': 'sk_test_KJtHgNwt2KS3xM7QJPr4O5E8',
+ 'stripe_publishable_key': 'pk_test_QSPnimmb4ZhtkEy3Uhdm4S6J',
+ 'stripe_webhook_secret': 'whsec_vG1fL6CMUouQ7cObF2VJprLVXT5jBLxB',
+ 'state': 'test',
+ })
+ cls.token = cls.env['payment.token'].create({
+ 'name': 'Test Card',
+ 'acquirer_id': cls.stripe.id,
+ 'acquirer_ref': 'cus_G27S7FqQ2w3fuH',
+ 'stripe_payment_method': 'pm_1FW3DdAlCFm536g8eQoSCejY',
+ 'partner_id': cls.buyer.id,
+ 'verified': True,
+ })
+ cls.ideal_icon = cls.env.ref("payment.payment_icon_cc_ideal")
+ cls.bancontact_icon = cls.env.ref("payment.payment_icon_cc_bancontact")
+ cls.p24_icon = cls.env.ref("payment.payment_icon_cc_p24")
+ cls.eps_icon = cls.env.ref("payment.payment_icon_cc_eps")
+ cls.giropay_icon = cls.env.ref("payment.payment_icon_cc_giropay")
+ cls.all_icons = [cls.ideal_icon, cls.bancontact_icon, cls.p24_icon, cls.eps_icon, cls.giropay_icon]
+ cls.stripe.write({'payment_icon_ids': [(5, 0, 0)]})
+
+
+@odoo.tests.tagged('post_install', '-at_install', '-standard', 'external')
+class StripeTest(StripeCommon):
+
+ def run(self, result=None):
+ with mute_logger('odoo.addons.payment.models.payment_acquirer', 'odoo.addons.payment_stripe.models.payment'):
+ StripeCommon.run(self, result)
+
+ def test_10_stripe_s2s(self):
+ self.assertEqual(self.stripe.state, 'test', 'test without test environment')
+ # Create transaction
+ tx = self.env['payment.transaction'].create({
+ 'reference': 'stripe_test_10_%s' % fields.datetime.now().strftime('%Y%m%d_%H%M%S'),
+ 'currency_id': self.currency_euro.id,
+ 'acquirer_id': self.stripe.id,
+ 'partner_id': self.buyer_id,
+ 'payment_token_id': self.token.id,
+ 'type': 'server2server',
+ 'amount': 115.0
+ })
+ tx.with_context(off_session=True).stripe_s2s_do_transaction()
+
+ # Check state
+ self.assertEqual(tx.state, 'done', 'Stripe: Transcation has been discarded.')
+
+ def test_20_stripe_form_render(self):
+ self.assertEqual(self.stripe.state, 'test', 'test without test environment')
+
+ # ----------------------------------------
+ # Test: button direct rendering
+ # ----------------------------------------
+
+ # render the button
+ self.stripe.render('SO404', 320.0, self.currency_euro.id, values=self.buyer_values).decode('utf-8')
+
+ def test_30_stripe_form_management(self):
+ self.assertEqual(self.stripe.state, 'test', 'test without test environment')
+ ref = 'stripe_test_30_%s' % fields.datetime.now().strftime('%Y%m%d_%H%M%S')
+ tx = self.env['payment.transaction'].create({
+ 'amount': 4700.0,
+ 'acquirer_id': self.stripe.id,
+ 'currency_id': self.currency_euro.id,
+ 'reference': ref,
+ 'partner_name': 'Norbert Buyer',
+ 'partner_country_id': self.country_france.id,
+ 'payment_token_id': self.token.id,
+ })
+ res = tx.with_context(off_session=True)._stripe_create_payment_intent()
+ tx.stripe_payment_intent = res.get('payment_intent')
+
+ # typical data posted by Stripe after client has successfully paid
+ stripe_post_data = {'reference': ref}
+ # validate it
+ tx.form_feedback(stripe_post_data, 'stripe')
+ self.assertEqual(tx.state, 'done', 'Stripe: validation did not put tx into done state')
+ self.assertEqual(tx.acquirer_reference, stripe_post_data.get('id'), 'Stripe: validation did not update tx id')
+
+ def test_add_available_payment_method_types_local_enabled(self):
+ self.stripe.payment_icon_ids = [(6, 0, [i.id for i in self.all_icons])]
+ tx_values = {
+ 'billing_partner_country': self.env.ref('base.be'),
+ 'currency': self.env.ref('base.EUR'),
+ 'type': 'form'
+ }
+ stripe_session_data = {}
+
+ self.stripe._add_available_payment_method_types(stripe_session_data, tx_values)
+
+ actual = {pmt for key, pmt in stripe_session_data.items() if key.startswith('payment_method_types')}
+ self.assertEqual({'card', 'bancontact'}, actual)
+
+ def test_add_available_payment_method_types_local_enabled_2(self):
+ self.stripe.payment_icon_ids = [(6, 0, [i.id for i in self.all_icons])]
+ tx_values = {
+ 'billing_partner_country': self.env.ref('base.pl'),
+ 'currency': self.env.ref('base.PLN'),
+ 'type': 'form'
+ }
+ stripe_session_data = {}
+
+ self.stripe._add_available_payment_method_types(stripe_session_data, tx_values)
+
+ actual = {pmt for key, pmt in stripe_session_data.items() if key.startswith('payment_method_types')}
+ self.assertEqual({'card', 'p24'}, actual)
+
+ def test_add_available_payment_method_types_pmt_does_not_exist(self):
+ self.bancontact_icon.unlink()
+ tx_values = {
+ 'billing_partner_country': self.env.ref('base.be'),
+ 'currency': self.env.ref('base.EUR'),
+ 'type': 'form'
+ }
+ stripe_session_data = {}
+
+ self.stripe._add_available_payment_method_types(stripe_session_data, tx_values)
+
+ actual = {pmt for key, pmt in stripe_session_data.items() if key.startswith('payment_method_types')}
+ self.assertEqual({'card', 'bancontact'}, actual)
+
+ def test_add_available_payment_method_types_local_disabled(self):
+ tx_values = {
+ 'billing_partner_country': self.env.ref('base.be'),
+ 'currency': self.env.ref('base.EUR'),
+ 'type': 'form'
+ }
+ stripe_session_data = {}
+
+ self.stripe._add_available_payment_method_types(stripe_session_data, tx_values)
+
+ actual = {pmt for key, pmt in stripe_session_data.items() if key.startswith('payment_method_types')}
+ self.assertEqual({'card'}, actual)
+
+ def test_add_available_payment_method_types_local_all_but_bancontact(self):
+ self.stripe.payment_icon_ids = [(4, icon.id) for icon in self.all_icons if icon.name.lower() != 'bancontact']
+ tx_values = {
+ 'billing_partner_country': self.env.ref('base.be'),
+ 'currency': self.env.ref('base.EUR'),
+ 'type': 'form'
+ }
+ stripe_session_data = {}
+
+ self.stripe._add_available_payment_method_types(stripe_session_data, tx_values)
+
+ actual = {pmt for key, pmt in stripe_session_data.items() if key.startswith('payment_method_types')}
+ self.assertEqual({'card'}, actual)
+
+ def test_add_available_payment_method_types_recurrent(self):
+ tx_values = {
+ 'billing_partner_country': self.env.ref('base.be'),
+ 'currency': self.env.ref('base.EUR'),
+ 'type': 'form_save'
+ }
+ stripe_session_data = {}
+
+ self.stripe._add_available_payment_method_types(stripe_session_data, tx_values)
+
+ actual = {pmt for key, pmt in stripe_session_data.items() if key.startswith('payment_method_types')}
+ self.assertEqual({'card'}, actual)
+
+ def test_discarded_webhook(self):
+ self.assertFalse(self.env['payment.acquirer']._handle_stripe_webhook(dict(type='payment.intent.succeeded')))
+
+ def test_handle_checkout_webhook_no_secret(self):
+ self.stripe.stripe_webhook_secret = None
+
+ with self.assertRaises(ValidationError):
+ self.env['payment.acquirer']._handle_stripe_webhook(dict(type='checkout.session.completed'))
+
+ @patch('odoo.addons.payment_stripe.models.payment.request')
+ @patch('odoo.addons.payment_stripe.models.payment.datetime')
+ def test_handle_checkout_webhook(self, dt, request):
+ # pass signature verification
+ dt.utcnow.return_value.timestamp.return_value = 1591264652
+ request.httprequest.headers = {'Stripe-Signature': stripe_mocks.checkout_session_signature}
+ request.httprequest.data = stripe_mocks.checkout_session_body
+ # test setup
+ tx = self.env['payment.transaction'].create({
+ 'reference': 'tx_ref_test_handle_checkout_webhook',
+ 'currency_id': self.currency_euro.id,
+ 'acquirer_id': self.stripe.id,
+ 'partner_id': self.buyer_id,
+ 'payment_token_id': self.token.id,
+ 'type': 'server2server',
+ 'amount': 30
+ })
+ res = tx.with_context(off_session=True)._stripe_create_payment_intent()
+ tx.stripe_payment_intent = res.get('payment_intent')
+ stripe_object = stripe_mocks.checkout_session_object
+
+ actual = self.stripe._handle_checkout_webhook(stripe_object)
+
+ self.assertTrue(actual)
+
+ @patch('odoo.addons.payment_stripe.models.payment.request')
+ @patch('odoo.addons.payment_stripe.models.payment.datetime')
+ def test_handle_checkout_webhook_wrong_amount(self, dt, request):
+ # pass signature verification
+ dt.utcnow.return_value.timestamp.return_value = 1591264652
+ request.httprequest.headers = {'Stripe-Signature': stripe_mocks.checkout_session_signature}
+ request.httprequest.data = stripe_mocks.checkout_session_body
+ # test setup
+ bad_tx = self.env['payment.transaction'].create({
+ 'reference': 'tx_ref_test_handle_checkout_webhook_wrong_amount',
+ 'currency_id': self.currency_euro.id,
+ 'acquirer_id': self.stripe.id,
+ 'partner_id': self.buyer_id,
+ 'payment_token_id': self.token.id,
+ 'type': 'server2server',
+ 'amount': 10
+ })
+ wrong_amount_stripe_payment_intent = bad_tx.with_context(off_session=True)._stripe_create_payment_intent()
+ tx = self.env['payment.transaction'].create({
+ 'reference': 'tx_ref_test_handle_checkout_webhook',
+ 'currency_id': self.currency_euro.id,
+ 'acquirer_id': self.stripe.id,
+ 'partner_id': self.buyer_id,
+ 'payment_token_id': self.token.id,
+ 'type': 'server2server',
+ 'amount': 30
+ })
+ tx.stripe_payment_intent = wrong_amount_stripe_payment_intent.get('payment_intent')
+ stripe_object = stripe_mocks.checkout_session_object
+
+ actual = self.env['payment.acquirer']._handle_checkout_webhook(stripe_object)
+
+ self.assertFalse(actual)
+
+ def test_handle_checkout_webhook_no_odoo_tx(self):
+ stripe_object = stripe_mocks.checkout_session_object
+
+ actual = self.stripe._handle_checkout_webhook(stripe_object)
+
+ self.assertFalse(actual)
+
+ @patch('odoo.addons.payment_stripe.models.payment.request')
+ @patch('odoo.addons.payment_stripe.models.payment.datetime')
+ def test_handle_checkout_webhook_no_stripe_tx(self, dt, request):
+ # pass signature verification
+ dt.utcnow.return_value.timestamp.return_value = 1591264652
+ request.httprequest.headers = {'Stripe-Signature': stripe_mocks.checkout_session_signature}
+ request.httprequest.data = stripe_mocks.checkout_session_body
+ # test setup
+ self.env['payment.transaction'].create({
+ 'reference': 'tx_ref_test_handle_checkout_webhook',
+ 'currency_id': self.currency_euro.id,
+ 'acquirer_id': self.stripe.id,
+ 'partner_id': self.buyer_id,
+ 'payment_token_id': self.token.id,
+ 'type': 'server2server',
+ 'amount': 30
+ })
+ stripe_object = stripe_mocks.checkout_session_object
+
+ with self.assertRaises(ValidationError):
+ self.stripe._handle_checkout_webhook(stripe_object)
+
+ @patch('odoo.addons.payment_stripe.models.payment.request')
+ @patch('odoo.addons.payment_stripe.models.payment.datetime')
+ def test_verify_stripe_signature(self, dt, request):
+ dt.utcnow.return_value.timestamp.return_value = 1591264652
+ request.httprequest.headers = {'Stripe-Signature': stripe_mocks.checkout_session_signature}
+ request.httprequest.data = stripe_mocks.checkout_session_body
+
+ actual = self.stripe._verify_stripe_signature()
+
+ self.assertTrue(actual)
+
+ @patch('odoo.addons.payment_stripe.models.payment.request')
+ @patch('odoo.addons.payment_stripe.models.payment.datetime')
+ def test_verify_stripe_signature_tampered_body(self, dt, request):
+ dt.utcnow.return_value.timestamp.return_value = 1591264652
+ request.httprequest.headers = {'Stripe-Signature': stripe_mocks.checkout_session_signature}
+ request.httprequest.data = stripe_mocks.checkout_session_body.replace(b'1500', b'10')
+
+ with self.assertRaises(ValidationError):
+ self.stripe._verify_stripe_signature()
+
+ @patch('odoo.addons.payment_stripe.models.payment.request')
+ @patch('odoo.addons.payment_stripe.models.payment.datetime')
+ def test_verify_stripe_signature_wrong_secret(self, dt, request):
+ dt.utcnow.return_value.timestamp.return_value = 1591264652
+ request.httprequest.headers = {'Stripe-Signature': stripe_mocks.checkout_session_signature}
+ request.httprequest.data = stripe_mocks.checkout_session_body
+ self.stripe.write({
+ 'stripe_webhook_secret': 'whsec_vG1fL6CMUouQ7cObF2VJprL_TAMPERED',
+ })
+
+ with self.assertRaises(ValidationError):
+ self.stripe._verify_stripe_signature()
+
+ @patch('odoo.addons.payment_stripe.models.payment.request')
+ @patch('odoo.addons.payment_stripe.models.payment.datetime')
+ def test_verify_stripe_signature_too_old(self, dt, request):
+ dt.utcnow.return_value.timestamp.return_value = 1591264652 + STRIPE_SIGNATURE_AGE_TOLERANCE + 1
+ request.httprequest.headers = {'Stripe-Signature': stripe_mocks.checkout_session_signature}
+ request.httprequest.data = stripe_mocks.checkout_session_body
+
+ with self.assertRaises(ValidationError):
+ self.stripe._verify_stripe_signature()