Django / Python Stripe stripeToken не загружается / работает неправильно - PullRequest
0 голосов
/ 02 апреля 2020

Я пытаюсь оплатить подписку на Stripe API в тестовом режиме, и моя плата продолжает снижаться. Кажется, все работает нормально, за исключением того, что я не могу получить "stripeToken" через POST. Я проверил это, напечатав различные переменные, которые мне нужны, и все они работают нормально ... но когда дело доходит до печати stripeToken, я получаю эту ошибку:

MultiValueDictKeyError at /memberships/payment/
'stripeToken'
Request Method: POST
Request URL:    http://127.0.0.1:8000/memberships/payment/
Django Version: 2.2
Exception Type: MultiValueDictKeyError
Exception Value:    
'stripeToken'
Exception Location: /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/utils/datastructures.py in __getitem__, line 80
Python Executable:  /Library/Frameworks/Python.framework/Versions/3.8/bin/python3
Python Version: 3.8.2
Python Path:    
['/Users/fred/Documents/yonder/videoservice',
 '/Library/Frameworks/Python.framework/Versions/3.8/lib/python38.zip',
 '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8',
 '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/lib-dynload',
 '/Users/fred/Library/Python/3.8/lib/python/site-packages',
 '/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages']
Server time:    Wed, 1 Apr 2020 16:20:53 -0700

Вот мой код представления:

def PaymentView(request):
    user_membership = get_user_membership(request)
    try:
        selected_membership = get_selected_membership(request)
    except:
        return redirect(reverse("memberships:select"))
    publishKey = settings.STRIPE_PUBLISHABLE_KEY
    if request.method == "POST":
        token = request.POST['stripeToken']
        try:
            token = request.POST['stripeToken']

            customer = stripe.Customer.retrieve(user_membership.stripe_customer_id)
            customer.source = token # 4242424242424242
            customer.save()

            subscription = stripe.Subscription.create(
                customer=user_membership.stripe_customer_id,
                items=[
                    { "plan": selected_membership.stripe_plan_id },
                ]
            )

            return redirect(reverse('memberships:update-transactions',
                                    kwargs={
                                        'subscription_id': subscription.id
                                    }))

        except:
            messages.info(request, "An error has occurred, investigate it in the console")

    context = {
        'publishKey': publishKey,
        'selected_membership': selected_membership
    }

    return render(request, "memberships/membership_payment.html", context)

А вот мой HTML код

{% extends 'courses/base.html' %}
{% load static %}

{% block content %}

 <link rel="stylesheet" type="text/css" href="{% static 'css/checkout.css' %}">


