Я пытался внедрить полосу в Django, и все работало нормально, пока я не попытался перенаправить пользователя на страницу успеха после оплаты. Может ли кто-нибудь взглянуть на мой код и сказать мне, что я делаю неправильно?
просмотры.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)
модели.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()
продукт.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_intend» всегда пуст, он не сохраняется. Что еще я мог бы попробовать, чтобы получить каждый другой заказ?
Проблема в том, что момент, когда вы создаете сеанс проверки и устанавливаете данные order
, не связан с моментом, когда вы визуализируете свою страницу успеха с помощью класса PaymentSuccessView
. Тот факт, что эти две части кода находятся в одном файле, не означает, что состояние будет поддерживаться между различными запросами.
Вместо этого вы можете добавить информацию о заказе в сеанс оформления заказа, используя метаданные. Затем, когда вы получаете сеанс проверки на странице успеха, вы можете прочитать metadata
из сеанса проверки, чтобы получить соответствующую информацию.
Пожалуйста, обрежьте свой код, чтобы было легче найти вашу проблему. Следуйте этим рекомендациям, чтобы создать минимально воспроизводимый пример.