Django Stripe Webhook not consistent Statuscode 500 sometimes 201
L.S.
I am working on my first Django project and struggling with the Stripe integration. My webhook is acting inconsistently—it worked fine when running locally on localhost with the Stripe CLI. However, after deploying with Nginx and Gunicorn, it has become unreliable. Sometimes it goes through, but in most cases, I receive a 500 status code.
I want to send an email to the customer with a PDF attachment when the checkout.session.completed
webhook is triggered. I read that the webhook should return a 200 status code as quickly as possible; otherwise, Stripe might time out. Or could the issue be caused by a time difference between the request and the server?
Regardless, I’m unsure how to properly fix this. I’d really appreciate any guidance from someone with experience.
import datetime
import stripe
from django.conf import settings
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from webshop.models import Product, Customer, Order, OrderItem
from django.core.mail import EmailMessage
@csrf_exempt
def stripe_webhook(request):
payload = request.body
sig_header = request.META.get("HTTP_STRIPE_SIGNATURE")
endpoint_secret = settings.STRIPE_WEBHOOK_SECRET
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
return JsonResponse({"error": str(e)}, status=400)
except stripe.error.SignatureVerificationError as e:
return JsonResponse({"error": "Invalid signature"}, status=400)
# Handle checkout success
if event["type"] == "checkout.session.completed":
session = event["data"]["object"]
session_id = session["id"]
# Fetch line items from Stripe
line_items = stripe.checkout.Session.list_line_items(session_id)
# Extract order details
customer_email = session.get("customer_details").get("email")
customer_name = session.get("customer_details").get("name")
amount_total = session.get("amount_total") / 100
payment_status = session.get("payment_status") == "paid"
# Get or create customer
customer, created = Customer.objects.get_or_create(email=customer_email, defaults={"name": customer_name})
# Create new order
order = Order.objects.create(
customer=customer,
date_ordered=datetime.datetime.now(),
payment_status=payment_status,
total_price=amount_total,
)
ordered_products = [] # Store product names for email
# Add order items
for item in line_items["data"]:
product_name = item["description"]
quantity = item["quantity"]
# Get product from database
try:
product = Product.objects.get(name=product_name)
OrderItem.objects.create(order=order, product=product, quantity=quantity)
ordered_products.append(product_name)
except Product.DoesNotExist:
print(f"⚠️ Product '{product_name}' not found in database, skipping.")
print(f"✅ Order created: {order}")
if ordered_products:
send_email_with_pdf(ordered_products, customer_email)
return JsonResponse({"status": "Order created"}, status=201)
return JsonResponse({"status": "success"}, status=200)
def send_email_with_pdf(product_name_list, recipient_email):
try:
email = EmailMessage(
subject='Your PDF(s)',
body='Please find the attached PDFs.',
from_email='test123456733@gmail.com',
to=[recipient_email],
)
# Attach multiple PDFs
for name in product_name_list:
try:
product_obj = Product.objects.get(name=name)
if product_obj.remschema:
pdf_name = product_obj.remschema.name
pdf_content = product_obj.remschema.read()
email.attach(pdf_name, pdf_content, 'application/pdf')
except Product.DoesNotExist:
print(f"Product '{name}' not found.")
# Send the email only if there are attachments
if email.attachments:
email.send()
return "Email sent successfully!"
else:
return "No PDFs found to send."
except Product.DoesNotExist:
print("Product nog found")
return "PDF not found."
except Exception as e:
print(f"Error: {e}")
return f"Error: {e}"
I have the feeling that maybe the view is to slow?