【问题标题】:Django Stripe Payment: Invalid card object: must be a dictionary or a non-empty stringDjango Stripe Payment:无效的卡对象:必须是字典或非空字符串
【发布时间】:2021-03-29 14:15:51
【问题描述】:

当我尝试向 stripe 发送付款时,我收到一条错误消息:“无效的卡对象:必须是字典或非空字符串。”

付款金额为 5 欧元。我正在使用信用卡号 4242 4242 4242 4242 来测试付款。我可以看到除了“stripe_id”之外,条纹的“Post”参数都是正确的。我一直在尝试查看“stripe_id”有什么问题,但我不知所措。

谁能帮我找出我的代码有什么问题?

checkout.html:

{% extends "base.html" %}
{% load static from staticfiles %}
{% load bootstrap_tags %}

{% block head_js %}
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript" src="">
    //<![CDATA[
    Stripe.publishableKey = '{{ publishable }}';
   // ]]>
</script>
<script type="text/javascript" src="{% static 'js/stripe.js' %}"></script>
{% endblock %}

{% block content %}

<form action="{% url 'checkout' %}" method="post" id="payment-form" class="col-md-6 col-md-offset-3">
    <legend>Payment Details</legend>

    <div id="credit-card-errors" style="display: none;">
        <div class="alert-message block-message error" id="stripe-error-message"></div>
    </div>

    <div class="form-group col-md-6">
        {{ payment_form|as_bootstrap }}
    </div>

    {% csrf_token %}
    <div class="form-group col-md-12">
        <input class=" btn btn-primary" id="submit_payment_btn" name="commit" type="submit" value="Submit Payment of 5 Euros">
    </div>
</form>

{% endblock %}

forms.py:

from django import forms

class MakePaymentForm(forms.Form):
    print("MakePaymentForm...")
    MONTH_CHOICES = [(i, i) for i in range(1, 12)]
    YEAR_CHOICES = [(i, i) for i in range(2019, 2040)]
    
    credit_card_number = forms.CharField(label='Credit Card Number', required=False)
    cvv = forms.CharField(label ='Security Code (CVV)', required=False)
    expiry_month = forms.ChoiceField(label="Month",choices=MONTH_CHOICES, required=False)
    expiry_year = forms.ChoiceField(label='year',choices=YEAR_CHOICES, required=False)
    stripe_id = forms.CharField(widget=forms.HiddenInput,  required=False)

views.py:

from django.shortcuts import render, get_object_or_404, redirect, reverse
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import MakePaymentForm
from tickets.forms import TicketsForm
from tickets.models import Ticket
from django.conf import settings
from accounts.views import login, index 
from django.utils import timezone
import stripe
# Create your views here.

stripe.api_key = settings.STRIPE_SECRET

@login_required()
def checkout(request):
    if request.method == "POST":
        payment_form = MakePaymentForm(request.POST)
        print("checkout...")

        if  payment_form.is_valid():
            print("Payment form is valid...")
            try:
                print("Just about to charge the customer...")
                customer = stripe.Charge.create(
                    amount=500,
                    currency="EUR",
                    description="Thank you for your contribution, it will really help our site" and request.user.email,
                    card=payment_form.cleaned_data['stripe_id']
                )
            except stripe.error.CardError:
                messages.error(request, "Your card was declined!")
            
            if customer.paid:
                print("Customer has paid...")
                messages.error(request, "You have successfully paid")
                return redirect(reverse('index'))
            else:
                messages.error(request, "Unable to take payment")
                return redirect(reverse('index'))
        else:
            print("There are errors...")
            print(payment_form.errors)
            messages.error(request, "We were unable to take a payment with that card!")
    else:
        print("Method isn't post...")
        payment_form = MakePaymentForm()

    return render(request, "checkout.html", {"payment_form": payment_form, "publishable": settings.STRIPE_PUBLISHABLE})

这是终端中的输出:

Method isn't post...
[18/Dec/2020 23:24:26] "GET /checkout/ HTTP/1.1" 200 5957
checkout...
Payment form is valid...
Just about to charge the customer...
Internal Server Error: /checkout/
Traceback (most recent call last):
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/ubuntu/environment/issuetracker/checkout/views.py", line 29, in checkout
    card=payment_form.cleaned_data['stripe_id']
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/stripe/api_resources/abstract/createable_api_resource.py", line 22, in create
    response, api_key = requestor.request("post", url, params, headers)
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/stripe/api_requestor.py", line 122, in request
    resp = self.interpret_response(rbody, rcode, rheaders)
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/stripe/api_requestor.py", line 373, in interpret_response
    self.handle_error_response(rbody, rcode, resp.data, rheaders)
  File "/home/ubuntu/environment/issuetracker/foo/lib/python3.6/site-packages/stripe/api_requestor.py", line 152, in handle_error_response
    raise err
stripe.error.InvalidRequestError: Request req_KWiO7eNBrSt4ph: Invalid card object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'
[18/Dec/2020 23:24:40] "POST /checkout/ HTTP/1.1" 500 104672

这里是 stripe.js:

$(function(){
    $("#payment-form").submit(function() {
        console.log("#payment-form");
        var form = this;
        var card = {
            number: $("#id_credit_card_number").val(),
            expMonth: $("#id_expiry_month").val(),
            expYear: $("#id_expiry_year").val(),
            cvc: $("#id_cvv").val()
        };
    
    Stripe.createToken(card, function(status, response) {
        console.log("#createToken");
        if (status === 200) {
            $("#credit-card-errors").hide();
            $("#id_stripe_id").val(response.id);

            // Prevent the credit card details from being submitted
            // to our server
            $("#id_credit_card_number").removeAttr('name');
            $("#id_cvv").removeAttr('name');
            $("#id_expiry_month").removeAttr('name');
            $("#id_expiry_year").removeAttr('name');

            form.submit();
        } else {
            $("#stripe-error-message").text(response.error.message);
            $("#credit-card-errors").show();
            $("#validate_card_btn").attr("disabled", false);
        }
    });
    return false;
    });
});

支付失败时我的页面截图如下:

【问题讨论】:

    标签: python django stripe-payments


    【解决方案1】:

    查看您的 Stripe 仪表板中的请求:https://dashboard.stripe.com/test/logs/req_KWiO7eNBrSt4ph

    您可以在那里看到card 的值是一个空字符串,这就是您收到错误的原因。

    您前端的这段代码似乎阻止将卡信息发送到您的服务器:

    // Prevent the credit card details from being submitted
    // to our server
    $("#id_credit_card_number").removeAttr('name');
    $("#id_cvv").removeAttr('name');
    $("#id_expiry_month").removeAttr('name');
    $("#id_expiry_year").removeAttr('name');
    

    因此,您的服务器在 card 属性中没有要发送的内容。

    Stripe.js v2 已经过时了;如果可能的话,我推荐你upgrade to Stripe.js v3 and Elements

    【讨论】:

    • 非常感谢您的回复。我已经删除了这些行,但我仍然得到同样的错误。我是 django 和 stripe 的新手,所以我不确定这是否是我应该做的。您还有其他想法吗?
    • 我的主要建议是migrate from Stripe.js v2 to Stripe.js v3,这将需要您重写很多此代码,但您最终将获得更好的集成(并且可能更少的 PCI 合规性负担)作为结果。
    • 实际上,我认为 stripe.js 没有被正确调用,因为 console.log 的输出没有显示。这可能是问题吗?
    【解决方案2】:

    我找到了答案,现在信用卡付款正常。我没有在标头中包含 jQuery CDN,所以没有正确调用 stripe.js!

    感谢贾斯汀迈克尔,你在我的大脑中触发了一些东西,让我走上了正确的道路!

    【讨论】:

      猜你喜欢
      • 2021-03-26
      • 1970-01-01
      • 2017-10-07
      • 1970-01-01
      • 2019-01-16
      • 2020-08-31
      • 2022-01-19
      • 2021-12-03
      • 1970-01-01
      相关资源
      最近更新 更多