@@ -39,6 +39,35 @@ def __getitem__(self, key):
3939 return getattr (self , key )
4040
4141
42+ class MockCard (object ):
43+ def __init__ (self ):
44+ self .brand = "visa"
45+ self .last4 = "1234"
46+
47+ def __getitem__ (self , key ):
48+ return getattr (self , key )
49+
50+
51+ class MockPaymentMethod (object ):
52+ def __init__ (self , noCard = False ):
53+ if noCard :
54+ self .card = None
55+ return
56+
57+ self .card = MockCard ()
58+
59+ def __getitem__ (self , key ):
60+ return getattr (self , key )
61+
62+
63+ class MockPaymentIntent (object ):
64+ def __init__ (self , noCard = False ):
65+ self .payment_method = MockPaymentMethod (noCard )
66+
67+ def __getitem__ (self , key ):
68+ return getattr (self , key )
69+
70+
4271class StripeWebhookHandlerTests (APITestCase ):
4372 def setUp (self ):
4473 self .owner = OwnerFactory (
@@ -97,6 +126,8 @@ def test_invoice_payment_succeeded_sets_owner_delinquent_false(self):
97126 "object" : {
98127 "customer" : self .owner .stripe_customer_id ,
99128 "subscription" : self .owner .stripe_subscription_id ,
129+ "total" : 24000 ,
130+ "hosted_invoice_url" : "https://stripe.com" ,
100131 }
101132 },
102133 }
@@ -120,6 +151,72 @@ def test_invoice_payment_succeeded_sets_multiple_owners_delinquent_false(self):
120151 "object" : {
121152 "customer" : self .owner .stripe_customer_id ,
122153 "subscription" : self .owner .stripe_subscription_id ,
154+ "total" : 24000 ,
155+ "hosted_invoice_url" : "https://stripe.com" ,
156+ }
157+ },
158+ }
159+ )
160+
161+ self .owner .refresh_from_db ()
162+ self .other_owner .refresh_from_db ()
163+ assert response .status_code == status .HTTP_204_NO_CONTENT
164+ assert self .owner .delinquent is False
165+ assert self .other_owner .delinquent is False
166+
167+ @patch ("services.task.TaskService.send_email" )
168+ def test_invoice_payment_succeeded_emails_only_emails_delinquents (
169+ self ,
170+ mocked_send_email ,
171+ ):
172+ self .add_second_owner ()
173+ self .owner .delinquent = False
174+ self .owner .save ()
175+
176+ response = self ._send_event (
177+ payload = {
178+ "type" : "invoice.payment_succeeded" ,
179+ "data" : {
180+ "object" : {
181+ "customer" : self .owner .stripe_customer_id ,
182+ "subscription" : self .owner .stripe_subscription_id ,
183+ "total" : 24000 ,
184+ "hosted_invoice_url" : "https://stripe.com" ,
185+ }
186+ },
187+ }
188+ )
189+
190+ self .owner .refresh_from_db ()
191+ self .other_owner .refresh_from_db ()
192+ assert response .status_code == status .HTTP_204_NO_CONTENT
193+ assert self .owner .delinquent is False
194+
195+ mocked_send_email .assert_not_called ()
196+
197+ @patch ("services.task.TaskService.send_email" )
198+ def test_invoice_payment_succeeded_emails_delinquents (self , mocked_send_email ):
199+ non_admin = OwnerFactory (
email = "[email protected] " )
200+ admin_1 = OwnerFactory (
email = "[email protected] " )
201+ admin_2 = OwnerFactory (
email = "[email protected] " )
202+ self .owner .admins = [admin_1 .ownerid , admin_2 .ownerid ]
203+ self .owner .plan_activated_users = [non_admin .ownerid ]
204+ self .
owner .
email = "[email protected] " 205+ self .owner .delinquent = True
206+ self .owner .save ()
207+ self .add_second_owner ()
208+ self .other_owner .delinquent = False
209+ self .other_owner .save ()
210+
211+ response = self ._send_event (
212+ payload = {
213+ "type" : "invoice.payment_succeeded" ,
214+ "data" : {
215+ "object" : {
216+ "customer" : self .owner .stripe_customer_id ,
217+ "subscription" : self .owner .stripe_subscription_id ,
218+ "total" : 24000 ,
219+ "hosted_invoice_url" : "https://stripe.com" ,
123220 }
124221 },
125222 }
@@ -131,22 +228,54 @@ def test_invoice_payment_succeeded_sets_multiple_owners_delinquent_false(self):
131228 assert self .owner .delinquent is False
132229 assert self .other_owner .delinquent is False
133230
134- def test_invoice_payment_failed_sets_owner_delinquent_true (self ):
231+ expected_calls = [
232+ call (
233+ to_addr = self .owner .email ,
234+ subject = "You're all set" ,
235+ template_name = "success-after-failed-payment" ,
236+ amount = 240 ,
237+ cta_link = "https://stripe.com" ,
238+ date = datetime .now ().strftime ("%B %-d, %Y" ),
239+ ),
240+ call (
241+ to_addr = admin_1 .email ,
242+ subject = "You're all set" ,
243+ template_name = "success-after-failed-payment" ,
244+ amount = 240 ,
245+ cta_link = "https://stripe.com" ,
246+ date = datetime .now ().strftime ("%B %-d, %Y" ),
247+ ),
248+ call (
249+ to_addr = admin_2 .email ,
250+ subject = "You're all set" ,
251+ template_name = "success-after-failed-payment" ,
252+ amount = 240 ,
253+ cta_link = "https://stripe.com" ,
254+ date = datetime .now ().strftime ("%B %-d, %Y" ),
255+ ),
256+ ]
257+
258+ mocked_send_email .assert_has_calls (expected_calls )
259+
260+ @patch ("services.billing.stripe.PaymentIntent.retrieve" )
261+ def test_invoice_payment_failed_sets_owner_delinquent_true (
262+ self , retrieve_paymentintent_mock
263+ ):
135264 self .owner .delinquent = False
136265 self .owner .save ()
137266
267+ retrieve_paymentintent_mock .return_value = MockPaymentIntent ()
268+
138269 response = self ._send_event (
139270 payload = {
140271 "type" : "invoice.payment_failed" ,
141272 "data" : {
142273 "object" : {
143274 "customer" : self .owner .stripe_customer_id ,
144275 "subscription" : self .owner .stripe_subscription_id ,
145- "default_payment_method" : {
146- "card" : {"brand" : "visa" , "last4" : 1234 }
147- },
148276 "total" : 24000 ,
149277 "hosted_invoice_url" : "https://stripe.com" ,
278+ "payment_intent" : "payment_intent_asdf" ,
150279 }
151280 },
152281 }
@@ -156,25 +285,28 @@ def test_invoice_payment_failed_sets_owner_delinquent_true(self):
156285 assert response .status_code == status .HTTP_204_NO_CONTENT
157286 assert self .owner .delinquent is True
158287
159- def test_invoice_payment_failed_sets_multiple_owners_delinquent_true (self ):
288+ @patch ("services.billing.stripe.PaymentIntent.retrieve" )
289+ def test_invoice_payment_failed_sets_multiple_owners_delinquent_true (
290+ self , retrieve_paymentintent_mock
291+ ):
160292 self .add_second_owner ()
161293 self .owner .delinquent = False
162294 self .owner .save ()
163295 self .other_owner .delinquent = False
164296 self .other_owner .save ()
165297
298+ retrieve_paymentintent_mock .return_value = MockPaymentIntent ()
299+
166300 response = self ._send_event (
167301 payload = {
168302 "type" : "invoice.payment_failed" ,
169303 "data" : {
170304 "object" : {
171305 "customer" : self .owner .stripe_customer_id ,
172306 "subscription" : self .owner .stripe_subscription_id ,
173- "default_payment_method" : {
174- "card" : {"brand" : "visa" , "last4" : 1234 }
175- },
176307 "total" : 24000 ,
177308 "hosted_invoice_url" : "https://stripe.com" ,
309+ "payment_intent" : "payment_intent_asdf" ,
178310 }
179311 },
180312 }
@@ -187,7 +319,12 @@ def test_invoice_payment_failed_sets_multiple_owners_delinquent_true(self):
187319 assert self .other_owner .delinquent is True
188320
189321 @patch ("services.task.TaskService.send_email" )
190- def test_invoice_payment_failed_sends_email_to_admins (self , mocked_send_email ):
322+ @patch ("services.billing.stripe.PaymentIntent.retrieve" )
323+ def test_invoice_payment_failed_sends_email_to_admins (
324+ self ,
325+ retrieve_paymentintent_mock ,
326+ mocked_send_email ,
327+ ):
191328 non_admin = OwnerFactory (
email = "[email protected] " )
192329 admin_1 = OwnerFactory (
email = "[email protected] " )
193330 admin_2 = OwnerFactory (
email = "[email protected] " )
@@ -196,18 +333,18 @@ def test_invoice_payment_failed_sends_email_to_admins(self, mocked_send_email):
196333 self .
owner .
email = "[email protected] " 197334 self .owner .save ()
198335
336+ retrieve_paymentintent_mock .return_value = MockPaymentIntent ()
337+
199338 response = self ._send_event (
200339 payload = {
201340 "type" : "invoice.payment_failed" ,
202341 "data" : {
203342 "object" : {
204343 "customer" : self .owner .stripe_customer_id ,
205344 "subscription" : self .owner .stripe_subscription_id ,
206- "default_payment_method" : {
207- "card" : {"brand" : "visa" , "last4" : 1234 }
208- },
209345 "total" : 24000 ,
210346 "hosted_invoice_url" : "https://stripe.com" ,
347+ "payment_intent" : "payment_intent_asdf" ,
211348 }
212349 },
213350 }
@@ -225,7 +362,7 @@ def test_invoice_payment_failed_sends_email_to_admins(self, mocked_send_email):
225362 name = self .owner .username ,
226363 amount = 240 ,
227364 card_type = "visa" ,
228- last_four = 1234 ,
365+ last_four = " 1234" ,
229366 cta_link = "https://stripe.com" ,
230367 date = datetime .now ().strftime ("%B %-d, %Y" ),
231368 ),
@@ -236,7 +373,7 @@ def test_invoice_payment_failed_sends_email_to_admins(self, mocked_send_email):
236373 name = admin_1 .username ,
237374 amount = 240 ,
238375 card_type = "visa" ,
239- last_four = 1234 ,
376+ last_four = " 1234" ,
240377 cta_link = "https://stripe.com" ,
241378 date = datetime .now ().strftime ("%B %-d, %Y" ),
242379 ),
@@ -247,16 +384,20 @@ def test_invoice_payment_failed_sends_email_to_admins(self, mocked_send_email):
247384 name = admin_2 .username ,
248385 amount = 240 ,
249386 card_type = "visa" ,
250- last_four = 1234 ,
387+ last_four = " 1234" ,
251388 cta_link = "https://stripe.com" ,
252389 date = datetime .now ().strftime ("%B %-d, %Y" ),
253390 ),
254391 ]
392+
255393 mocked_send_email .assert_has_calls (expected_calls )
256394
257395 @patch ("services.task.TaskService.send_email" )
396+ @patch ("services.billing.stripe.PaymentIntent.retrieve" )
258397 def test_invoice_payment_failed_sends_email_to_admins_no_card (
259- self , mocked_send_email
398+ self ,
399+ retrieve_paymentintent_mock ,
400+ mocked_send_email ,
260401 ):
261402 non_admin = OwnerFactory (
email = "[email protected] " )
262403 admin_1 = OwnerFactory (
email = "[email protected] " )
@@ -266,6 +407,8 @@ def test_invoice_payment_failed_sends_email_to_admins_no_card(
266407 self .
owner .
email = "[email protected] " 267408 self .owner .save ()
268409
410+ retrieve_paymentintent_mock .return_value = MockPaymentIntent (noCard = True )
411+
269412 response = self ._send_event (
270413 payload = {
271414 "type" : "invoice.payment_failed" ,
@@ -276,6 +419,7 @@ def test_invoice_payment_failed_sends_email_to_admins_no_card(
276419 "default_payment_method" : None ,
277420 "total" : 24000 ,
278421 "hosted_invoice_url" : "https://stripe.com" ,
422+ "payment_intent" : "payment_intent_asdf" ,
279423 }
280424 },
281425 }
0 commit comments