diff --git a/backend/core/settings.py b/backend/core/settings.py index 85978ae..5907635 100644 --- a/backend/core/settings.py +++ b/backend/core/settings.py @@ -12,6 +12,8 @@ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get('DJANGO_SECRET', 'default') +STRIPE_SECRET_KEY = os.environ.get('STRIPE_SECRET_KEY', 'default') +STRIPE_WEBHOOK_SECRET = os.environ.get('STRIPE_WEBHOOK_SECRET', 'default') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True diff --git a/backend/core/urls.py b/backend/core/urls.py index 7e2404b..94019f9 100644 --- a/backend/core/urls.py +++ b/backend/core/urls.py @@ -4,10 +4,13 @@ from django.conf.urls.static import static from django.conf import settings +from .views import stripe_webhook + urlpatterns = [ path('admin/', admin.site.urls), path('api/token/', include('auth.urls')), path('api/accounts/', include('accounts.urls')), path('api/events/', include('events.urls')), path('api/tickets/', include('tickets.urls')), + path('api/stripe/webhook/', stripe_webhook, name='stripe-webhook'), ]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/backend/core/views.py b/backend/core/views.py new file mode 100644 index 0000000..147d446 --- /dev/null +++ b/backend/core/views.py @@ -0,0 +1,32 @@ +from django.views.decorators.csrf import csrf_exempt +from django.http import HttpResponse +import stripe + +from django.conf import settings +from tickets.models import Ticket + + +@csrf_exempt +def stripe_webhook(request) : + payload = request.body + sig_header = request.META['HTTP_STRIPE_SIGNATURE'] + event = None + + try : + event = stripe.Webhook.construct_event( + payload, sig_header, settings.STRIPE_WEBHOOK_SECRET + ) + except ValueError as e: + return HttpResponse(status=400) + + except stripe.error.SignatureVerificationError as e: + return HttpResponse(status=400) + + if event['type'] == 'payment_intent.succeeded': + payment_intent = event['data']['object'] + ticket_id = payment_intent['metadata']['ticket_id'] + ticket = Ticket.objects.get(id=ticket_id) + ticket.update(status='purchased') + ticket.save() + + return HttpResponse(status=200) \ No newline at end of file diff --git a/backend/events/models.py b/backend/events/models.py index a2f1211..4eda937 100644 --- a/backend/events/models.py +++ b/backend/events/models.py @@ -1,4 +1,5 @@ from django.db import models +from products.models import ProductImage # Create your models here. @@ -30,7 +31,7 @@ class Event (models.Model) : ) event_type = models.CharField(max_length=100, choices=event_type_choices) - + cover_image = models.ImageField(upload_to='event_cover_images/', default='event_cover_images/default.jpg') location = models.CharField(max_length=200) ticket_price = models.DecimalField(max_digits=10, decimal_places=2) created_at = models.DateTimeField(auto_now_add=True) diff --git a/backend/events/serializers.py b/backend/events/serializers.py index 2016b48..f080532 100644 --- a/backend/events/serializers.py +++ b/backend/events/serializers.py @@ -12,6 +12,7 @@ class Meta: 'phone', 'date', 'time', + 'cover_image', 'event_type', 'location', 'ticket_price', diff --git a/backend/requirements.txt b/backend/requirements.txt index dea3ff6..165a3ce 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -20,3 +20,4 @@ sqlparse==0.4.4 tomli==2.0.1 typing_extensions==4.6.3 tzdata==2022.6 +stripe diff --git a/backend/tickets/models.py b/backend/tickets/models.py index dbaf649..fa68e1c 100644 --- a/backend/tickets/models.py +++ b/backend/tickets/models.py @@ -4,8 +4,8 @@ status_enums = [ ('pending','Pending'), - ('approved','Approved'), - ('rejected','Rejected'), + ('purchased','Purchased'), + ('failed','Purchase Failed'), ('cancelled','Cancelled'), ] diff --git a/backend/tickets/urls.py b/backend/tickets/urls.py index 5dc91cc..125faa5 100644 --- a/backend/tickets/urls.py +++ b/backend/tickets/urls.py @@ -1,10 +1,11 @@ from django.urls import path,include from rest_framework.routers import DefaultRouter -from .views import TicketViewSet +from .views import TicketViewSet, CreatePaymentIntent router = DefaultRouter() router.register('', TicketViewSet, basename='ticket') urlpatterns = [ + path('create-payment-intent/', CreatePaymentIntent.as_view(), name='create-payment-intent'), path('', include(router.urls)), ] \ No newline at end of file diff --git a/backend/tickets/views.py b/backend/tickets/views.py index 20851c4..edf86d6 100644 --- a/backend/tickets/views.py +++ b/backend/tickets/views.py @@ -1,9 +1,40 @@ -from rest_framework import viewsets +from django.conf import settings +from rest_framework import viewsets +from rest_framework.views import APIView +from rest_framework.response import Response +import stripe from .models import Ticket from .serializers import TicketSerializer +from rest_framework import status + +stripe.api_key = settings.STRIPE_SECRET_KEY + # Create your views here. class TicketViewSet(viewsets.ModelViewSet): queryset = Ticket.objects.all() - serializer_class = TicketSerializer \ No newline at end of file + serializer_class = TicketSerializer + +class CreatePaymentIntent(APIView): + + def post(self, request, *args, **kwargs): + amount = request.data.get('amount') + print(request.data) + + try : + intent = stripe.PaymentIntent.create( + amount=amount, + currency='inr', + payment_method_types=['card','upi'], + metadata={ + 'ticket_id': request.data.get('ticket_id') + } + ) + return Response({ + 'clientSecret': intent['client_secret'] + }) + except Exception as e: + return Response({ + 'error': str(e) + }, status = status.HTTP_400_BAD_REQUEST)