django中的条带实现未重定向到成功页面

jhkqcmku  于 2022-11-26  发布在  Go
关注(0)|答案(1)|浏览(188)

我试着在Django中实现stripe,一切都很好,直到我尝试在付款后将用户重定向到成功页面。有人能看看我的代码,告诉我哪里做错了吗?
views.py

@csrf_exempt
def create_checkout_session(request, id):
    request_data = json.loads(request.body)
    gig = get_object_or_404(Gig, pk=id)
    stripe.api_key = settings.STRIPE_SECRET_KEY
    checkout_session = stripe.checkout.Session.create(
        customer_email=request_data['email'],
        payment_method_types=['card'],
        line_items=[
            {
                'price_data': {
                    'currency': 'eur',
                    'product_data': {
                        'name': gig.seller,
                    },
                    'unit_amount': int(gig.price * 100),
                },
                'quantity': 1,
            }
        ],

        mode='payment',
        success_url='http://127.0.0.1:8000/checkout/success?session_id={CHECKOUT_SESSION_ID}',
        cancel_url='http://127.0.0.1:8000/checkout/failed/',
    )

    order = OrderDetail()
    order.customer_email = request_data['email']
    order.gig = gig
    order.stripe_payment_intent = checkout_session.payment_intent
    order.amount = int(gig.price * 100)
    order.save()
    
    # return JsonResponse({'data': checkout_session})
    return JsonResponse({'sessionId': checkout_session.id})

class PaymentSuccessView(TemplateView):
    template_name = "checkout/payment_success.html"

    def get(self, request, *args, **kwargs):
        session_id = request.GET.get('session_id')
        if session_id is None:
            return HttpResponse("failed")
        
        stripe.api_key = settings.STRIPE_SECRET_KEY
        session = stripe.checkout.Session.retrieve(session_id)
        
        order = get_object_or_404(OrderDetail, stripe_payment_intent=session.payment_intent)
        order.has_paid = True
        order.save()
        return render(request, self.template_name)

models.py

from django.db import models
from django.core import validators



class OrderDetail(models.Model):

    id = models.BigAutoField(
        primary_key=True
    )

    # You can change as a Foreign Key to the user model
    customer_email = models.EmailField(
        verbose_name='Customer Email'
    )

    gig = models.ForeignKey(
        to=Gig,
        verbose_name='Product',
        on_delete=models.PROTECT
    )

    amount = models.IntegerField(
        verbose_name='Amount'
    )

    stripe_payment_intent = models.CharField(
        max_length=200, null=True, blank=True
    )

    # This field can be changed as status
    has_paid = models.BooleanField(
        default=False,
        verbose_name='Payment Status'
    )

    created_on = models.DateTimeField(
        auto_now_add=True
    )

    updated_on = models.DateTimeField(
        auto_now_add=True
    )

class Gig(models.Model):
    id = models.BigAutoField(
        primary_key=True
    )

    gigger = models.ForeignKey(
        Mentors, 
        on_delete=models.CASCADE,
        related_name="seller")
    
    description = models.TextField(
        blank=True,
        max_length=800,
        verbose_name='Description'
    )

    price = models.DecimalField(
        verbose_name='Price',
        decimal_places=2,
        max_digits=6,
    )

    def __str__(self):
       return f"{self.gigger}, ${self.price}, id:{self.id}"

class Comments:
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="Commentor")
    comment = models.TextField(blank=True)
    stars = models.PositiveSmallIntegerField()

product.html

{% extends 'web/layout.html' %}

{% block body %}
<h1 class="text-center">Product Detail</h1>
<div class="container">

    <div class="card">
        <div class="card-header">
            <h2>Product Detail</h2>
        </div>
        <div class="card-body">
            <div class="container row">
                <div class="col-md-2">
                    <img src="https://dummyimage.com/150x150.gif?text={{ object.name }}" alt="">
                </div>
                <div class="col-md-10">
                    <h1>Name: {{ object.seller.mentor.username }}</h1>
                    <p>Description: {{ object.description }}</p>
                    <p>Price: {{ object.price }}</p>

                    <div class="form-group">
                        <label for="email">Email: </label>
                        <input type="email" name="email" id="email" class="form-control" placeholder="{{object.gigger.mentor.email}}">
                        <small>Please enter your email address</small>
                    </div>
                </div>
            </div>
        </div>
        <div class="card-footer d-flex">
            <button class="btn btn-success ml-auto" id="checkout-button">Checkout</button>
        </div>
    </div>
</div>

<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">
    // Create an instance of the Stripe object with your publishable API key
    var stripe = Stripe('{{ stripe_publishable_key }}');
    var checkoutButton = document.getElementById('checkout-button');

    checkoutButton.addEventListener('click', function () {

        var email = document.getElementById('email').value;
        if (email.length == 0) {
            alert("Please enter your email address.");
            return;
        }

        // Create a new Checkout Session using the server-side endpoint you
        // created in step 3.
        fetch("http://127.0.0.1:8000/checkout/api/checkout-session/{{ object.id }}/", {
            method: 'POST',
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(
                { email: email }
            )
        })
            .then(response => response.json())
            .then(function (session) {
                return stripe.redirectToCheckout({ sessionId: session.sessionId });
            })
            .then(function (result) {
                // If `redirectToCheckout` fails due to a browser or network
                // error, you should display the localized error message to your
                // customer using `error.message`.
                if (result.error) {
                    alert(result.error.message);
                }
            })
            .catch(function (error) {
                console.error('Error:', error);
            });
    });
</script>
{% endblock %}

下单后,当我进入'order details'对象并看到'stripe_payment_intend'键始终为空时,它没有被保存。我还可以尝试什么来获取每个不同的订单?

wpx232ag

wpx232ag1#

问题在于,创建Checkout Session并设置order数据的时间点与使用PaymentSuccessView类呈现成功页面的时间点是断开的。仅仅因为这两段代码在同一个文件中,并不意味着在不同的请求之间将保持状态。
您可以使用metadata将订单信息添加到Checkout Session中。然后,当您在成功页面上检索Checkout Session时,可以从Checkout Session中读取metadata以获取相关信息。

相关问题