128 lines
3.5 KiB
Python
128 lines
3.5 KiB
Python
import forms
|
|
import models
|
|
|
|
from django.core.exceptions import ValidationError
|
|
from django.conf import settings
|
|
from django.contrib import messages
|
|
from django.db import transaction
|
|
from django.http import HttpResponse
|
|
from django.shortcuts import redirect, render
|
|
|
|
from registrasion.controllers.invoice import InvoiceController
|
|
from registrasion.models import commerce
|
|
|
|
from pinax.stripe import actions
|
|
from stripe.error import StripeError
|
|
|
|
from symposion.conference.models import Conference
|
|
|
|
CURRENCY = settings.INVOICE_CURRENCY
|
|
CONFERENCE_ID = settings.CONFERENCE_ID
|
|
|
|
|
|
def pubkey_script(request):
|
|
''' Returns a JS snippet that sets the Stripe public key for Stripe.js. '''
|
|
|
|
script_template = "Stripe.setPublishableKey('%s');"
|
|
script = script_template % settings.PINAX_STRIPE_PUBLIC_KEY
|
|
|
|
return HttpResponse(script, content_type="text/javascript")
|
|
|
|
|
|
def card(request, invoice_id):
|
|
''' View that shows and processes a Stripe CreditCardForm to pay the given
|
|
invoice. Redirects back to the invoice once the invoice is fully paid.
|
|
|
|
Arguments:
|
|
invoice_id (castable to str): The invoice id for the invoice to pay.
|
|
|
|
'''
|
|
|
|
form = forms.CreditCardForm(request.POST or None)
|
|
|
|
inv = InvoiceController.for_id_or_404(str(invoice_id))
|
|
|
|
if not inv.can_view(user=request.user):
|
|
raise Http404()
|
|
|
|
to_invoice = redirect("invoice", inv.invoice.id)
|
|
|
|
if inv.invoice.balance_due() <= 0:
|
|
return to_invoice
|
|
|
|
if request.POST and form.is_valid():
|
|
try:
|
|
inv.validate_allowed_to_pay() # Verify that we're allowed to do this.
|
|
process_card(request, form, inv)
|
|
return to_invoice
|
|
except StripeError as e:
|
|
form.add_error(None, ValidationError(e))
|
|
except ValidationError as ve:
|
|
form.add_error(None, ve)
|
|
|
|
data = {
|
|
"invoice": inv.invoice,
|
|
"form": form,
|
|
}
|
|
|
|
return render(
|
|
request, "registrasion/stripe/credit_card_payment.html", data
|
|
)
|
|
|
|
|
|
@transaction.atomic
|
|
def process_card(request, form, inv):
|
|
''' Processes the given credit card form
|
|
|
|
Arguments:
|
|
request: the current request context
|
|
form: a CreditCardForm
|
|
inv: an InvoiceController
|
|
'''
|
|
|
|
conference = Conference.objects.get(id=CONFERENCE_ID)
|
|
amount_to_pay = inv.invoice.balance_due()
|
|
|
|
token = form.cleaned_data["stripe_token"]
|
|
|
|
customer = actions.customers.get_customer_for_user(request.user)
|
|
|
|
if not customer:
|
|
customer = actions.customers.create(request.user)
|
|
|
|
card = actions.sources.create_card(customer, token)
|
|
|
|
description="Payment for %s invoice #%s" % (
|
|
conference.title, inv.invoice.id
|
|
)
|
|
|
|
try:
|
|
charge = actions.charges.create(
|
|
amount_to_pay,
|
|
customer,
|
|
currency=CURRENCY,
|
|
description=description,
|
|
capture=False,
|
|
)
|
|
|
|
receipt = charge.stripe_charge.receipt_number
|
|
if not receipt:
|
|
receipt = charge.stripe_charge.id
|
|
reference = "Paid with Stripe receipt number: " + receipt
|
|
|
|
# Create the payment object
|
|
models.StripePayment.objects.create(
|
|
invoice=inv.invoice,
|
|
reference=reference,
|
|
amount=charge.amount,
|
|
charge=charge,
|
|
)
|
|
except StripeError as e:
|
|
raise e
|
|
finally:
|
|
# Do not actually charge the account until we've reconciled locally.
|
|
actions.charges.capture(charge)
|
|
|
|
inv.update_status()
|
|
|
|
messages.success(request, "This invoice was successfully paid.")
|