Im trying to create an order for my application i have a big issue with the webhook
@login_required def cart_detail(request): # Try to fetch the cart for the logged-in user cart = Cart.objects.filter(user=request.user).first()
if not cart or not cart.items.exists(): # Ensure that cart has items
# If no cart exists or cart is empty, pass a flag to indicate an empty cart
context = {'cart_exists': False}
return render(request, 'services/cart_detail.html', context)
# Calculate the total price for the cart
total_price = sum(item.total_price() for item in cart.items.all())
context = {
'cart': cart,
'total_price': total_price,
'cart_exists': True,
'STRIPE_PUBLISHABLE_KEY': settings.STRIPE_PUBLISHABLE_KEY,
}
return render(request, 'services/cart_detail.html', context)
Payment is initiated with the cart detail goes to create checkout
class CreateCheckoutSessionView(View): def post(self, request, *args, **kwargs): cart = get_object_or_404(Cart, user=request.user)
if not cart.items.exists():
return JsonResponse({'error': 'Cart is empty'}, status=400)
line_items = []
total_price = 0 # To calculate total price of the cart for the order
# Prepare line items for Stripe
for item in cart.items.all():
name = item.plan.name if item.plan else item.extra_service.title
amount = int(item.get_price() * 100) # Amount in cents for Stripe
total_price += item.total_price()
line_items.append({
'price_data': {
'currency': 'usd',
'unit_amount': amount,
'product_data': {
'name': name,
},
},
'quantity': item.quantity,
})
success_url = request.build_absolute_uri('/success/')
cancel_url = request.build_absolute_uri('/cancel/')
# Create Stripe Checkout session
checkout_session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=line_items,
mode='payment',
success_url=success_url,
cancel_url=cancel_url,
)
# Create a temporary "unpaid" order to track the session
order = Order.objects.create(
user=request.user,
total_price=total_price,
order_number=checkout_session.id[:50], # Truncate to fit 50 characters
status='PENDING', # Order is pending payment
slug=checkout_session.id[:50], # Truncate to fit 50 characters
)
# Save Stripe checkout session ID to the order
order.stripe_checkout_id = checkout_session.id
order.save()
# Save Stripe checkout session ID to the cart
cart.stripe_checkout_id = checkout_session.id
cart.save()
# Clear the cart after creating OrderItems
cart.items.all().delete()
# Return the session ID in JSON response
return JsonResponse({'id': checkout_session.id})
class StripeWebhookView(View): def post(self, request, *args, **kwargs): payload = request.body sig_header = request.META['HTTP_STRIPE_SIGNATURE'] event = None
# Replace with your Stripe Webhook Secret
endpoint_secret = settings.STRIPE_WEBHOOK_SECRET
try:
# Verify the webhook signature
event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
except ValueError as e:
# Invalid payload
return JsonResponse({'error': 'Invalid payload'}, status=400)
except stripe.error.SignatureVerificationError as e:
# Invalid signature
return JsonResponse({'error': 'Invalid signature'}, status=400)
# Handle the event
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
# Retrieve the Order using the checkout session ID
order = Order.objects.filter(order_number=session['id']).first()
if order:
# Mark the order as PAID
order.status = 'PAID'
order.save()
# Send the order confirmation email
user = order.user
full_name = f"{user.first_name} {user.last_name}".strip() or user.email
# Collect all the items in the order and format them
item_lines = [
f"- {item.quantity}x {item.product} @ ${item.price}" for item in order.items.all()
]
item_details = "\n".join(item_lines)
# Construct the subject and message for the email
subject = f"🛒 New Order #{order.order_number} by {full_name}"
message = f"""
A new order has been placed.
Order ID: {order.order_number}
User: {full_name} ({user.email})
Company: {user.company or 'N/A'}
Total Price: ${order.total_price}
Items Ordered:
{item_details}
Please log in to the admin dashboard to view and process this order.
"""
# Send the email
send_mail(
subject,
message,
settings.DEFAULT_FROM_EMAIL,
['orders@saasiskey.com'],
fail_silently=False,
)
# Return a 200 response to acknowledge receipt of the event
return JsonResponse({'status': 'success'}, status=200)
i wanna create an order mark order as paid but only after payment went through with stripe, bit now it is created before payment is recorded, that is my issue i also wanna trigger a signal but it is not eign troggered