Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upCard.api_retrieve() will crash if the customer associated with the card has been deleted #432
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jleclanche
Feb 28, 2017
Contributor
This is pretty hard to fix without reworking the djstripe api because api_retrieve() is always expected to either return a real object, or a native stripe error.
We can check for if "sources" not in customer... but then what to do with that? raise our own error? return none? neither of those are handled anywhere.
|
This is pretty hard to fix without reworking the djstripe api because api_retrieve() is always expected to either return a real object, or a native stripe error. We can check for |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jleclanche
Feb 28, 2017
Contributor
Something like this should work, but ain't pretty:
diff --git a/djstripe/stripe_objects.py b/djstripe/stripe_objects.py
index 600bfd8..161b0bb 100644
--- a/djstripe/stripe_objects.py
+++ b/djstripe/stripe_objects.py
@@ -1199,10 +1199,13 @@ Fields not implemented:
def api_retrieve(self, api_key=settings.STRIPE_SECRET_KEY):
# OVERRIDING the parent version of this function
# Cards must be manipulated through a customer or account.
- # TODO: When managed accounts are supported, this method needs to check if either a customer or
- # account is supplied to determine the correct object to use.
-
- return self.customer.api_retrieve(api_key=api_key).sources.retrieve(self.stripe_id, expand=self.expand_fields)
+ # TODO: When managed accounts are supported, this method needs to check if
+ # either a customer or account is supplied to determine the correct object to use.
+ customer = self.customer.api_retrieve(api_key=api_key)
+ if "sources" not in customer:
+ # The customer has most likely been deleted and doesn't have a sources attribute
+ raise InvalidRequestError("No such source: %s" % (self.stripe_id))
+ return customer.sources.retrieve(self.stripe_id, expand=self.expand_fields)
@staticmethod
def _get_customer_from_kwargs(**kwargs):|
Something like this should work, but ain't pretty: diff --git a/djstripe/stripe_objects.py b/djstripe/stripe_objects.py
index 600bfd8..161b0bb 100644
--- a/djstripe/stripe_objects.py
+++ b/djstripe/stripe_objects.py
@@ -1199,10 +1199,13 @@ Fields not implemented:
def api_retrieve(self, api_key=settings.STRIPE_SECRET_KEY):
# OVERRIDING the parent version of this function
# Cards must be manipulated through a customer or account.
- # TODO: When managed accounts are supported, this method needs to check if either a customer or
- # account is supplied to determine the correct object to use.
-
- return self.customer.api_retrieve(api_key=api_key).sources.retrieve(self.stripe_id, expand=self.expand_fields)
+ # TODO: When managed accounts are supported, this method needs to check if
+ # either a customer or account is supplied to determine the correct object to use.
+ customer = self.customer.api_retrieve(api_key=api_key)
+ if "sources" not in customer:
+ # The customer has most likely been deleted and doesn't have a sources attribute
+ raise InvalidRequestError("No such source: %s" % (self.stripe_id))
+ return customer.sources.retrieve(self.stripe_id, expand=self.expand_fields)
@staticmethod
def _get_customer_from_kwargs(**kwargs): |
jleclanche commentedFeb 28, 2017
•
edited
Situation: Calling
on_delete_subscriber_purge_customeron a customer that has already been deleted by Stripe.Eventually, we enter
Customer.purge()which hitsfor source in self.sources.all(): source.remove().However, if the customer has already been deleted, calling
remove()on a source whose customer has already been deleted will crash, because it first callsretrieve()on the card object. This is caused by theStripeCard.api_retrievemethod:Now, what happens if
self.customer.api_retrieve(...)returns a deleted customer? See for yourself: