我试着在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'键始终为空时,它没有被保存。我还可以尝试什么来获取每个不同的订单?
1条答案
按热度按时间wpx232ag1#
问题在于,创建Checkout Session并设置
order
数据的时间点与使用PaymentSuccessView
类呈现成功页面的时间点是断开的。仅仅因为这两段代码在同一个文件中,并不意味着在不同的请求之间将保持状态。您可以使用metadata将订单信息添加到Checkout Session中。然后,当您在成功页面上检索Checkout Session时,可以从Checkout Session中读取
metadata
以获取相关信息。