You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
5.4 KiB
Python

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))