website/conservancy/supporters/views.py

154 lines
5 KiB
Python

from datetime import datetime
import logging
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.utils import timezone
import stripe
from .. import ParameterValidator
from . import forms
from .models import Supporter, SustainerOrder
logger = logging.getLogger(__name__)
def sustainers(request):
with ParameterValidator(request.GET, 'upgrade_id') as validator:
try:
amount_param = float(request.GET['upgrade'])
except (KeyError, ValueError):
validator.fail()
else:
validator.validate('{:.2f}'.format(amount_param))
partial_amount = amount_param if validator.valid else 0
context = {
'partial_amount': partial_amount,
'minimum_amount': 120 - partial_amount,
}
return render(request, "supporters/sustainers.html", context)
def sponsors(request):
"""Conservancy Sponsors Page view
Performs object queries necessary to render the sponsors page.
"""
supporters = Supporter.objects.all().filter(display_until_date__gte=datetime.now())
supporters_count = len(supporters)
anonymous_count = len(supporters.filter(display_name='Anonymous'))
supporters = supporters.exclude(display_name='Anonymous').order_by('ledger_entity_id')
c = {
'supporters' : supporters,
'supporters_count' : supporters_count,
'anonymous_count' : anonymous_count
}
return render(request, "supporters/sponsors.html", c)
def create_checkout_session(reference_id, email, amount, base_url):
YOUR_DOMAIN = base_url
try:
checkout_session = stripe.checkout.Session.create(
client_reference_id=str(reference_id),
line_items=[
{
'price_data': {
'currency': 'usd',
'product_data': {'name': 'Contribution'},
'unit_amount': amount * 100,
},
'quantity': 1,
},
],
customer_email=email,
mode='payment',
success_url=YOUR_DOMAIN + '/sustainer/success/?session_id={CHECKOUT_SESSION_ID}',
cancel_url=YOUR_DOMAIN + '/sustainer/stripe/',
)
except Exception as e:
return str(e)
return checkout_session.url
def sustainers_stripe(request):
return render(request, 'supporters/sustainers_stripe.html', {})
def sustainers_stripe2(request):
if request.method == 'POST':
form = forms.SustainerForm(request.POST)
if form.is_valid():
order = form.save()
base_url = f'{request.scheme}://{request.get_host()}'
stripe_checkout_url = create_checkout_session(order.id, order.email, order.amount, base_url)
return redirect(stripe_checkout_url)
else:
form = forms.SustainerForm()
return render(request, 'supporters/sustainers_stripe2.html', {'form': form})
stripe.api_key = 'sk_test_zaAqrpHmpkXnHQfAs4UWkE3d'
def fulfill_checkout(session_id):
print("Fulfilling Checkout Session", session_id)
# TODO: Make this function safe to run multiple times,
# even concurrently, with the same session ID
# TODO: Make sure fulfillment hasn't already been
# peformed for this Checkout Session
# Retrieve the Checkout Session from the API with line_items expanded
checkout_session = stripe.checkout.Session.retrieve(
session_id,
expand=['line_items'],
)
# Check the Checkout Session's payment_status property
# to determine if fulfillment should be peformed
if checkout_session.payment_status != 'unpaid':
# TODO: Perform fulfillment of the line items
# TODO: Record/save fulfillment status for this
# Checkout Session
logger.info(f'Session ID {session_id} PAID!')
try:
order = SustainerOrder.objects.get(id=checkout_session['client_reference_id'], paid_time=None)
order.paid_time=timezone.now()
order.save()
logger.info(f'Marked sustainer order {order.id} (order.email) as paid')
except SustainerOrder.DoesNotExist:
logger.info('No action')
def success(request):
fulfill_checkout(request.GET['session_id'])
return render(request, 'supporters/stripe_success.html', {})
def webhook(request):
payload = request.body
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
event = None
# From webhook dashboard
endpoint_secret = 'whsec_lLy9pqxAAHdl4fwiC0cFg1KwR6y4CvOH'
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError:
# Invalid payload
return HttpResponse(status=400)
except stripe.error.SignatureVerificationError:
# Invalid signature
return HttpResponse(status=400)
if (
event['type'] == 'checkout.session.completed'
or event['type'] == 'checkout.session.async_payment_succeeded'
):
fulfill_checkout(event['data']['object']['id'])
return HttpResponse(status=200)