Вопрос

I am currently working on a payement system in a Django app and decided to use Zebra to connect to Stripe. I am using a custom customer model. When I go to submit credit card information, I get two errors upon validation:

(Hidden field last_4_digits) This field is required.

and

(Hidden field stripe_token) This field is required.

These fields are meant to be filled in by some jquery magic that is included as a static file with Zebra, card-form.js. In the browser dev window, I can see that it correctly locates these static resrouces as well as the jquery library. For the life of me, I can't figure out why this jquery script isn't running when the form is submitted.

card-form.js

$(function() {
  console.log('got here.');
  $("#id_card_number").parents("form").submit(function() {
    if ( $("#id_card_number").is(":visible")) {
      var form = this;
       var card = {
    number:   $("#id_card_number").val(),
    expMonth: $("#id_card_expiry_month").val(),
    expYear:  $("#id_card_expiry_year").val(),
    cvc:      $("#id_card_cvv").val()
  };

  Stripe.createToken(card, function(status, response) {
    console.log(status);
    console.log(response);
    if (status === 200) {
      // console.log(status, response);
      $("#credit-card-errors").hide();
      $("#id_last_4_digits").val(response.card.last4);
      console.log(response.card.last4)
      console.log(response)
      $("#id_stripe_token").val(response.id);
      form.submit();
      $("button[type=submit]").attr("disabled","disabled").html("Submitting..")
    } else {
      $(".payment-errors").text(response.error.message);
      $("#user_submit").attr("disabled", false);
    }
  });

  return false;

} 

return true

  });
});

views.py:

from rest_framework import viewsets
from .serializers import BillingSerializer, PlanSerializer, InvoiceSerializer
from .models import Billing, Plan, Invoice
from stripe import Card
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.http import HttpResponse
from django.utils import simplejson
from zebra.conf import options
import stripe
stripe.api_key = options.STRIPE_SECRET
from zebra.forms import StripePaymentForm
from zebra.conf import options

#Update/create payment info for Stripe
@login_required
def update(request):
    if request.user.userprofile.type == 'gallery':
        user = request.user
        print user
        gallery = request.user.gallery_set.first()
        success_updating = False

        if request.method == 'POST':
            try:
                zebra_form = StripePaymentForm(request.POST)
                if zebra_form.is_valid():
                    if gallery.billing.stripe_customer_id is not None: #this may not work, need to check what default stripe_customer_id is
                        customer = stripe.Customer.retrieve(gallery.billing.stripe_customer_id)
                        print customer
                        customer.card = zebra_form.cleaned_data['stripe_token']
                        customer.save()

                        profile = user.get_profile()
                        profile.last_4_digits = zebra_form.cleaned_data['last_4_digits']
                        profile.stripe_customer_id = customer.id
                        profile.save()
                        success_updating = True
                    else:
                        gallery.billing.stripe_customer #creates a stripe customer record
                        gallery.billing.stripe.Plan = gallery.billing.plan
                        gallery.billing.save()
            except stripe.CardError, ce:
                        body = ce.json_body
                        err = body['error']
                        msg = 'Card Error'

                        success_updating = False

            except stripe.error.InvalidRequestError, ce:

                    body = ce.json_body
                    err = body['error']
                    msg = err['message'] 

                    success_updating = False
              # Invalid parameters were supplied to Stripe's API
                    #pass
            except stripe.error.AuthenticationError, ce:
              # Authentication with Stripe's API failed
              # (maybe you changed API keys recently)
                    body = ce.json_body
                    err = body['error']
                    msg = err['message'] 

                    success_updating = False
                    #pass
            except stripe.error.APIConnectionError, ce:
              # Network communication with Stripe failed
                    body = ce.json_body
                    err = body['error']
                    msg = err['message'] 

                    #success_updating = False
            except stripe.error.StripeError, ce:
              # Display a very generic error to the user, and maybe send
              # yourself an email

                    body = ce.json_body
                    err = body['error']
                    msg = err['message'] 

                    success_updating = False
                    #pass
            except Exception, ce:
              # Something else happened, completely unrelated to Stripe
                    # body = ce.json_body
                    # msg = body['error']

                    success_updating = False
                    #pass
        else: #Most likely a GET- render form
            zebra_form = StripePaymentForm()
        return render_to_response('zebra/basic_update.html',
        {
              'zebra_form': zebra_form,
              'publishable': options.STRIPE_PUBLISHABLE,
              'success_updating': success_updating,
        },
            context_instance=RequestContext(request)
        )

forms.py

class MonospaceForm(forms.Form):
    def addError(self, message):
        self._errors[NON_FIELD_ERRORS] = self.error_class([message])


class CardForm(MonospaceForm):
    last_4_digits = forms.CharField(required=True, min_length=4, max_length=4,
        widget=forms.HiddenInput())
    stripe_token = forms.CharField(required=True, widget=forms.HiddenInput())

class StripePaymentForm(CardForm):
    def __init__(self, *args, **kwargs):
        super(StripePaymentForm, self).__init__(*args, **kwargs)
        self.fields['card_cvv'].label = "Card CVC"
        self.fields['card_cvv'].help_text = "Card Verification Code; see rear of card."
        months = [ (m[0], u'%02d - %s' % (m[0], unicode(m[1])))
                    for m in sorted(MONTHS.iteritems()) ]
        self.fields['card_expiry_month'].choices = months

    card_number = forms.CharField(required=False, max_length=20,
        widget=NoNameTextInput())
    card_cvv = forms.CharField(required=False, max_length=4,
        widget=NoNameTextInput())
    card_expiry_month = forms.ChoiceField(required=False, widget=NoNameSelect(),
        choices=MONTHS.iteritems())
    card_expiry_year = forms.ChoiceField(required=False, widget=NoNameSelect(),
        choices=options.ZEBRA_CARD_YEARS_CHOICES)
Это было полезно?

Решение

I needed to do two things:

  1. use the correct version of JQuery
  2. set/send success_updating when the card info was successfully handled.

These cleard up the issue for me!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top