Changeset - a74244efb44e
[Not reviewed]
0 5 3
Ben Sturmfels (bsturmfels) - 9 days ago 2024-10-08 15:01:32
ben@sturm.com.au
Record Stripe payment intent, export to CSV
8 files changed with 86 insertions and 7 deletions:
0 comments (0 inline, 0 general)
conservancy/settings/dev.py
Show inline comments
 
import os
 

	
 
from .base import *  # NOQA
 

	
 
DEBUG = True
...
 
@@ -13,3 +15,6 @@ DATABASES = {
 
SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
 

	
 
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
 

	
 
STRIPE_API_KEY = os.getenv('STRIPE_API_KEY', '')
 
STRIPE_ENDPOINT_SECRET = os.getenv('STRIPE_ENDPOINT_SECRET', '')
conservancy/settings/prod.py
Show inline comments
...
 
@@ -37,3 +37,6 @@ def get_secret(secrets, setting):
 
SECRET_KEY = get_secret(secrets, 'SECRET_KEY')
 

	
 
SESSION_COOKIE_SECURE = True
 

	
 
STRIPE_API_KEY = get_secret(secrets, 'STRIPE_API_KEY')
 
STRIPE_ENDPOINT_SECRET = get_secret(secrets, 'STRIPE_ENDPOINT_SECRET')
conservancy/supporters/admin.py
Show inline comments
...
 
@@ -13,6 +13,8 @@ class SustainerOrderAdmin(admin.ModelAdmin):
 
    fields = [
 
        'created_time',
 
        'paid_time',
 
        'payment_method',
 
        'payment_id',
 
        'name',
 
        'email',
 
        'amount',
...
 
@@ -26,6 +28,6 @@ class SustainerOrderAdmin(admin.ModelAdmin):
 
        'country',
 
    ]
 

	
 
    readonly_fields = ['created_time', 'paid_time']
 
    readonly_fields = ['created_time', 'paid_time', 'payment_method', 'payment_id']
 
    list_display = ['created_time', 'name', 'email', 'amount', 'paid']
 
    list_filter = ['paid_time']
conservancy/supporters/management/commands/__init__.py
Show inline comments
 
new file 100644
conservancy/supporters/management/commands/export_stripe.py
Show inline comments
 
new file 100644
 
import csv
 
import sys
 

	
 
from django.core.management.base import BaseCommand
 
from ...models import SustainerOrder
 

	
 

	
 
class Command(BaseCommand):
 
    help = "Closes the specified poll for voting"
 

	
 
    def handle(self, *args, **options):
 
        orders = SustainerOrder.objects.filter(paid_time__isnull=False)
 
        columns = ['time', 'name', 'email', 'amount', 'transaction_id', 'public_ack', 'shirt_size', 'join_list', 'street', 'city', 'state', 'zip_code', 'country']
 
        writer = csv.writer(sys.stdout)
 
        writer.writerow(columns)
 
        for order in orders:
 
            writer.writerow([
 
                order.created_time,
 
                order.name,
 
                order.email,
 
                order.amount,
 
                order.payment_id,
 
                order.acknowledge_publicly,
 
                repr(order.tshirt_size if order.tshirt_size else ''),
 
                order.add_to_mailing_list,
 
                order.street,
 
                order.city,
 
                order.state,
 
                order.zip_code,
 
                order.country,
 
            ])
conservancy/supporters/migrations/0004_sustainerorder_payment_id_and_more.py
Show inline comments
 
new file 100644
 
# Generated by Django 4.2.11 on 2024-10-08 09:44
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('supporters', '0003_remove_sustainerorder_monthly_recurring_and_more'),
 
    ]
 

	
 
    operations = [
 
        migrations.AddField(
 
            model_name='sustainerorder',
 
            name='payment_id',
 
            field=models.CharField(blank=True, max_length=255),
 
        ),
 
        migrations.AddField(
 
            model_name='sustainerorder',
 
            name='payment_method',
 
            field=models.CharField(default='Stripe', max_length=10),
 
        ),
 
    ]
