furry/products/views.py

839 lines
30 KiB
Python

from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.db.models import Q, Avg, Count
from django.db import transaction
# from rest_framework import viewsets # Temporär auskommentiert
# from rest_framework.permissions import IsAuthenticatedOrReadOnly # Temporär auskommentiert
from .models import Product, Cart, CartItem, Order, OrderItem, Review, UserProfile, Wishlist, FAQ, ContactMessage, CustomOrder, OrderProgress, GalleryImage, Category
from .forms import OrderForm, CustomUserCreationForm, CustomAuthenticationForm, ReviewForm, UserProfileForm, ContactForm, CustomOrderForm, OrderProgressForm
# from .serializers import ProductSerializer, ReviewSerializer # Temporär auskommentiert
import stripe
from django.conf import settings
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from django.core.mail import send_mail
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
import json
# import paypalrestsdk # Temporär auskommentiert
# from payments import get_payment_model, RedirectNeeded # Temporär auskommentiert
# from paypal.standard.ipn.models import PayPalIPN # Temporär auskommentiert
from django.urls import reverse
from django.http import HttpResponse
# from paypal.standard.forms import PayPalPaymentsForm # Temporär auskommentiert
import logging
from django.core.exceptions import ValidationError
from django.http import Http404
logger = logging.getLogger(__name__)
# Create your views here.
class ProductListView(ListView):
model = Product
template_name = 'products/product_list.html'
context_object_name = 'products'
paginate_by = 12
def get_queryset(self):
try:
queryset = Product.objects.all().annotate(
average_rating=Avg('reviews__rating'),
review_count=Count('reviews')
).select_related('category').prefetch_related(
'reviews__user', # Optimiert N+1 Queries für Reviews
'wishlist_users' # Optimiert Wishlist-Queries
)
# Erweiterte Suchfilter
search_query = self.request.GET.get('search')
if search_query:
# Verbesserte Suche mit Q-Objekten
search_terms = search_query.split()
q_objects = Q()
for term in search_terms:
q_objects |= (
Q(name__icontains=term) |
Q(description__icontains=term) |
Q(fursuit_type__icontains=term) |
Q(style__icontains=term) |
Q(category__name__icontains=term)
)
queryset = queryset.filter(q_objects)
# Preisbereich Filter mit Validierung
min_price = self.request.GET.get('min_price')
max_price = self.request.GET.get('max_price')
if min_price and min_price.isdigit():
queryset = queryset.filter(price__gte=float(min_price))
if max_price and max_price.isdigit():
queryset = queryset.filter(price__lte=float(max_price))
# Fursuit-Typ Filter
fursuit_type = self.request.GET.get('fursuit_type')
if fursuit_type:
queryset = queryset.filter(fursuit_type=fursuit_type)
# Style Filter
style = self.request.GET.get('style')
if style:
queryset = queryset.filter(style=style)
# Kategorie Filter
category = self.request.GET.get('category')
if category:
queryset = queryset.filter(category__slug=category)
# Verfügbarkeit Filter
availability = self.request.GET.get('availability')
if availability == 'in_stock':
queryset = queryset.filter(stock__gt=0)
elif availability == 'low_stock':
queryset = queryset.filter(stock__lte=5, stock__gt=0)
elif availability == 'out_of_stock':
queryset = queryset.filter(stock=0)
# Sortierung mit verbesserter Performance
sort = self.request.GET.get('sort', '-created')
if sort == 'price':
queryset = queryset.order_by('price')
elif sort == '-price':
queryset = queryset.order_by('-price')
elif sort == 'name':
queryset = queryset.order_by('name')
elif sort == '-name':
queryset = queryset.order_by('-name')
elif sort == '-rating':
queryset = queryset.order_by('-average_rating')
elif sort == 'popularity':
queryset = queryset.order_by('-review_count')
else: # Default: Neueste zuerst
queryset = queryset.order_by('-created')
return queryset.distinct()
except Exception as e:
logger.error(f"Error in ProductListView.get_queryset: {e}")
return Product.objects.none()
def get_context_data(self, **kwargs):
try:
context = super().get_context_data(**kwargs)
# Zusätzliche Context-Daten
context['categories'] = Category.objects.all()
context['fursuit_types'] = Product.FURSUIT_TYPE_CHOICES
context['styles'] = Product.STYLE_CHOICES
return context
except Exception as e:
logger.error(f"Error in ProductListView.get_context_data: {e}")
return super().get_context_data(**kwargs)
class ProductDetailView(DetailView):
model = Product
template_name = 'products/product_detail.html'
context_object_name = 'product'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.user.is_authenticated:
context['user_has_reviewed'] = Review.objects.filter(
product=self.object,
user=self.request.user
).exists()
context['review_form'] = ReviewForm()
return context
def get_or_create_cart(request):
if request.user.is_authenticated:
cart, created = Cart.objects.get_or_create(user=request.user)
else:
session_key = request.session.session_key
if not session_key:
request.session.create()
session_key = request.session.session_key
cart, created = Cart.objects.get_or_create(session_id=session_key)
return cart
def add_to_cart(request, product_id):
if request.method == 'POST':
product = get_object_or_404(Product, id=product_id)
quantity = int(request.POST.get('quantity', 1))
if quantity > product.stock:
messages.error(request, 'Nicht genügend Artikel auf Lager!')
return redirect('products:product_detail', pk=product_id)
cart = get_or_create_cart(request)
cart_item, created = CartItem.objects.get_or_create(
cart=cart,
product=product,
defaults={'quantity': quantity}
)
if not created:
cart_item.quantity += quantity
cart_item.save()
messages.success(request, f'{quantity}x {product.name} wurde zum Warenkorb hinzugefügt.')
return redirect('products:cart_detail')
def cart_detail(request):
cart = get_or_create_cart(request)
return render(request, 'products/cart_detail.html', {'cart': cart})
def create_order(request):
if request.method == 'POST':
cart = get_or_create_cart(request)
if not cart.items.exists():
messages.error(request, 'Ihr Warenkorb ist leer.')
return redirect('products:cart_detail')
# Erstelle eine neue Bestellung
order = Order.objects.create(
user=request.user if request.user.is_authenticated else None,
full_name=f"{request.user.first_name} {request.user.last_name}" if request.user.is_authenticated else "",
email=request.user.email if request.user.is_authenticated else "",
total_amount=cart.get_total()
)
# Füge die Artikel aus dem Warenkorb zur Bestellung hinzu
for cart_item in cart.items.all():
OrderItem.objects.create(
order=order,
product=cart_item.product,
product_name=cart_item.product.name,
quantity=cart_item.quantity,
price=cart_item.product.price
)
# Leere den Warenkorb
cart.items.all().delete()
messages.success(request, 'Ihre Bestellung wurde erfolgreich erstellt.')
return redirect('products:checkout', order_id=order.id)
return redirect('products:cart_detail')
@login_required
def checkout(request, order_id):
order = get_object_or_404(Order, id=order_id)
if request.user.is_authenticated and order.user != request.user:
messages.error(request, 'Sie haben keine Berechtigung, diese Bestellung einzusehen.')
return redirect('products:product_list')
# PayPal Zahlungsformular erstellen
host = request.get_host()
paypal_dict = {
"business": settings.PAYPAL_RECEIVER_EMAIL,
"amount": str(order.total_amount),
"item_name": f"Bestellung #{order.id}",
"invoice": str(order.id),
"currency_code": "EUR",
"notify_url": request.build_absolute_uri('/paypal/'),
"return_url": request.build_absolute_uri(f'/products/payment/success/{order.id}/'),
"cancel_return": request.build_absolute_uri(f'/products/payment/failed/{order.id}/'),
}
form = PayPalPaymentsForm(initial=paypal_dict)
return render(request, 'products/checkout.html', {
'order': order,
'form': form
})
@csrf_exempt
@login_required
def create_paypal_order(request):
if request.method != 'POST':
return JsonResponse({'error': 'Nur POST-Anfragen erlaubt'}, status=405)
data = json.loads(request.body)
order = get_object_or_404(Order, id=data['order_id'], user=request.user)
payment = paypalrestsdk.Payment({
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [{
"amount": {
"total": str(order.total_amount),
"currency": "EUR"
},
"description": f"Bestellung #{order.id}"
}],
"redirect_urls": {
"return_url": f"{settings.SITE_URL}/products/order/confirmation/{order.id}/",
"cancel_url": f"{settings.SITE_URL}/products/checkout/{order.id}/"
}
})
if payment.create():
return JsonResponse({'paypal_order_id': payment.id})
else:
return JsonResponse({'error': payment.error}, status=400)
@csrf_exempt
@login_required
def capture_paypal_order(request):
if request.method != 'POST':
return JsonResponse({'error': 'Nur POST-Anfragen erlaubt'}, status=405)
data = json.loads(request.body)
order = get_object_or_404(Order, id=data['order_id'], user=request.user)
payment_id = data['paypal_order_id']
payment = paypalrestsdk.Payment.find(payment_id)
if payment.execute({'payer_id': payment.payer.payer_info.payer_id}):
order.status = 'paid'
order.payment_id = payment_id
order.save()
# E-Mail-Bestätigung senden
send_payment_confirmation_email(order)
return JsonResponse({'success': True})
else:
return JsonResponse({'error': payment.error}, status=400)
def order_confirmation(request, order_id):
order = get_object_or_404(Order, id=order_id)
if request.user.is_authenticated and order.user != request.user:
messages.error(request, 'Sie haben keine Berechtigung, diese Bestellung einzusehen.')
return redirect('products:product_list')
return render(request, 'products/order_confirmation.html', {'order': order})
def update_cart_item(request, item_id):
if request.method == 'POST':
cart_item = get_object_or_404(CartItem, id=item_id)
quantity = int(request.POST.get('quantity', 1))
if quantity > cart_item.product.stock:
messages.error(request, 'Nicht genügend Artikel auf Lager!')
elif quantity > 0:
cart_item.quantity = quantity
cart_item.save()
messages.success(request, 'Warenkorb wurde aktualisiert.')
else:
cart_item.delete()
messages.success(request, 'Artikel wurde aus dem Warenkorb entfernt.')
return redirect('products:cart_detail')
def remove_from_cart(request, item_id):
if request.method == 'POST':
cart_item = get_object_or_404(CartItem, id=item_id)
cart_item.delete()
messages.success(request, 'Artikel wurde aus dem Warenkorb entfernt.')
return redirect('products:cart_detail')
def register(request):
if request.method == 'POST':
form = CustomUserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
messages.success(request, 'Registrierung erfolgreich!')
return redirect('products:product_list')
else:
form = CustomUserCreationForm()
return render(request, 'registration/register.html', {'form': form})
@login_required
def add_review(request, product_id):
product = get_object_or_404(Product, id=product_id)
if request.method == 'POST':
form = ReviewForm(request.POST)
if form.is_valid():
review = form.save(commit=False)
review.product = product
review.user = request.user
review.save()
messages.success(request, 'Ihre Bewertung wurde erfolgreich hinzugefügt.')
else:
messages.error(request, 'Es gab einen Fehler beim Hinzufügen Ihrer Bewertung.')
return redirect('product_detail', pk=product_id)
@login_required
def profile_view(request):
if request.method == 'POST':
form = UserProfileForm(request.POST, instance=request.user.userprofile)
if form.is_valid():
form.save()
messages.success(request, 'Profil wurde erfolgreich aktualisiert.')
return redirect('products:profile')
else:
form = UserProfileForm(instance=request.user.userprofile)
return render(request, 'products/profile.html', {'form': form})
@login_required
def order_history(request):
orders = Order.objects.filter(user=request.user).order_by('-created')
return render(request, 'products/order_history.html', {'orders': orders})
@login_required
def wishlist_view(request):
wishlist, created = Wishlist.objects.get_or_create(user=request.user)
return render(request, 'products/wishlist.html', {'wishlist': wishlist})
@login_required
def add_to_wishlist(request, product_id):
product = get_object_or_404(Product, id=product_id)
wishlist, created = Wishlist.objects.get_or_create(user=request.user)
wishlist.products.add(product)
messages.success(request, f'{product.name} wurde zu Ihrer Wunschliste hinzugefügt.')
return redirect('product_detail', product_id=product_id)
@login_required
def remove_from_wishlist(request, product_id):
product = get_object_or_404(Product, id=product_id)
wishlist = get_object_or_404(Wishlist, user=request.user)
wishlist.products.remove(product)
messages.success(request, f'{product.name} wurde von Ihrer Wunschliste entfernt.')
return redirect('wishlist')
def faq_list(request):
faqs = FAQ.objects.all()
categories = FAQ.objects.values_list('category', flat=True).distinct()
return render(request, 'products/faq.html', {
'faqs': faqs,
'categories': categories
})
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST, user=request.user)
if form.is_valid():
contact_message = form.save(commit=False)
if request.user.is_authenticated:
contact_message.user = request.user
contact_message.save()
messages.success(
request,
'Vielen Dank für Ihre Nachricht! Wir werden uns schnellstmöglich bei Ihnen melden.'
)
return redirect('contact_success')
else:
form = ContactForm(user=request.user)
return render(request, 'products/contact.html', {'form': form})
def contact_success(request):
return render(request, 'products/contact_success.html')
@login_required
def custom_order(request):
if request.method == 'POST':
form = CustomOrderForm(request.POST, request.FILES)
if form.is_valid():
custom_order = form.save(commit=False)
custom_order.user = request.user
custom_order.save()
messages.success(
request,
'Ihre Anfrage wurde erfolgreich übermittelt. Wir werden uns in Kürze mit einem Angebot bei Ihnen melden.'
)
return redirect('custom_order_success', order_id=custom_order.id)
else:
form = CustomOrderForm()
return render(request, 'products/custom_order.html', {
'form': form
})
@login_required
def custom_order_success(request, order_id):
order = get_object_or_404(CustomOrder, id=order_id, user=request.user)
return render(request, 'products/custom_order_success.html', {
'order': order
})
@login_required
def custom_order_detail(request, order_id):
order = get_object_or_404(CustomOrder, id=order_id, user=request.user)
progress_updates = order.progress_updates.all()
return render(request, 'products/custom_order_detail.html', {
'order': order,
'progress_updates': progress_updates
})
def gallery(request):
# Hole alle Galeriebilder
images = GalleryImage.objects.all().order_by('order', '-created')
# Filter nach Typ
fursuit_type = request.GET.get('fursuit_type')
if fursuit_type:
images = images.filter(fursuit_type=fursuit_type)
# Filter nach Stil
style = request.GET.get('style')
if style:
images = images.filter(style=style)
# Sortierung
sort = request.GET.get('sort', 'order')
if sort == 'newest':
images = images.order_by('-created')
elif sort == 'oldest':
images = images.order_by('created')
context = {
'images': images,
'fursuit_types': GalleryImage.FURSUIT_TYPE_CHOICES,
'fursuit_styles': GalleryImage.STYLE_CHOICES,
'current_type': fursuit_type,
'current_style': style,
'current_sort': sort
}
print(f"Anzahl der geladenen Bilder: {images.count()}") # Debug-Ausgabe
for img in images:
print(f"Bild: {img.title}, URL: {img.image.url}") # Debug-Ausgabe
return render(request, 'products/gallery.html', context)
@login_required
def add_progress_update(request, order_id):
order = get_object_or_404(CustomOrder, id=order_id)
if not request.user.is_staff:
messages.error(request, 'Sie haben keine Berechtigung für diese Aktion.')
return redirect('custom_order_detail', order_id=order_id)
if request.method == 'POST':
form = OrderProgressForm(request.POST, request.FILES)
if form.is_valid():
progress = form.save(commit=False)
progress.custom_order = order
progress.save()
messages.success(request, 'Fortschritts-Update wurde hinzugefügt.')
# Wenn alle Schritte abgeschlossen sind, setze den Status auf "ready"
if all(update.completed for update in order.progress_updates.all()):
order.status = 'ready'
order.save()
return redirect('custom_order_detail', order_id=order_id)
else:
form = OrderProgressForm()
return render(request, 'products/add_progress.html', {
'form': form,
'order': order
})
@login_required
def dashboard(request):
# Basis-Informationen
user_profile = request.user.userprofile
wishlist = Wishlist.objects.get_or_create(user=request.user)[0]
cart = get_or_create_cart(request)
# Custom Orders mit Fortschritt
custom_orders = CustomOrder.objects.filter(user=request.user).order_by('-created')
for order in custom_orders:
order.progress_percentage = calculate_order_progress(order)
# Letzte Bestellungen mit Details
recent_orders = Order.objects.filter(user=request.user).order_by('-created')[:5]
for order in recent_orders:
order.items_count = order.items.count()
# Bewertungsübersicht
reviews = Review.objects.filter(user=request.user).select_related('product').order_by('-created')[:5]
# Statistiken
stats = {
'total_orders': Order.objects.filter(user=request.user).count(),
'total_custom_orders': CustomOrder.objects.filter(user=request.user).count(),
'total_reviews': Review.objects.filter(user=request.user).count(),
'wishlist_count': wishlist.products.count(),
}
return render(request, 'products/dashboard.html', {
'user_profile': user_profile,
'custom_orders': custom_orders,
'recent_orders': recent_orders,
'reviews': reviews,
'stats': stats,
'wishlist': wishlist,
'cart': cart,
})
def calculate_order_progress(order):
"""Berechne den Fortschritt einer Custom Order in Prozent."""
if order.status == 'cancelled':
return 0
elif order.status == 'completed':
return 100
# Status-Gewichtung
status_weights = {
'pending': 10,
'quoted': 20,
'approved': 30,
'in_progress': 50,
'ready': 90,
'shipped': 95,
}
base_progress = status_weights.get(order.status, 0)
# Zusätzlicher Fortschritt basierend auf OrderProgress
if order.status == 'in_progress':
completed_stages = order.progress_updates.filter(completed=True).count()
total_stages = len(OrderProgress.PROGRESS_CHOICES)
stage_progress = (completed_stages / total_stages) * 40 # 40% für Fortschrittsstufen
return base_progress + stage_progress
return base_progress
# API ViewSets - Temporär auskommentiert
# class ProductViewSet(viewsets.ModelViewSet):
# queryset = Product.objects.all()
# serializer_class = ProductSerializer
# permission_classes = [IsAuthenticatedOrReadOnly]
# class ReviewViewSet(viewsets.ModelViewSet):
# queryset = Review.objects.all()
# serializer_class = ReviewSerializer
# permission_classes = [IsAuthenticatedOrReadOnly]
# def perform_create(self, serializer):
# serializer.save(user=self.request.user)
# Stripe-Konfiguration
stripe.api_key = settings.STRIPE_SECRET_KEY
def create_payment_intent(request, order_id):
"""Erstellt einen Stripe Payment Intent für eine Bestellung."""
try:
order = get_object_or_404(Order, id=order_id)
# Stripe akzeptiert nur Cent-Beträge
amount = int(order.total_amount * 100)
# Payment Intent erstellen
intent = stripe.PaymentIntent.create(
amount=amount,
currency='eur',
metadata={
'order_id': order.id,
'user_id': request.user.id if request.user.is_authenticated else None
}
)
# Order aktualisieren
order.stripe_payment_intent_id = intent.id
order.save()
return JsonResponse({
'clientSecret': intent.client_secret,
'amount': amount
})
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
def payment_view(request, order_id):
"""Zeigt die Zahlungsseite an."""
order = get_object_or_404(Order, id=order_id)
# Überprüfen, ob die Bestellung dem Benutzer gehört
if request.user.is_authenticated and order.user != request.user:
messages.error(request, 'Sie haben keine Berechtigung für diese Bestellung.')
return redirect('dashboard')
# Überprüfen, ob die Bestellung bereits bezahlt wurde
if order.payment_status == 'paid':
messages.info(request, 'Diese Bestellung wurde bereits bezahlt.')
return redirect('order_detail', order_id=order.id)
context = {
'order': order,
'stripe_publishable_key': settings.STRIPE_PUBLISHABLE_KEY
}
return render(request, 'products/payment.html', context)
@csrf_exempt
def stripe_webhook(request):
"""Webhook für Stripe-Events."""
payload = request.body
sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')
try:
event = stripe.Webhook.construct_event(
payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
)
except ValueError as e:
return JsonResponse({'error': 'Invalid payload'}, status=400)
except stripe.error.SignatureVerificationError as e:
return JsonResponse({'error': 'Invalid signature'}, status=400)
if event.type == 'payment_intent.succeeded':
payment_intent = event.data.object
handle_successful_payment(payment_intent)
elif event.type == 'payment_intent.payment_failed':
payment_intent = event.data.object
handle_failed_payment(payment_intent)
return JsonResponse({'status': 'success'})
def handle_successful_payment(payment_intent):
"""Verarbeitet erfolgreiche Zahlungen."""
order_id = payment_intent.metadata.get('order_id')
if order_id:
try:
order = Order.objects.get(id=order_id)
order.payment_status = 'paid'
order.payment_date = timezone.now()
order.status = 'processing'
order.stripe_payment_method_id = payment_intent.payment_method
order.save()
# E-Mail-Benachrichtigung senden
send_payment_confirmation_email(order)
except Order.DoesNotExist:
print(f"Bestellung {order_id} nicht gefunden")
def handle_failed_payment(payment_intent):
"""Verarbeitet fehlgeschlagene Zahlungen."""
order_id = payment_intent.metadata.get('order_id')
if order_id:
try:
order = Order.objects.get(id=order_id)
order.payment_status = 'failed'
order.save()
# E-Mail-Benachrichtigung senden
send_payment_failed_email(order)
except Order.DoesNotExist:
print(f"Bestellung {order_id} nicht gefunden")
@login_required
def payment_success(request, order_id):
"""Zeigt die Erfolgsseite nach erfolgreicher Zahlung an."""
order = get_object_or_404(Order, id=order_id, user=request.user)
messages.success(request, 'Ihre Zahlung wurde erfolgreich verarbeitet!')
return render(request, 'products/payment_success.html', {'order': order})
@login_required
def payment_failed(request, order_id):
"""Zeigt die Fehlerseite nach fehlgeschlagener Zahlung an."""
order = get_object_or_404(Order, id=order_id, user=request.user)
messages.error(request, 'Die Zahlung konnte nicht verarbeitet werden. Bitte versuchen Sie es erneut.')
return render(request, 'products/payment_failed.html', {'order': order})
# Hilfsfunktionen für E-Mail-Benachrichtigungen
def send_payment_confirmation_email(order):
"""Sendet eine Bestätigungs-E-Mail nach erfolgreicher Zahlung."""
subject = f'Zahlungsbestätigung für Bestellung #{order.id}'
message = f"""
Sehr geehrte(r) {order.full_name},
vielen Dank für Ihre Zahlung. Ihre Bestellung #{order.id} wurde erfolgreich bezahlt.
Bestelldetails:
- Gesamtbetrag: {order.total_amount}
- Zahlungsmethode: {order.get_payment_method_display()}
- Zahlungsdatum: {order.payment_date.strftime('%d.%m.%Y %H:%M')}
Wir werden Ihre Bestellung schnellstmöglich bearbeiten.
Mit freundlichen Grüßen
Ihr Fursuit-Shop Team
"""
send_mail(
subject,
message,
settings.DEFAULT_FROM_EMAIL,
[order.email],
fail_silently=False,
)
def send_payment_failed_email(order):
"""Sendet eine Benachrichtigung nach fehlgeschlagener Zahlung."""
subject = f'Zahlungsproblem bei Bestellung #{order.id}'
message = f"""
Sehr geehrte(r) {order.full_name},
leider ist die Zahlung für Ihre Bestellung #{order.id} fehlgeschlagen.
Sie können die Zahlung unter folgendem Link erneut versuchen:
{settings.SITE_URL}/payment/{order.id}/
Falls Sie Fragen haben, kontaktieren Sie uns bitte.
Mit freundlichen Grüßen
Ihr Fursuit-Shop Team
"""
send_mail(
subject,
message,
settings.DEFAULT_FROM_EMAIL,
[order.email],
fail_silently=False,
)
@login_required
def payment_process(request, order_id):
order = get_object_or_404(Order, id=order_id, user=request.user)
if request.method == 'POST':
# Initiiere PayPal-Zahlung
paypal_dict = {
"business": settings.PAYPAL_RECEIVER_EMAIL,
"amount": str(order.total_amount),
"item_name": f"Bestellung #{order.id}",
"invoice": str(order.id),
"notify_url": request.build_absolute_uri(reverse('paypal-ipn')),
"return_url": request.build_absolute_uri(reverse('payment_success', args=[order.id])),
"cancel_return": request.build_absolute_uri(reverse('payment_failed', args=[order.id])),
"custom": json.dumps({
"order_id": order.id,
"user_id": request.user.id,
})
}
form = PayPalPaymentsForm(initial=paypal_dict)
return render(request, 'products/payment_process.html', {'order': order, 'form': form})
return render(request, 'products/payment_process.html', {'order': order})
@csrf_exempt
def paypal_ipn(request):
"""PayPal IPN (Instant Payment Notification) Handler"""
if request.method == "POST":
try:
ipn_obj = PayPalIPN(request.POST)
ipn_obj.verify()
if ipn_obj.payment_status == "Completed":
# Zahlung war erfolgreich
try:
order = Order.objects.get(id=ipn_obj.invoice)
order.status = 'paid'
order.payment_method = 'paypal'
order.payment_id = ipn_obj.txn_id
order.save()
# Sende Bestätigungs-E-Mail
send_payment_confirmation_email(order)
except Order.DoesNotExist:
pass
return HttpResponse("OK")
except Exception as e:
return HttpResponse(str(e))
return HttpResponse("OK")