Stripe checkout #104411
@ -0,0 +1,51 @@
|
|||||||
|
responses:
|
||||||
|
- response:
|
||||||
|
auto_calculate_content_length: false
|
||||||
|
body: "{\n \"id\": \"cus_QGeKULCHd4p9o2\",\n \"object\": \"customer\",\n \"\
|
||||||
|
address\": null,\n \"balance\": 0,\n \"created\": 1718021356,\n \"currency\"\
|
||||||
|
: null,\n \"default_source\": null,\n \"delinquent\": false,\n \"description\"\
|
||||||
|
: null,\n \"discount\": null,\n \"email\": \"billing@example.com\",\n \"\
|
||||||
|
invoice_prefix\": \"0ABA8C57\",\n \"invoice_settings\": {\n \"custom_fields\"\
|
||||||
|
: null,\n \"default_payment_method\": null,\n \"footer\": null,\n \"\
|
||||||
|
rendering_options\": null\n },\n \"livemode\": false,\n \"metadata\": {},\n\
|
||||||
|
\ \"name\": \"\u0410\u043B\u0435\u043A\u0441\u0435\u0439 \u041D.\",\n \"phone\"\
|
||||||
|
: null,\n \"preferred_locales\": [],\n \"shipping\": null,\n \"tax_exempt\"\
|
||||||
|
: \"none\",\n \"test_clock\": null\n}"
|
||||||
|
content_type: text/plain; charset=utf-8
|
||||||
|
method: POST
|
||||||
|
status: 200
|
||||||
|
url: https://api.stripe.com/v1/customers
|
||||||
|
- response:
|
||||||
|
auto_calculate_content_length: false
|
||||||
|
body: "{\n \"id\": \"cs_test_c1QeSt36UcbmnmrXJnEYZpWakr377WPMfbWLeR9d3ZBYJPWXRUJ3TQ0UG9\"\
|
||||||
|
,\n \"object\": \"checkout.session\",\n \"after_expiration\": null,\n \"\
|
||||||
|
allow_promotion_codes\": null,\n \"amount_subtotal\": null,\n \"amount_total\"\
|
||||||
|
: null,\n \"automatic_tax\": {\n \"enabled\": false,\n \"liability\"\
|
||||||
|
: null,\n \"status\": null\n },\n \"billing_address_collection\": null,\n\
|
||||||
|
\ \"cancel_url\": \"http://testserver/settings/billing/\",\n \"client_reference_id\"\
|
||||||
|
: null,\n \"client_secret\": null,\n \"consent\": null,\n \"consent_collection\"\
|
||||||
|
: null,\n \"created\": 1718021357,\n \"currency\": null,\n \"currency_conversion\"\
|
||||||
|
: null,\n \"custom_fields\": [],\n \"custom_text\": {\n \"after_submit\"\
|
||||||
|
: null,\n \"shipping_address\": null,\n \"submit\": null,\n \"terms_of_service_acceptance\"\
|
||||||
|
: null\n },\n \"customer\": \"cus_QGeKULCHd4p9o2\",\n \"customer_creation\"\
|
||||||
|
: null,\n \"customer_details\": {\n \"address\": null,\n \"email\": \"\
|
||||||
|
billing@example.com\",\n \"name\": null,\n \"phone\": null,\n \"tax_exempt\"\
|
||||||
|
: null,\n \"tax_ids\": null\n },\n \"customer_email\": null,\n \"expires_at\"\
|
||||||
|
: 1718107757,\n \"invoice\": null,\n \"invoice_creation\": null,\n \"livemode\"\
|
||||||
|
: false,\n \"locale\": null,\n \"metadata\": {},\n \"mode\": \"setup\",\n\
|
||||||
|
\ \"payment_intent\": null,\n \"payment_link\": null,\n \"payment_method_collection\"\
|
||||||
|
: \"always\",\n \"payment_method_configuration_details\": null,\n \"payment_method_options\"\
|
||||||
|
: {\n \"card\": {\n \"request_three_d_secure\": \"automatic\"\n }\n\
|
||||||
|
\ },\n \"payment_method_types\": [\n \"card\",\n \"link\",\n \"paypal\"\
|
||||||
|
\n ],\n \"payment_status\": \"no_payment_required\",\n \"phone_number_collection\"\
|
||||||
|
: {\n \"enabled\": false\n },\n \"recovered_from\": null,\n \"saved_payment_method_options\"\
|
||||||
|
: null,\n \"setup_intent\": \"seti_1PQ72HE4KAUB5djsPthAKRdZ\",\n \"shipping_address_collection\"\
|
||||||
|
: null,\n \"shipping_cost\": null,\n \"shipping_details\": null,\n \"shipping_options\"\
|
||||||
|
: [],\n \"status\": \"open\",\n \"submit_type\": null,\n \"subscription\"\
|
||||||
|
: null,\n \"success_url\": \"http://testserver/subscription/1/payment-method/change/{CHECKOUT_SESSION_ID}/\"\
|
||||||
|
,\n \"total_details\": null,\n \"ui_mode\": \"hosted\",\n \"url\": \"https://checkout.stripe.com/c/pay/cs_test_c1QeSt36UcbmnmrXJnEYZpWakr377WPMfbWLeR9d3ZBYJPWXRUJ3TQ0UG9#fidkdWxOYHwnPyd1blpxYHZxWjA0VUpnNzNAMU5EUEcwYW92dWIwclxRMzQ8ZkxsUDRET2dPbTVidnBCNEJTdlBJQTRJYFF2c09BMEFBdlxVT19USGpWSXRSXFJwdm5UQXRpdVw2Rmp%2FZ11NNTU3fHdHUl1JTCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl\"\
|
||||||
|
\n}"
|
||||||
|
content_type: text/plain
|
||||||
|
method: POST
|
||||||
|
status: 200
|
||||||
|
url: https://api.stripe.com/v1/checkout/sessions
|
@ -0,0 +1,67 @@
|
|||||||
|
responses:
|
||||||
|
- response:
|
||||||
|
auto_calculate_content_length: false
|
||||||
|
body: "{\n \"id\": \"cs_test_c1QeSt36UcbmnmrXJnEYZpWakr377WPMfbWLeR9d3ZBYJPWXRUJ3TQ0UG9\"\
|
||||||
|
,\n \"object\": \"checkout.session\",\n \"after_expiration\": null,\n \"\
|
||||||
|
allow_promotion_codes\": null,\n \"amount_subtotal\": null,\n \"amount_total\"\
|
||||||
|
: null,\n \"automatic_tax\": {\n \"enabled\": false,\n \"liability\"\
|
||||||
|
: null,\n \"status\": null\n },\n \"billing_address_collection\": null,\n\
|
||||||
|
\ \"cancel_url\": \"http://testserver/settings/billing/\",\n \"client_reference_id\"\
|
||||||
|
: null,\n \"client_secret\": null,\n \"consent\": null,\n \"consent_collection\"\
|
||||||
|
: null,\n \"created\": 1718021357,\n \"currency\": null,\n \"currency_conversion\"\
|
||||||
|
: null,\n \"custom_fields\": [],\n \"custom_text\": {\n \"after_submit\"\
|
||||||
|
: null,\n \"shipping_address\": null,\n \"submit\": null,\n \"terms_of_service_acceptance\"\
|
||||||
|
: null\n },\n \"customer\": \"cus_QGeKULCHd4p9o2\",\n \"customer_creation\"\
|
||||||
|
: null,\n \"customer_details\": {\n \"address\": null,\n \"email\": \"\
|
||||||
|
billing@example.com\",\n \"name\": \"\u0410\u043B\u0435\u043A\u0441\u0435\
|
||||||
|
\u0439 \u041D.\",\n \"phone\": null,\n \"tax_exempt\": null,\n \"tax_ids\"\
|
||||||
|
: []\n },\n \"customer_email\": null,\n \"expires_at\": 1718107757,\n \"\
|
||||||
|
invoice\": null,\n \"invoice_creation\": null,\n \"livemode\": false,\n \"\
|
||||||
|
locale\": null,\n \"metadata\": {},\n \"mode\": \"setup\",\n \"payment_intent\"\
|
||||||
|
: null,\n \"payment_link\": null,\n \"payment_method_collection\": \"always\"\
|
||||||
|
,\n \"payment_method_configuration_details\": null,\n \"payment_method_options\"\
|
||||||
|
: {\n \"card\": {\n \"request_three_d_secure\": \"automatic\"\n }\n\
|
||||||
|
\ },\n \"payment_method_types\": [\n \"card\",\n \"link\",\n \"paypal\"\
|
||||||
|
\n ],\n \"payment_status\": \"no_payment_required\",\n \"phone_number_collection\"\
|
||||||
|
: {\n \"enabled\": false\n },\n \"recovered_from\": null,\n \"saved_payment_method_options\"\
|
||||||
|
: null,\n \"setup_intent\": {\n \"id\": \"seti_1PQ72HE4KAUB5djsPthAKRdZ\"\
|
||||||
|
,\n \"object\": \"setup_intent\",\n \"application\": null,\n \"automatic_payment_methods\"\
|
||||||
|
: null,\n \"cancellation_reason\": null,\n \"client_secret\": \"seti_1PQ72HE4KAUB5djsPthAKRdZ_secret_QGeKD74KJNAouKtjbevE1O3dwVKxxt7\"\
|
||||||
|
,\n \"created\": 1718021357,\n \"customer\": \"cus_QGeKULCHd4p9o2\",\n\
|
||||||
|
\ \"description\": null,\n \"flow_directions\": null,\n \"last_setup_error\"\
|
||||||
|
: null,\n \"latest_attempt\": \"setatt_1PQ7DuE4KAUB5djsZtPVk4XB\",\n \"\
|
||||||
|
livemode\": false,\n \"mandate\": null,\n \"metadata\": {\n \"subscription_id\"\
|
||||||
|
: \"1\"\n },\n \"next_action\": null,\n \"on_behalf_of\": null,\n \
|
||||||
|
\ \"payment_method\": {\n \"id\": \"pm_1PQ7DsE4KAUB5djsw4z0K5PS\",\n\
|
||||||
|
\ \"object\": \"payment_method\",\n \"allow_redisplay\": \"always\"\
|
||||||
|
,\n \"billing_details\": {\n \"address\": {\n \"city\"\
|
||||||
|
: null,\n \"country\": \"NL\",\n \"line1\": null,\n \
|
||||||
|
\ \"line2\": null,\n \"postal_code\": null,\n \"state\"\
|
||||||
|
: null\n },\n \"email\": \"billing@example.com\",\n \"\
|
||||||
|
name\": \"John Smith\",\n \"phone\": null\n },\n \"card\":\
|
||||||
|
\ {\n \"brand\": \"visa\",\n \"checks\": {\n \"address_line1_check\"\
|
||||||
|
: null,\n \"address_postal_code_check\": null,\n \"cvc_check\"\
|
||||||
|
: \"pass\"\n },\n \"country\": \"US\",\n \"display_brand\"\
|
||||||
|
: \"visa\",\n \"exp_month\": 12,\n \"exp_year\": 2033,\n \
|
||||||
|
\ \"fingerprint\": \"YcmpGi38fZZuBsh4\",\n \"funding\": \"credit\"\
|
||||||
|
,\n \"generated_from\": null,\n \"last4\": \"4242\",\n \
|
||||||
|
\ \"networks\": {\n \"available\": [\n \"visa\"\n \
|
||||||
|
\ ],\n \"preferred\": null\n },\n \"three_d_secure_usage\"\
|
||||||
|
: {\n \"supported\": true\n },\n \"wallet\": null\n \
|
||||||
|
\ },\n \"created\": 1718022076,\n \"customer\": \"cus_QGeKULCHd4p9o2\"\
|
||||||
|
,\n \"livemode\": false,\n \"metadata\": {},\n \"type\": \"card\"\
|
||||||
|
\n },\n \"payment_method_configuration_details\": null,\n \"payment_method_options\"\
|
||||||
|
: {\n \"card\": {\n \"mandate_options\": null,\n \"network\"\
|
||||||
|
: null,\n \"request_three_d_secure\": \"automatic\"\n }\n },\n\
|
||||||
|
\ \"payment_method_types\": [\n \"card\",\n \"link\",\n \"\
|
||||||
|
paypal\"\n ],\n \"single_use_mandate\": null,\n \"status\": \"succeeded\"\
|
||||||
|
,\n \"usage\": \"off_session\"\n },\n \"shipping_address_collection\":\
|
||||||
|
\ null,\n \"shipping_cost\": null,\n \"shipping_details\": null,\n \"shipping_options\"\
|
||||||
|
: [],\n \"status\": \"complete\",\n \"submit_type\": null,\n \"subscription\"\
|
||||||
|
: null,\n \"success_url\": \"http://testserver/subscription/1/payment-method/change/{CHECKOUT_SESSION_ID}/\"\
|
||||||
|
,\n \"total_details\": null,\n \"ui_mode\": \"hosted\",\n \"url\": null\n\
|
||||||
|
}"
|
||||||
|
content_type: text/plain; charset=utf-8
|
||||||
|
method: GET
|
||||||
|
status: 200
|
||||||
|
url: https://api.stripe.com/v1/checkout/sessions/cs_test_c1QeSt36UcbmnmrXJnEYZpWakr377WPMfbWLeR9d3ZBYJPWXRUJ3TQ0UG9?expand%5B0%5D=setup_intent&expand%5B1%5D=setup_intent.payment_method
|
@ -21,6 +21,7 @@ import subscriptions.tasks
|
|||||||
import users.tasks
|
import users.tasks
|
||||||
import users.tests.util as util
|
import users.tests.util as util
|
||||||
|
|
||||||
|
responses_dir = 'subscriptions/tests/_responses/'
|
||||||
required_address_data = {
|
required_address_data = {
|
||||||
'country': 'NL',
|
'country': 'NL',
|
||||||
'email': 'my.billing.email@example.com',
|
'email': 'my.billing.email@example.com',
|
||||||
@ -176,7 +177,7 @@ class TestGETJoinView(BaseSubscriptionTestCase):
|
|||||||
class TestPOSTJoinView(BaseSubscriptionTestCase):
|
class TestPOSTJoinView(BaseSubscriptionTestCase):
|
||||||
url_usd = reverse('subscriptions:join-billing-details', kwargs={'plan_variation_id': 1})
|
url_usd = reverse('subscriptions:join-billing-details', kwargs={'plan_variation_id': 1})
|
||||||
url = reverse('subscriptions:join-billing-details', kwargs={'plan_variation_id': 2})
|
url = reverse('subscriptions:join-billing-details', kwargs={'plan_variation_id': 2})
|
||||||
responses._add_from_file('stripe_create_checkout_session.yaml')
|
responses._add_from_file(f'{responses_dir}stripe_create_checkout_session.yaml')
|
||||||
|
|
||||||
def test_post_updates_billing_address_and_customer_renders_next_form_de(self):
|
def test_post_updates_billing_address_and_customer_renders_next_form_de(self):
|
||||||
customer = create_customer_with_billing_address(vat_number='', country='DE')
|
customer = create_customer_with_billing_address(vat_number='', country='DE')
|
||||||
|
@ -5,11 +5,15 @@ from django.urls import reverse
|
|||||||
from looper.models import PaymentMethod, PaymentMethodAuthentication, Gateway
|
from looper.models import PaymentMethod, PaymentMethodAuthentication, Gateway
|
||||||
from looper.money import Money
|
from looper.money import Money
|
||||||
from looper.tests.factories import SubscriptionFactory
|
from looper.tests.factories import SubscriptionFactory
|
||||||
|
import responses
|
||||||
|
|
||||||
|
# from responses import _recorder
|
||||||
|
|
||||||
from common.tests.factories.users import UserFactory
|
from common.tests.factories.users import UserFactory
|
||||||
from subscriptions.tests.base import BaseSubscriptionTestCase
|
from subscriptions.tests.base import BaseSubscriptionTestCase
|
||||||
import subscriptions.tasks
|
import subscriptions.tasks
|
||||||
|
|
||||||
|
responses_dir = 'subscriptions/tests/_responses/'
|
||||||
required_address_data = {
|
required_address_data = {
|
||||||
'country': 'NL',
|
'country': 'NL',
|
||||||
'email': 'my.billing.email@example.com',
|
'email': 'my.billing.email@example.com',
|
||||||
@ -99,6 +103,8 @@ class TestSubscriptionSettingsChangePaymentMethod(BaseSubscriptionTestCase):
|
|||||||
url_name = 'subscriptions:payment-method-change'
|
url_name = 'subscriptions:payment-method-change'
|
||||||
success_url_name = 'user-settings-billing'
|
success_url_name = 'user-settings-billing'
|
||||||
|
|
||||||
|
# @_recorder.record(file_path=f'{responses_dir}stripe_create_checkout_session_setup.yaml')
|
||||||
|
# @_recorder.record(file_path=f'{responses_dir}stripe_retrieve_checkout_session_setup.yaml')
|
||||||
def test_can_change_payment_method_from_bank_to_credit_card_with_sca(self):
|
def test_can_change_payment_method_from_bank_to_credit_card_with_sca(self):
|
||||||
bank = Gateway.objects.get(name='bank')
|
bank = Gateway.objects.get(name='bank')
|
||||||
subscription = SubscriptionFactory(
|
subscription = SubscriptionFactory(
|
||||||
@ -112,15 +118,23 @@ class TestSubscriptionSettingsChangePaymentMethod(BaseSubscriptionTestCase):
|
|||||||
self.client.force_login(self.user)
|
self.client.force_login(self.user)
|
||||||
|
|
||||||
url = reverse(self.url_name, kwargs={'subscription_id': subscription.pk})
|
url = reverse(self.url_name, kwargs={'subscription_id': subscription.pk})
|
||||||
data = {
|
with responses.RequestsMock() as rsps:
|
||||||
**self.shared_payment_form_data,
|
rsps._add_from_file(f'{responses_dir}stripe_create_checkout_session_setup.yaml')
|
||||||
'gateway': 'braintree',
|
response = self.client.post(url)
|
||||||
'payment_method_nonce': 'fake-three-d-secure-visa-full-authentication-nonce',
|
|
||||||
}
|
|
||||||
response = self.client.post(url, data=data)
|
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertEqual(response['Location'], reverse(self.success_url_name))
|
expected_redirect_url = 'https://checkout.stripe.com/c/pay/cs_test_c1QeSt36UcbmnmrXJnEYZpWakr377WPMfbWLeR9d3ZBYJPWXRUJ3TQ0UG9#fidkdWxOYHwnPyd1blpxYHZxWjA0VUpnNzNAMU5EUEcwYW92dWIwclxRMzQ8ZkxsUDRET2dPbTVidnBCNEJTdlBJQTRJYFF2c09BMEFBdlxVT19USGpWSXRSXFJwdm5UQXRpdVw2Rmp%2FZ11NNTU3fHdHUl1JTCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl'
|
||||||
|
self.assertEqual(response['Location'], expected_redirect_url, response['Location'])
|
||||||
|
|
||||||
|
# Pretend that checkout session was completed and we've returned to the success page with its ID:
|
||||||
|
checkout_session_id = 'cs_test_c1QeSt36UcbmnmrXJnEYZpWakr377WPMfbWLeR9d3ZBYJPWXRUJ3TQ0UG9'
|
||||||
|
success_url = url + f'{checkout_session_id}/'
|
||||||
|
with responses.RequestsMock() as rsps:
|
||||||
|
rsps._add_from_file(f'{responses_dir}stripe_retrieve_checkout_session_setup.yaml')
|
||||||
|
response = self.client.get(success_url)
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertEqual(response['Location'], '/subscription/1/manage/')
|
||||||
|
|
||||||
# New payment method was created
|
# New payment method was created
|
||||||
self.assertEqual(PaymentMethod.objects.count(), 2)
|
self.assertEqual(PaymentMethod.objects.count(), 2)
|
||||||
|
|
||||||
@ -130,40 +144,9 @@ class TestSubscriptionSettingsChangePaymentMethod(BaseSubscriptionTestCase):
|
|||||||
self.assertNotEqual(subscription.payment_method_id, payment_method.pk)
|
self.assertNotEqual(subscription.payment_method_id, payment_method.pk)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
str(subscription.payment_method),
|
str(subscription.payment_method),
|
||||||
'Visa credit card ending in 0002',
|
'visa credit card ending in 4242',
|
||||||
)
|
)
|
||||||
# SCA was stored
|
# SCA isn't stored for Stripe payment methods
|
||||||
self.assertIsNotNone(PaymentMethodAuthentication.objects.first())
|
|
||||||
|
|
||||||
def test_can_change_payment_method_from_credit_card_to_bank(self):
|
|
||||||
braintree = Gateway.objects.get(name='braintree')
|
|
||||||
subscription = SubscriptionFactory(
|
|
||||||
customer=self.user.customer,
|
|
||||||
payment_method__customer_id=self.user.customer.pk,
|
|
||||||
payment_method__gateway=braintree,
|
|
||||||
)
|
|
||||||
self.assertEqual(PaymentMethod.objects.count(), 1)
|
|
||||||
payment_method = subscription.payment_method
|
|
||||||
self.client.force_login(self.user)
|
|
||||||
|
|
||||||
url = reverse(self.url_name, kwargs={'subscription_id': subscription.pk})
|
|
||||||
data = {
|
|
||||||
**self.shared_payment_form_data,
|
|
||||||
'gateway': 'bank',
|
|
||||||
'payment_method_nonce': 'unused',
|
|
||||||
}
|
|
||||||
response = self.client.post(url, data=data)
|
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 302)
|
|
||||||
self.assertEqual(response['Location'], reverse(self.success_url_name))
|
|
||||||
# New payment method was created
|
|
||||||
self.assertEqual(PaymentMethod.objects.count(), 2)
|
|
||||||
|
|
||||||
subscription.refresh_from_db()
|
|
||||||
subscription.payment_method.refresh_from_db()
|
|
||||||
# Subscription's payment method was changed to bank transfer
|
|
||||||
self.assertNotEqual(subscription.payment_method_id, payment_method.pk)
|
|
||||||
self.assertEqual(str(subscription.payment_method), 'Bank Transfer')
|
|
||||||
self.assertIsNone(PaymentMethodAuthentication.objects.first())
|
self.assertIsNone(PaymentMethodAuthentication.objects.first())
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user