I needed to do two things:
- use the correct version of JQuery
- set/send success_updating when the card info was successfully handled.
These cleard up the issue for me!
Вопрос
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:
These cleard up the issue for me!