website/conservancy/supporters/views.py

161 lines
5.6 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: str, amount: int, recurring: bool, base_url: str):
# https://docs.stripe.com/payments/accept-a-payment
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, # in cents
# https://docs.stripe.com/products-prices/pricing-models#variable-pricing
'recurring': {'interval': 'month'} if recurring else None,
},
'quantity': 1,
},
],
customer_email=email,
mode='subscription' if recurring else '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(commit=False)
if form.data['recurring'] == 'monthly':
order.amount = form.cleaned_data['amount_monthly']
order.monthly_recurring = True
order.save()
base_url = f'{request.scheme}://{request.get_host()}'
stripe_checkout_url = create_checkout_session(order.id, order.email, order.amount, order.monthly_recurring, 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)