django中的Stripe实现不会重定向到成功页面



我试图在Django中实现条纹,一切都工作得很好,直到我试图在付款后将用户重定向到成功页面。谁能看看我的代码,告诉我我做错了什么?

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 %}

下订单后,当我进入"订单详细信息"对象并看到"stripe_payment_intent"键始终为空时,它不会被保存。我还能做什么来得到不同的顺序呢?

问题是,当您创建Checkout会话并设置order数据时,与您使用PaymentSuccessView类呈现成功页面的点是断开的。仅仅因为这两段代码在同一个文件中并不意味着在不同的请求之间将维护状态。

您可以做的是使用元数据将订单信息添加到Checkout会话。然后,当您在成功页面上检索结帐会话时,您可以从结帐会话中读取metadata以获得相关信息。

最新更新