<div class="container">
    <div class="row">
        <h1>Payment</h1>
        <div class="col-sm-4 col-md-4">
            <p>Selected Membership: {{ selected_membership }}</p>
            <p>Price: ${{ selected_membership.price }}<small>/mo.</small></p>



            <button onclick="toggleDisplay();" class="btn btn-warning" style="width: 100%;">Checkout with a credit card</button>


            <div id="collapseStripe" class="wrapper">
              <script src="https://js.stripe.com/v3/"></script>


              <form action="." method="post" id="payment-form">
                {% csrf_token %}
                <div class="form-row">
                  <label for="card-element">
                    Credit or debit card
                  </label>
                  <div id="card-element" class="StripeElement StripeElement--empty"><div class="__PrivateStripeElement" style="margin: 0px !important; padding: 0px !important; border: none !important; display: block !important; background: transparent !important; position: relative !important; opacity: 1 !important;"><iframe frameborder="0" allowtransparency="true" scrolling="no" name="__privateStripeFrame3" allowpaymentrequest="true" src="https://js.stripe.com/v3/elements-inner-card-8a434729e4eb82355db4882974049278.html#style[base][color]=%2332325d&amp;style[base][lineHeight]=18px&amp;style[base][fontFamily]=%22Helvetica+Neue%22%2C+Helvetica%2C+sans-serif&amp;style[base][fontSmoothing]=antialiased&amp;style[base][fontSize]=16px&amp;style[base][::placeholder][color]=%23aab7c4&amp;style[invalid][color]=%23fa755a&amp;style[invalid][iconColor]=%23fa755a&amp;componentName=card&amp;wait=false&amp;rtl=false&amp;features[noop]=false&amp;origin=https%3A%2F%2Fstripe.com&amp;referrer=https%3A%2F%2Fstripe.com%2Fdocs%2Fstripe-js%2Felements%2Fquickstart&amp;controllerId=__privateStripeController0" title="Secure payment input frame" style="border: none !important; margin: 0px !important; padding: 0px !important; width: 1px !important; min-width: 100% !important; overflow: hidden !important; display: block !important; height: 18px;"></iframe><input class="__PrivateStripeElement-input" aria-hidden="true" style="border: none !important; display: block !important; position: absolute !important; height: 1px !important; top: 0px !important; left: 0px !important; padding: 0px !important; margin: 0px !important; width: 100% !important; opacity: 0 !important; background: transparent !important; pointer-events: none !important; font-size: 16px !important;"><input class="__PrivateStripeElement-safariInput" aria-hidden="true" tabindex="-1" style="border: none !important; display: block !important; position: absolute !important; height: 1px !important; top: 0px !important; left: 0px !important; padding: 0px !important; margin: 0px !important; width: 100% !important; opacity: 0 !important; background: transparent !important; pointer-events: none !important; font-size: 16px !important;"></div></div>

                  <!-- Used to display form errors. -->
                  <div id="card-errors" role="alert"></div>
                </div>

                <button>Submit Payment</button>
              </form>

              </div>

            </div>

            <div id="stripe-token-handler" class="is-hidden">Success! Got token: <span class="token"></span></div>


                    </div>
                </div>
            </div>


            <!-- script for the stripe form -->
            <script src="{% static 'js/checkout.js' %}"></script>

            <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

            <!-- script for toggling display of the form -->
            <script type="text/javascript">
                function toggleDisplay() {
                  var x = document.getElementById("collapseStripe");
                  if (x.style.display === "none") {
                      x.style.display = "block";
                  } else {
                      x.style.display = "none";
                  }
                };
            </script>


            {% endblock content %}

А вот и заказ. js

// Create a Stripe client.

var stripe = Stripe('123456'); //key goes here

  // Create an instance of Elements.
  var elements = stripe.elements();

  // Custom styling can be passed to options when creating an Element.
  // (Note that this demo uses a wider set of styles than the guide below.)
  var style = {
    base: {
      color: '#32325d',
      lineHeight: '18px',
      fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
      fontSmoothing: 'antialiased',
      fontSize: '16px',
      '::placeholder': {
        color: '#aab7c4'
      }
    },
    invalid: {
      color: '#fa755a',
      iconColor: '#fa755a'
    }
  };

  // Create an instance of the card Element.
  var card = elements.create('card', {style: style});

  // Add an instance of the card Element into the `card-element` <div>.
  card.mount('#card-element');

  // Handle real-time validation errors from the card Element.
  card.addEventListener('change', function(event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
      displayError.textContent = event.error.message;
    } else {
      displayError.textContent = '';
    }
  });

  // Handle form submission.
  var form = document.getElementById('payment-form');
  form.addEventListener('submit', function(event) {
    event.preventDefault();

    stripe.createToken(card).then(function(result) {
      if (result.error) {
        // Inform the user if there was an error.
        var errorElement = document.getElementById('card-errors');
        errorElement.textContent = result.error.message;
      } else {
        // Send the token to your server.
        stripeTokenHandler(result.token);
      }
    });

  });

  var successElement = document.getElementById('stripe-token-handler');
  document.querySelector('.wrapper').addEventListener('click', function() {
    successElement.className = 'is-hidden';
  });

  function stripeTokenHandler(token) {
    successElement.className = '';
    successElement.querySelector('.token').textContent = token.id;
    // Insert the token ID into the form so it gets submitted to the server
    var form = document.getElementById('payment-form');
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'stripeToken');
    hiddenInput.setAttribute('value', token.id);
    form.appendChild(hiddenInput);

    // Submit the form
    form.submit();
  }

Мои открытые / секретные ключи API находятся в моем файле настроек и я дважды проверил их; они оба правильные.

Что я здесь не так делаю? Это мой первый проект Django / Python. Ценю некоторое понимание. Спасибо.

...