conservancy/supporters/models.py
Show inline comments
...
 
@@ -27,7 +27,7 @@ class SustainerOrder(models.Model):
 
    TSHIRT_CHOICES = [
 
        (
 
            '',
 
            (("None", "None"),),
 
            (("", "None"),),
 
        ),
 
        (
 
            "Men's",
...
 
@@ -69,10 +69,12 @@ class SustainerOrder(models.Model):
 
            validators.MinValueValidator(100),
 
        ])
 
    recurring = models.CharField(max_length=10)
 
    payment_method = models.CharField(max_length=10, default='Stripe')
 
    payment_id = models.CharField(max_length=255, blank=True)
 
    paid_time = models.DateTimeField(null=True, blank=True)
 
    acknowledge_publicly = models.BooleanField(default=True)
 
    add_to_mailing_list = models.BooleanField(default=True)
 
    tshirt_size = models.CharField(max_length=50, choices=TSHIRT_CHOICES)
 
    tshirt_size = models.CharField(max_length=50, choices=TSHIRT_CHOICES, blank=True)
 
    street = models.CharField(max_length=255, blank=True)
 
    city = models.CharField(max_length=255, blank=True)
 
    state = models.CharField(max_length=255, blank=True)
conservancy/supporters/views.py
Show inline comments
 
from datetime import datetime
 
import logging
 

	
 
from django.conf import settings
 
from django.http import HttpResponse
 
from django.shortcuts import render, redirect
 
from django.utils import timezone
...
 
@@ -47,6 +48,7 @@ def sponsors(request):
 

	
 
def create_checkout_session(reference_id, email: str, amount: int, recurring: str, base_url: str):
 
    # https://docs.stripe.com/payments/accept-a-payment
 
    # https://docs.stripe.com/api/checkout/sessions
 
    YOUR_DOMAIN = base_url
 
    try:
 
        checkout_session = stripe.checkout.Session.create(
...
 
@@ -94,7 +96,10 @@ def sustainers_stripe2(request):
 
    return render(request, 'supporters/sustainers_stripe2.html', {'form': form})
 

	
 

	
 
stripe.api_key = 'sk_test_zaAqrpHmpkXnHQfAs4UWkE3d'
 
stripe.api_key = settings.STRIPE_API_KEY
 
if stripe.api_key == '':
 
    logger.warning('Missing STRIPE_API_KEY')
 

	
 

	
 
def fulfill_checkout(session_id):
 
    print("Fulfilling Checkout Session", session_id)
...
 
@@ -108,7 +113,7 @@ def fulfill_checkout(session_id):
 
    # Retrieve the Checkout Session from the API with line_items expanded
 
    checkout_session = stripe.checkout.Session.retrieve(
 
        session_id,
 
        expand=['line_items'],
 
        expand=['line_items', 'invoice'],
 
    )
 

	
 
    # Check the Checkout Session's payment_status property
...
 
@@ -121,7 +126,13 @@ def fulfill_checkout(session_id):
 
        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.paid_time = timezone.now()
 
            if checkout_session['payment_intent']:
 
                # Payments get a payment intent directly
 
                order.payment_id = checkout_session['payment_intent']
 
            else:
 
                # Subscriptions go get a payment intent generated on the invoice
 
                order.payment_id = checkout_session['invoice']['payment_intent']
 
            order.save()
 
            logger.info(f'Marked sustainer order {order.id} (order.email) as paid')
 
        except SustainerOrder.DoesNotExist:
...
 
@@ -139,7 +150,9 @@ def webhook(request):
 
    event = None
 

	
 
    # From webhook dashboard
 
    endpoint_secret = 'whsec_lLy9pqxAAHdl4fwiC0cFg1KwR6y4CvOH'
 
    endpoint_secret = settings.STRIPE_ENDPOINT_SECRET
 
    if endpoint_secret == '':
 
        logger.warning('Missing STRIPE_ENDPOINT_SECRET')
 

	
 
    try:
 
        event = stripe.Webhook.construct_event(
0 comments (0 inline, 0 general)