Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot assign None: "Card.customer" does not allow null values. #231

Open
ukch opened this issue Jan 7, 2016 · 5 comments
Open

Cannot assign None: "Card.customer" does not allow null values. #231

ukch opened this issue Jan 7, 2016 · 5 comments
Labels

Comments

@ukch
Copy link

ukch commented Jan 7, 2016

I got this through from the webhook:

ValueError: Cannot assign None: "Card.customer" does not allow null values.
  File "django/core/handlers/base.py", line 132, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "django/utils/decorators.py", line 34, in _wrapper
    return bound_func(*args, **kwargs)
  File "django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "django/utils/decorators.py", line 30, in bound_func
    return func.__get__(self, type(self))(*args2, **kwargs2)
  File "pinax/stripe/views.py", line 177, in dispatch
    return super(Webhook, self).dispatch(*args, **kwargs)
  File "django/views/generic/base.py", line 89, in dispatch
    return handler(request, *args, **kwargs)
  File "pinax/stripe/views.py", line 192, in post
    message=data
  File "pinax/stripe/actions/events.py", line 30, in add_event
    webhook.process()
  File "pinax/stripe/webhooks.py", line 91, in process
    self.process_webhook()
  File "pinax/stripe/webhooks.py", line 281, in process_webhook
    self.event.validated_message["data"]["object"]
  File "pinax/stripe/actions/sources.py", line 118, in sync_payment_source_from_stripe_data
    sync_card(customer, source)
  File "pinax/stripe/actions/sources.py", line 71, in sync_card
    defaults=defaults
  File "django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "django/db/models/query.py", line 407, in get_or_create
    return self._create_object_from_params(lookup, params)
  File "django/db/models/query.py", line 439, in _create_object_from_params
    obj = self.create(**params)
  File "django/db/models/query.py", line 346, in create
    obj = self.model(**kwargs)
  File "django/db/models/base.py", line 468, in __init__
    setattr(self, field.name, rel_obj)
  File "django/db/models/fields/related.py", line 621, in __set__
    (instance._meta.object_name, self.field.name)

This was the request body sent from Stripe:

{api_version: 2015-10-16, created: 1452130000, data: {object: {address_city: None, address_country: None, address_line1: None, address_line1_check: None, address_line2: None, address_state: None, address_zip: None, address_zip_check: None, brand: Visa, country: US, customer: cus_7foAIapD8EHGaE, cvc_check: pass, dynamic_last4: None, exp_month: 1, exp_year: 2020, fingerprint: Aj881ZHXRU2aVj5K, funding: credit, id: card_17QSXvEpqJ8aOjuY0CVtUfIJ, last4: 4242, metadata: {}, name: REDACTED, object: card, tokenization_method: None}}, id: evt_17QSY0EpqJ8aOjuYVmgj11yn, livemode: False, object: event, pending_webhooks: 1, request: req_7foAc39djNtYDB, type: customer.source.created}
@ossanna16 ossanna16 added the bug label Jan 7, 2016
@paltman
Copy link
Contributor

paltman commented Jan 19, 2016

As I follow the code path, it appears that what is happening is that you don't have the customer object in your database.

I think pinax-stripe should in fact do something different than blow up like this but I am not sure what yet.

In the meantime, I'm pretty sure you can avoid this by making sure you have customer records in your project.

  1. Is this a new project? In other words do you have users in your site that don't have customer records in Stripe?
  2. Is this a pre-existing Stripe account and you don't have users in your new site for?
  3. I suspect this might be a new project AND a new Stripe account and you just don't have a receiver setup to create customer records as each new user is created. If this is the case you can solve this by hooking up a signal on user creation or account signup (if using DUA) similar to have we've done in the Pinax Stripe starter project:
from django.dispatch import receiver
from account.signals import user_signed_up

from pinax.eventlog.models import log
from pinax.stripe.actions import customers


@receiver(user_signed_up)
def handle_user_signed_up(sender, **kwargs):
    log(
        user=kwargs.get("user"),
        action="USER_SIGNED_UP",
        extra={}
    )
    customers.create(kwargs.get("user"))

@ukch
Copy link
Author

ukch commented Jan 21, 2016

Yes, that is correct. Was I wrong in thinking the webhook does this automatically then?

@paltman paltman modified the milestone: 16.04 Mar 18, 2016
@paltman
Copy link
Contributor

paltman commented Mar 24, 2016

@ukch does what automatically?

@paltman paltman modified the milestones: post-16.04, 16.04 Mar 24, 2016
@jtauber jtauber modified the milestones: post-16.04, post-16.07 Jul 28, 2016
@lukeburden
Copy link
Contributor

I'm seeing this issue too when running customer.create() and providing the card parameter.

I think it's because there is a race condition in customer.create():

  1. stripe.Customer.create is called, passing in the source. This will result in customer.created and customer.source.created webhooks, arriving in indeterminate order.
  2. a Customer instance is created customer.source.created
  3. the stripe customer is sync'd

In some cases, it appears when the customer.source.created webhook arrives, the customer record in the database does not yet exist. This results in the none FK error.

It'd be preferable not to have to create customer records for all users ahead of time.

One option would be to change customers.create to use multiple API calls to Stripe rather than potentially creating a source and subscription in the one stripe.Customer.create call.

@blueyed
Copy link
Contributor

blueyed commented Oct 16, 2017

arriving in indeterminate order

I would assume that the order is correct, i.e. customer.created first, but that is just a feeling.

Related: #410

In case of the customer not existing already, it could also just get fetched an created then?!

@paltman paltman modified the milestones: post-16.07, Samwise Oct 20, 2017
@paltman paltman modified the milestones: Samwise, Rosie Oct 30, 2017
@paltman paltman modified the milestones: Rosie, December 2017 Sprint Dec 1, 2017
@paltman paltman removed this from the December 2017 Sprint milestone Nov 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants