import pprint from datetime import datetime import stripe from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponse, JsonResponse from django.shortcuts import redirect, render from django.urls import reverse, reverse_lazy from django.views import View from django.views.decorators.csrf import csrf_exempt from django.views.generic.edit import CreateView from rest_framework.parsers import JSONParser from rest_framework.views import APIView from core.forms import NewUserForm from core.lib.products import assemble_plan_map from core.models import Plan, Session, User pp = pprint.PrettyPrinter(indent=4) # Create your views here class Home(View): template_name = "index.html" def get(self, request): return render(request, self.template_name) class Billing(LoginRequiredMixin, View): template_name = "billing.html" def get(self, request): context = {"plans": Plan.objects.all(), "user_plans": request.user.plans.all()} return render(request, self.template_name, context) class Order(LoginRequiredMixin, View): def get(self, request, product_id): try: session = stripe.checkout.Session.create( payment_method_types=settings.ALLOWED_PAYMENT_METHODS, mode="subscription", customer=request.user.stripe_id, line_items=assemble_plan_map(product_id_filter=product_id), success_url=request.build_absolute_uri(reverse("success")), cancel_url=request.build_absolute_uri(reverse("cancel")), ) Session.objects.create(user=request.user, session=session.id) return redirect(session.url) # return JsonResponse({'id': session.id}) except Exception as e: # Raise a server error return JsonResponse({"error": str(e)}, status=500) class Signup(CreateView): form_class = NewUserForm success_url = reverse_lazy("login") template_name = "registration/signup.html" class Portal(LoginRequiredMixin, View): def get(self, request): session = stripe.billing_portal.Session.create( customer=request.user.stripe_id, return_url=request.build_absolute_uri(reverse("billing")), ) return redirect(session.url) class Callback(APIView): parser_classes = [JSONParser] @csrf_exempt def post(self, request): payload = request.body sig_header = request.META["HTTP_STRIPE_SIGNATURE"] try: stripe.Webhook.construct_event( payload, sig_header, settings.STRIPE_ENDPOINT_SECRET ) except ValueError: # Invalid payload return HttpResponse(status=400) except stripe.error.SignatureVerificationError: # Invalid signature return HttpResponse(status=400) pp.pprint(request.data) if request.data is None: return JsonResponse({"success": False}, status=500) if "type" in request.data.keys(): rtype = request.data["type"] if rtype == "checkout.session.completed": session = request.data["data"]["object"]["id"] subscription_id = request.data["data"]["object"]["subscription"] session_map = Session.objects.get(session=session) print("querying session", session) if not session_map: return JsonResponse({"success": False}, status=500) user = session_map.user session_map.subscription_id = subscription_id session_map.save() if rtype == "customer.subscription.updated": stripe_id = request.data["data"]["object"]["customer"] if not stripe_id: print("No user found for customer:", stripe_id) return JsonResponse({"success": False}, status=500) user = User.objects.get(stripe_id=stripe_id) # ssubscription_active subscription_id = request.data["data"]["object"]["id"] sessions = Session.objects.filter(user=user) session = None for session_iter in sessions: if session_iter.subscription_id == subscription_id: session = session_iter if not session: print(f"No session found for subscription id {subscription_id}") return JsonResponse({"success": False}, status=500) # query Session objects # iterate and check against product_id session.request = request.data["request"]["id"] product_id = request.data["data"]["object"]["plan"]["id"] plan = Plan.objects.get(product_id=product_id) if not plan: print(f"Plan not found: {product_id}") return JsonResponse({"success": False}, status=500) session.plan = plan session.save() elif rtype == "payment_intent.succeeded": customer = request.data["data"]["object"]["customer"] print("customer", customer) user = User.objects.get(stripe_id=customer) if not user: print("No user found for customer:", customer) return JsonResponse({"success": False}, status=500) print("got", user.email) session = Session.objects.get(request=request.data["request"]["id"]) print("Got session", session) user.plans.add(session.plan) print("ADDING PLAN TO USER PLANS") user.last_payment = datetime.utcnow() user.save() elif rtype == "customer.subscription.deleted": customer = request.data["data"]["object"]["customer"] user = User.objects.get(stripe_id=customer) if not user: print("No user found for customer:", customer) return JsonResponse({"success": False}, status=500) product_id = request.data["data"]["object"]["plan"]["id"] plan = Plan.objects.get(product_id=product_id) user.plans.remove(plan) user.save() else: return JsonResponse({"success": False}, status=500) return JsonResponse({"success": True})