Validate Stripe coupon via AJAX and Django view

750 views Asked by At

I’ve built a Django view so that I can validate a Stripe coupon code via an AJAX call, but I haven't gotten the code quite right yet.

I know that the view is at least getting triggered because the print statement I’ve put in there is working, but unfortunately it shows that coupon_code is None. Also, when I click on the “Apply” button after typing in a coupon code (valid or not), I’m getting GET http://localhost:8000/payments/coupon 404 (NOT FOUND). I thought maybe I should change the AJAX to a POST request, but then I get 405 (METHOD NOT ALLOWED).

Should I be using GET or POST? How can I successfully get the coupon code to the view for validation? What do I need to do to get the Stripe results from the view back into the template so I can apply the percent or amount off during the checkout process?

Here is my view:

class StripeCouponView(generic.View):
    def get(self, request):
        stripe.api_key=settings.STRIPE_SECRET_KEY
        if request.method == 'GET':
            coupon_code = request.GET.get('coupon_code')
            print "coupon_code IS", coupon_code
            try: 
                coupon_response = stripe.Coupon.retrieve(coupon_code)
                return HttpResponse(
                    json.dumps(coupon_response),
                    content_type="application/json"
                )
            except (requests.exceptions.HTTPError, Exception):
                return HttpResponseNotFound('BAD request')
        else:
            return HttpResponseNotFound('No coupon?')

Here is the applicable code in my urls.py:

from .views import StripeCouponView
# ... a lot of URLs
    url(r'^payments/coupon',
        StripeCouponView.as_view(),
        name='stripecoupon'),

Here is the HTML (built off of djstripe's subscribe_form.html):

{% extends "djstripe/base.html" %}
{% load static djstripe_tags %}

{% block title %}Subscribe{% endblock title %}

{% block content %}
<div class="row">
    {% for plan in PLAN_LIST %}
      {% with plan_count=PLAN_LIST|length %}
        <div class="col-xs-{{ 6|djdiv:plan_count|floatformat }} col-xs-offset-3">
      {% endwith %}
            <form
              {% if not customer.current_subscription or customer.current_subscription.status == CurrentSubscription.STATUS_CANCELLED %}
                  action="{% url 'djstripe:subscribe' %}" class="djstripe-subscribe"  
                  data-key="{{ STRIPE_PUBLIC_KEY }}"
                  data-amount="{{ plan.price }}"
                  data-name="{{ plan.name }}"
                  data-description="{{ plan.description }}"
              {% else %}
                  data-stripe-key="{{ STRIPE_PUBLIC_KEY }}" 
                  action="{% url 'djstripe:change_plan' %}" class="djstripe-change-plan"
              {% endif %}
            method="POST">


                {% csrf_token %}
                <input type="hidden" name="plan" value="{{ plan.plan }}" />
                <input name="stripe_token" type="hidden" /> 

                <!-- disable this when clicked -->
                <button style="width:100%; border-radius:4px;"
                  {% if customer.current_subscription.plan == plan.plan and customer.current_subscription.status != CurrentSubscription.STATUS_CANCELLED %}
                    disabled="true"
                  {% endif %}
                  type="submit" class="btn btn-primary">
                  {% comment %}
                    {% with image=plan.image|default:"img/default-plan-image.png" %}
                      <img src="{% static image %}" class="img-thumbnail" />
                    {% endwith %}
                  {% endcomment %}
                  <h3>{{ plan.name }}</h3>
                  <p>{{ plan.description }}</p>
                </button>
              {% if not customer.current_subscription or customer.current_subscription.status == CurrentSubscription.STATUS_CANCELLED %}
                <!-- do nothing -->
              {% elif customer.current_subscription.plan == plan.plan %}
                <h4>Your Current Plan</h4>
              {% endif %}  
            </form>
            <span class="discount-span"><label>Discount Code:</label>
              <input type="text" id="discount-field"/>
              <button id="apply-coupon">Apply</button></span>
              <div id="coupon-msg">
              </div>
        </div>
    {% endfor %}
</div>
{% endblock content %}

Here's the JavaScript where the Stripe checkout action occurs:

 {% block bottom_js %}
    {{ block.super }}
    <script src="https://checkout.stripe.com/v2/checkout.js"></script>
    <script type="text/javascript">
    $('#apply-coupon').on('click', function (e) {
        $.ajax({
        type: 'GET',
        url: '{% url 'stripecoupon' %}',
        data: { coupon_code : $('#discount-field').val() },
        success: function(results){
          $('#discount-field').val('');
          if (results) {
            $('#coupon-msg').html("Valid code.")
            // Do something here to send results to StripeCheckout?
          }
          else {
            $('#coupon-msg').html("Invalid code.")
          }
        }
        });
    });

    $(function() {
        $('body').on("click", '.djstripe-subscribe button[type=submit]', function(e) {
          e.preventDefault();
          // retrieve current $(".djstripe-subscribe")
          var $form = $(e.target).parents('form'),
              token = function(res) {
                $form.find("input[name=stripe_token]").val(res.id);
                $("button[type=submit]").attr("disabled", "true");
                $('#in-progress').modal({"keyboard": false})
                $('.progress-bar').animate({width:'+=100%'}, 2000);
                $form.trigger("submit");
              };
          StripeCheckout.open({
            key:         '{{ STRIPE_PUBLIC_KEY }}',
            email:       '{{ user.email }}',
            name:        'Premium Subscription',
            description:  'Curated Monthly Content',
            panelLabel:  'Subscribe',
            // amount: whatever the coupon code's percent_off or amount_off is.
            token:       token,
            // coupon: coupon
          });
          return false;
        });
          {% if PLAN_LIST|length > 1 %}
            $('.djstripe-change-plan').click(function(e){
                $("button[type=submit]").attr("disabled", "true");
                $('#in-progress').modal({"keyboard": false})
                $('.progress-bar').animate({width:'+=100%'}, 2000);
                var $form = $(this);
                $form.trigger("submit");
            });
          {% endif %}
    });
    </script>
    {% endblock %}
0

There are 0 answers