Problèmes de panier dans un site e-commerce Django
Bonjour, je suis occupé sur le site e-commerce Django et je rencontre 2 problèmes:
-
mon panier n'est pas marqué comme ordered et supprimé après le paiement
-
peut importe les items que j'ajoute dans le panier quand je me dirige vers la page de checkout avec stripe se ne sont pas les items qui s'affichent
vieuw :
from http.client import HTTPS_PORT
from importlib.metadata import metadata
from pprint import pprint
import stripe
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from accounts.models import Shopper
from shop import settings
from store.models import Product, Cart, Order # import product
import json
YOUR_DOMAIN = 'http://localhost:8000'
stripe.api_key = settings.STRIPE_API_KEY
def index(request):
products = Product.objects.all()
return render(request, 'store/index.html', context={"products": products})
def product_detail(request, slug):
product = get_object_or_404(Product, slug=slug)
if request.method == "POST":
comment = request.POST.get("comment")
if comment:
product.user_comment = comment # Sauvegarde du commentaire
product.save()
return redirect("product", slug=product.slug) # Rafraîchit la page
return render(request, 'store/product-detail.html', context={"product": product})
def add_to_cart(request, slug):
user = request.user # get user
product = get_object_or_404(Product, slug=slug)
cart, _ = Cart.objects.get_or_create(user=user) # Get or create cart
order, created = Order.objects.get_or_create(user=user, ordered=False,product=product) # Get or create order
if created:
cart.orders.add(order)
cart.save()
else:
order.quantity += 1
order.save()
return redirect(reverse("product", kwargs={"slug": slug}))
def delete_cart(request):
cart = getattr(request.user, "cart", None)
if cart:
cart.delete()
return redirect("index")
def cart(request):
cart = get_object_or_404(Cart, user=request.user, ordered=False)
orders = cart.orders.filter(ordered=False) # Seules les commandes non terminées
return render(request, 'store/cart.html', context={"cart": cart, "orders": orders})
def create_checkout_session(request):
cart = request.user.cart
line_items = [{"price": order.product.stripe_id,
"quantity": order.quantity} for order in cart.orders.all()]
try:
# Create a checkout session
checkout_session = stripe.checkout.Session.create(
locale="fr",
payment_method_types=['card'], # Only card payments
line_items=line_items,
mode='payment',
success_url = YOUR_DOMAIN + reverse('checkout-success'),
cancel_url=YOUR_DOMAIN + '/',
metadata={
"user_email": request.user.email
}
)
# Redirect to Stripe checkout page
return redirect(checkout_session.url, code=303)
except Exception as e:
return JsonResponse({"error": str(e)}, status=500) # Return a JSON response on error
endpoint_secret = 'whsec_517e4430b4ef6cd82c3dd1bc5875745dc3eed84b823491b73760bb05adf8288e'
def checkout_success(request):
return render(request, 'store/success.html')
@csrf_exempt
def stripe_webhook(request):
payload = request.body
sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')
event = None
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
print(f"Payload invalide : {str(e)}")
return HttpResponse(status=400)
except stripe.error.SignatureVerificationError as e:
print(f"Signature invalide : {str(e)}")
return HttpResponse(status=400)
# Logging pour vérifier les données reçues
print(f"Événement reçu : {event.type}")
pprint(event)
# Gérer l'événement checkout.session.completed
if event.type == 'checkout.session.completed':
data = event['data']['object']
return complete_order(data)
return HttpResponse(status=200)
def complete_order(data):
try:
user_email = data['metadata'].get('user_email')
if not user_email:
raise KeyError("Email manquant dans les métadonnées")
except KeyError as e:
print(f"Erreur: {str(e)}")
return HttpResponse("Invalid user email", status=404)
user = get_object_or_404(Shopper, email=user_email)
if not hasattr(user, 'cart'):
print("Erreur: Aucun panier associé à cet utilisateur")
return HttpResponse("Cart not found for user", status=404)
# Marquer le panier comme commandé
cart = user.cart
cart.ordered = True
cart.ordered_date = timezone.now()
cart.save()
# Marquer toutes les commandes associées comme commandées
for order in cart.orders.all():
order.ordered = True
order.save()
return HttpResponse(status=200)
model :
from ckeditor.fields import RichTextField
from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
from django.db import models
from shop.settings import AUTH_USER_MODEL
class Variant(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=100, unique=True, blank=True) # Slug généré automatiquement si vide
price = models.FloatField(default=0.0)
available = models.BooleanField(default=True)
description = RichTextField(blank=True) # RichText pour mise en forme
thumbnail = models.ImageField(upload_to="products", blank=True, null=True) # Image principale
variants = models.ManyToManyField("self", blank=True, symmetrical=False)
user_comment = models.TextField(blank=True, null=True)
stripe_id = models.CharField(max_length=90, blank=True)
def save(self, *args, **kwargs):
if not self.slug: # Générer le slug automatiquement
self.slug = slugify(self.name)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse("product", kwargs={"slug": self.slug})
def __str__(self):
return self.name
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="images")
image = models.ImageField(upload_to="product_images", blank=True, null=True)
def __str__(self):
return f"Image de {self.product.name}"
# (Order)
class Order(models.Model):
user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE) #user relie a plusieurs articles grace a foreignKey() - on_delete-> si user deleted from db if will erase his stored products
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1) # quantity of one item in the cart
ordered = models.BooleanField(default=False)
def __str__(self):
return f"{self.product.name} ({self.quantity})"
# (Cart)
class Cart(models.Model):
user = models.OneToOneField(AUTH_USER_MODEL, on_delete=models.CASCADE)
orders = models.ManyToManyField(Order)
ordered = models.BooleanField(default=False)
ordered_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.user.username
def delete(self, *args, **kwargs):
# Mark all orders in the cart as ordered and set the ordered date
for order in self.orders.all():
order.ordered = True
order.ordered_date = timezone.now()
order.save()
# Clear the orders from the cart
self.orders.clear()
# Call the superclass delete method to delete the cart
super().delete(*args, **kwargs)
# def process_payment(self):
# # Mark all orders in the cart as ordered
# for order in self.orders.all():
# order.ordered = True
# order.save()
# # Mark the cart as ordered and set the ordered date
# self.ordered = True
# self.ordered_date = timezone.now()
# self.save()
# # Delete the cart
# super().delete()
Salut,
Dans ton webhook tu fais ça via complete_order :
cart.ordered = True
cart.ordered_date = timezone.now()
cart.save()
# Marquer toutes les commandes associées comme commandées
for order in cart.orders.all():
order.ordered = True
order.save()
Voici quelques pistes :
-
Le
cartne devrait pas avoir d'attributorderedet deordered_date. Mais bien un attrbutorders. Il y a un petit problème de conception au niveau du modèle. -
Dans ta fonction
complete_ordertu devrais appeler la méthode delete de Cart qui va faire le boulot de passer les commandes àorderedet supprimer le panier. -
Aussi, tu ne devrais pas retourner
complete_ordermais uneHttpResponse.
Si tu veux, regarde ce que j'avais fait à l'époque : https://github.com/gabigab117/DocShop.git
Et tu as quoi qui est affiché au checkout ?
N'hésites pas si jamais tu as d'autres difficultés :)
Merci pour ta réponse.
En effet, le problème venait du fait que mon stripe cli n'etait pas lancé..je n'avais pas compris que le webhook était nécessaire pour écouter les actions
Inscris-toi
(c'est gratuit !)
Tu dois créer un compte pour participer aux discussions.
Créer un compte