from datetime import timedelta from django.shortcuts import render, redirect from django.urls import reverse from django.conf import settings from django.contrib.auth.decorators import login_required from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound, Http404 from django.views.decorators.csrf import csrf_exempt from django.utils import timezone from django.contrib import messages from django.utils.translation import ugettext_lazy as _ from .forms import NewPaymentForm from .models import Payment, Subscription, BACKENDS, ACTIVE_BACKENDS, Feedback def require_backend(name): backend = BACKENDS.get(name) if not backend: raise Http404() if not backend.backend_enabled: raise Http404() return backend @login_required def new(request): if request.method != 'POST': return redirect('account:index') if Payment.objects.filter(user=request.user, status='new').count() > 10: messages.error(request, "Too many open payments.") return redirect('account:index') form = NewPaymentForm(request.POST) if not form.is_valid(): return redirect('account:index') if request.user.vpnuser.get_subscription() is not None: return redirect('account:index') subscr = form.cleaned_data['subscr'] == '1' backend_id = form.cleaned_data['method'] months = int(form.cleaned_data['time']) if backend_id not in ACTIVE_BACKENDS: return HttpResponseNotFound() if subscr: if months not in (3, 6, 12): return redirect('account:index') rps = Subscription( user=request.user, backend_id=backend_id, period=str(months) + 'm', ) rps.save() r = rps.backend.new_subscription(rps) else: payment = Payment.create_payment(backend_id, request.user, months) payment.save() r = payment.backend.new_payment(payment) if not r: payment.status = 'error' payment.save() raise Exception("Failed to initialize payment #%d" % payment.id) if isinstance(r, str): return render(request, 'payments/form.html', dict(html=r)) elif r is None: return redirect('payments:view', payment.id) return r def plain_callback(backend_name, method='callback'): @csrf_exempt def callback(request): backend = require_backend(backend_name) m = getattr(backend, method) if m and m(Payment, request): return HttpResponse() else: return HttpResponseBadRequest() return callback def payment_callback(backend_name): @csrf_exempt def callback(request, id): backend = require_backend(backend_name) p = Payment.objects.get(id=id) if backend.callback(p, request): return HttpResponse() else: return HttpResponseBadRequest() return callback def sub_callback(backend_name): @csrf_exempt def callback(request, id): backend = require_backend(backend_name) p = Subscription.objects.get(id=id) if backend.callback_subscr(p, request): return HttpResponse() else: return HttpResponseBadRequest() return callback @csrf_exempt def stripe_hook(request): backend = require_backend('stripe') if backend.webhook(request): return HttpResponse() else: return HttpResponseBadRequest() @login_required @csrf_exempt def view(request, id): p = Payment.objects.get(id=id, user=request.user) return render(request, 'payments/view.html', dict(payment=p)) @login_required def cancel(request, id): p = Payment.objects.get(id=id, user=request.user) if p.status == 'new': p.status = 'cancelled' p.save() return render(request, 'payments/view.html', dict(payment=p)) @login_required def cancel_subscr(request, id=None): if request.method == 'POST' and id: p = Subscription.objects.get(id=id, user=request.user) # Saving any feedback note feedback = request.POST.get('feedback') if feedback: feedback = feedback[:10000] f = Feedback(user=request.user, subscription=p, message=feedback) f.save() try: if p.backend.cancel_subscription(p): messages.add_message(request, messages.INFO, _("Subscription cancelled!")) else: messages.add_message(request, messages.ERROR, _("Could not cancel the subscription. It may have already been cancelled or caused an error.")) except NotImplementedError: pass return redirect('account:index') subscription = request.user.vpnuser.get_subscription(include_unconfirmed=True) return render(request, 'payments/cancel_subscr.html', { 'subscription': subscription, }) @login_required def return_subscr(request, id): p = Subscription.objects.get(id=id, user=request.user) if p.status == 'new': p.status = 'unconfirmed' p.save() return redirect('account:index') @login_required def list_payments(request): # Only show recent cancelled payments cancelled_limit = timezone.now() - timedelta(days=3) objects = request.user.payment_set.exclude(status='cancelled', created__lte=cancelled_limit) return render(request, 'payments/list.html', dict(payments=objects))