dj-stripe: PaymentMethod.detach() does not set default_payment_method to None

Describe the bug

I found a bug today when a customer is detaching his PaymentMethod and he only had one.

Detaching works fine because PaymentMethod.customer is set to None, however Customer.default_payment_method still references the now detached PaymentMethod.

To Reproduce

  1. Create customer
  2. Attach a payment method
  3. Detach payment method

Expected behavior

If no other payment methods are available, set default_payment_method back to None. If any other payment method is available, we could pick one of them optionally.

As a workaround I am using the payment_method.detached webhook:


def payment_method_detached(event):
    """ Not sure if it's a bug in djstripe's PaymentMethod.detach() but default_payment_method is not set to None """

    customer_id = event.data["previous_attributes"]["customer"]
    customer = Customer.objects.get(id=customer_id)

    if not customer.payment_methods.all().exists():
        customer.default_payment_method = None
        customer.save()

Environment

  • dj-stripe version: 2.3.0
  • Your Stripe account’s default API version: 2019-11-05
  • Database: Postgres
  • Python version: 3.6.9
  • Django version: 2.2.11

Can you reproduce the issue with the latest version of master?

[Yes / No]

Additional context Add any other context about the problem here.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 22 (6 by maintainers)

Commits related to this issue

Most upvoted comments

@dbartenstein I was able to replicate this issue. This happens when the customer has atleast 1 or more subscriptions. This does not happen for one time payments for some reason. This is Stripe’s default behaviour. Also this is a more generic issue with nulled FKs not being synced. The current logic essentially skips their sync which is why sync fails when the last PM is removed. Or more generally when any FK is set to null as returned by the Stripe API.

I will think of a way to fix this generic issue.