git subrepo pull vendor/registripe
Also update vendored_requirements to make sure we pull this in. subrepo: subdir: "vendor/registripe" merged: "9fc3645" upstream: origin: "git@gitlab.com:tchaypo/registrasion-stripe.git" branch: "lca2018" commit: "9fc3645" git-subrepo: version: "0.3.1" origin: "???" commit: "???"
This commit is contained in:
parent
6eaddfc1d8
commit
660690c5cf
27 changed files with 474 additions and 233 deletions
89
vendor/registripe/.gitignore
vendored
Normal file
89
vendor/registripe/.gitignore
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*,cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IPython Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# dotenv
|
||||||
|
.env
|
||||||
|
|
||||||
|
# virtualenv
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
4
vendor/registripe/.gitrepo
vendored
4
vendor/registripe/.gitrepo
vendored
|
@ -6,6 +6,6 @@
|
||||||
[subrepo]
|
[subrepo]
|
||||||
remote = git@gitlab.com:tchaypo/registrasion-stripe.git
|
remote = git@gitlab.com:tchaypo/registrasion-stripe.git
|
||||||
branch = lca2018
|
branch = lca2018
|
||||||
commit = 5ebd58154006e63d390c5feadafb9a19769c7455
|
commit = 9fc364586b2246801979da690bdf2387b8f53e42
|
||||||
parent = 5789cbd05e06742f4f7d5dfaf02c92cc8be6bfad
|
parent = 6eaddfc1d8dd08dfeaaf7101a827974c977f23f4
|
||||||
cmdver = 0.3.1
|
cmdver = 0.3.1
|
||||||
|
|
2
vendor/registripe/README.md
vendored
Normal file
2
vendor/registripe/README.md
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# registrasion-stripe
|
||||||
|
Provides Credit Card processing for Registrasion using the Stripe API.
|
223
vendor/registripe/forms.py
vendored
223
vendor/registripe/forms.py
vendored
|
@ -1,223 +0,0 @@
|
||||||
import copy
|
|
||||||
from registripe import models
|
|
||||||
|
|
||||||
from django import forms
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.db.models import F, Q
|
|
||||||
from django.forms import widgets
|
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
from django_countries import countries
|
|
||||||
from django_countries.fields import LazyTypedChoiceField
|
|
||||||
from django_countries.widgets import CountrySelectWidget
|
|
||||||
|
|
||||||
|
|
||||||
class NoRenderWidget(forms.widgets.HiddenInput):
|
|
||||||
|
|
||||||
def render(self, name, value, attrs=None):
|
|
||||||
return "<!-- no widget: " + name + " -->"
|
|
||||||
|
|
||||||
|
|
||||||
def secure_striped(field):
|
|
||||||
''' Calls stripe() with secure=True. '''
|
|
||||||
return striped(field, True)
|
|
||||||
|
|
||||||
|
|
||||||
def striped(field, secure=False):
|
|
||||||
|
|
||||||
oldwidget = field.widget
|
|
||||||
field.widget = StripeWidgetProxy(oldwidget, secure)
|
|
||||||
return field
|
|
||||||
|
|
||||||
|
|
||||||
class StripeWidgetProxy(widgets.Widget):
|
|
||||||
|
|
||||||
def __init__(self, underlying, secure=False):
|
|
||||||
self.underlying = underlying
|
|
||||||
self.secure = secure
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
|
||||||
copy_underlying = copy.deepcopy(self.underlying, memo)
|
|
||||||
return type(self)(copy_underlying, self.secure)
|
|
||||||
|
|
||||||
def __getattribute__(self, attr):
|
|
||||||
spr = super(StripeWidgetProxy, self).__getattribute__
|
|
||||||
if attr in ("underlying", "render", "secure", "__deepcopy__"):
|
|
||||||
return spr(attr)
|
|
||||||
else:
|
|
||||||
return getattr(self.underlying, attr)
|
|
||||||
|
|
||||||
def render(self, name, value, attrs=None):
|
|
||||||
|
|
||||||
if not attrs:
|
|
||||||
attrs = {}
|
|
||||||
|
|
||||||
attrs["data-stripe"] = name
|
|
||||||
|
|
||||||
if self.secure:
|
|
||||||
name = ""
|
|
||||||
|
|
||||||
return self.underlying.render(name, value, attrs=attrs)
|
|
||||||
|
|
||||||
|
|
||||||
class CreditCardForm(forms.Form):
|
|
||||||
|
|
||||||
required_css_class = 'label-required'
|
|
||||||
|
|
||||||
def _media(self):
|
|
||||||
js = (
|
|
||||||
'https://js.stripe.com/v2/',
|
|
||||||
reverse("registripe_pubkey"),
|
|
||||||
)
|
|
||||||
|
|
||||||
return forms.Media(js=js)
|
|
||||||
|
|
||||||
media = property(_media)
|
|
||||||
|
|
||||||
number = secure_striped(forms.CharField(
|
|
||||||
required=False,
|
|
||||||
label="Credit card Number",
|
|
||||||
help_text="Your credit card number, with or without spaces.",
|
|
||||||
max_length=255,
|
|
||||||
))
|
|
||||||
exp_month = secure_striped(forms.IntegerField(
|
|
||||||
required=False,
|
|
||||||
label="Card expiry month",
|
|
||||||
min_value=1,
|
|
||||||
max_value=12,
|
|
||||||
))
|
|
||||||
exp_year = secure_striped(forms.IntegerField(
|
|
||||||
required=False,
|
|
||||||
label="Card expiry year",
|
|
||||||
help_text="The expiry year for your card in 4-digit form",
|
|
||||||
min_value=timezone.now().year,
|
|
||||||
))
|
|
||||||
cvc = secure_striped(forms.CharField(
|
|
||||||
required=False,
|
|
||||||
min_length=3,
|
|
||||||
max_length=4,
|
|
||||||
))
|
|
||||||
|
|
||||||
stripe_token = forms.CharField(
|
|
||||||
max_length=255,
|
|
||||||
# required=True,
|
|
||||||
widget=NoRenderWidget(),
|
|
||||||
)
|
|
||||||
|
|
||||||
name = striped(forms.CharField(
|
|
||||||
required=True,
|
|
||||||
label="Cardholder name",
|
|
||||||
help_text="The cardholder's name, as it appears on the credit card",
|
|
||||||
max_length=255,
|
|
||||||
))
|
|
||||||
address_line1 = striped(forms.CharField(
|
|
||||||
required=True,
|
|
||||||
label="Cardholder account address, line 1",
|
|
||||||
max_length=255,
|
|
||||||
))
|
|
||||||
address_line2 = striped(forms.CharField(
|
|
||||||
required=False,
|
|
||||||
label="Cardholder account address, line 2",
|
|
||||||
max_length=255,
|
|
||||||
))
|
|
||||||
address_city = striped(forms.CharField(
|
|
||||||
required=True,
|
|
||||||
label="Cardholder account city",
|
|
||||||
max_length=255,
|
|
||||||
))
|
|
||||||
address_state = striped(forms.CharField(
|
|
||||||
required=True,
|
|
||||||
max_length=255,
|
|
||||||
label="Cardholder account state or province",
|
|
||||||
))
|
|
||||||
address_zip = striped(forms.CharField(
|
|
||||||
required=True,
|
|
||||||
max_length=255,
|
|
||||||
label="Cardholder account postal code",
|
|
||||||
))
|
|
||||||
address_country = striped(LazyTypedChoiceField(
|
|
||||||
label="Cardholder account country",
|
|
||||||
choices=countries,
|
|
||||||
widget=CountrySelectWidget,
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
class StripeRefundForm(forms.Form):
|
|
||||||
|
|
||||||
required_css_class = 'label-required'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
'''
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
user (User): The user whose charges we should filter to.
|
|
||||||
min_value (Decimal): The minimum value of the charges we should
|
|
||||||
show (currently, credit notes can only be cashed out in full.)
|
|
||||||
|
|
||||||
'''
|
|
||||||
user = kwargs.pop('user', None)
|
|
||||||
min_value = kwargs.pop('min_value', None)
|
|
||||||
super(StripeRefundForm, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
payment_field = self.fields['payment']
|
|
||||||
qs = payment_field.queryset
|
|
||||||
|
|
||||||
if user:
|
|
||||||
qs = qs.filter(
|
|
||||||
charge__customer__user=user,
|
|
||||||
)
|
|
||||||
|
|
||||||
if min_value is not None:
|
|
||||||
# amount >= amount_to_refund + amount_refunded
|
|
||||||
# No refunds yet
|
|
||||||
q1 = (
|
|
||||||
Q(charge__amount_refunded__isnull=True) &
|
|
||||||
Q(charge__amount__gte=min_value)
|
|
||||||
)
|
|
||||||
# There are some refunds
|
|
||||||
q2 = (
|
|
||||||
Q(charge__amount_refunded__isnull=False) &
|
|
||||||
Q(charge__amount__gte=(
|
|
||||||
F("charge__amount_refunded") + min_value))
|
|
||||||
)
|
|
||||||
qs = qs.filter(q1 | q2)
|
|
||||||
|
|
||||||
payment_field.queryset = qs
|
|
||||||
|
|
||||||
payment = forms.ModelChoiceField(
|
|
||||||
required=True,
|
|
||||||
queryset=models.StripePayment.objects.all(),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
'''{
|
|
||||||
From stripe.js details:
|
|
||||||
|
|
||||||
Card details:
|
|
||||||
|
|
||||||
The first argument to createToken is a JavaScript object containing credit
|
|
||||||
card data entered by the user. It should contain the following required
|
|
||||||
members:
|
|
||||||
|
|
||||||
number: card number as a string without any separators
|
|
||||||
(e.g., "4242424242424242")
|
|
||||||
exp_month: two digit number representing the card's expiration month
|
|
||||||
(e.g., 12)
|
|
||||||
exp_year: two or four digit number representing the card's expiration year
|
|
||||||
(e.g., 2017)
|
|
||||||
(The expiration date can also be passed as a single string.)
|
|
||||||
|
|
||||||
cvc: optional, but we highly recommend you provide it to help prevent fraud.
|
|
||||||
This is the card's security code, as a string (e.g., "123").
|
|
||||||
The following fields are entirely optional and cannot result in a token
|
|
||||||
creation failure:
|
|
||||||
|
|
||||||
name: cardholder name
|
|
||||||
address_line1: billing address line 1
|
|
||||||
address_line2: billing address line 2
|
|
||||||
address_city: billing address city
|
|
||||||
address_state: billing address state
|
|
||||||
address_zip: billing postal code as a string (e.g., "94301")
|
|
||||||
address_country: billing address country
|
|
||||||
}
|
|
||||||
'''
|
|
3
vendor/registripe/registripe/admin.py
vendored
Normal file
3
vendor/registripe/registripe/admin.py
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
120
vendor/registripe/registripe/forms.py
vendored
Normal file
120
vendor/registripe/registripe/forms.py
vendored
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
import copy
|
||||||
|
from registripe import models
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
import functools
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.db.models import F, Q
|
||||||
|
from django.forms import widgets
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from django_countries import countries
|
||||||
|
from django_countries.fields import LazyTypedChoiceField
|
||||||
|
from django_countries.widgets import CountrySelectWidget
|
||||||
|
|
||||||
|
from pinax.stripe import models as pinax_stripe_models
|
||||||
|
|
||||||
|
|
||||||
|
class StripeCardElement(forms.widgets.TextInput):
|
||||||
|
|
||||||
|
def render(self, name, value, attrs=None):
|
||||||
|
element = '''
|
||||||
|
<div class="registrasion-stripe-element" id='%s' style='"-moz-appearance: textfield; -webkit-appearance: textfield; appearance: field;"'>Please wait.</div>''' % (name, )
|
||||||
|
|
||||||
|
script = '''
|
||||||
|
<script type='text/javascript'>
|
||||||
|
window.addEventListener('load', function(event){
|
||||||
|
stripeify('%s');
|
||||||
|
});
|
||||||
|
</script>''' % (name)
|
||||||
|
return element + script
|
||||||
|
|
||||||
|
|
||||||
|
class StripeTokenWidget(forms.widgets.HiddenInput):
|
||||||
|
|
||||||
|
def render(self, name, value, attrs=None):
|
||||||
|
|
||||||
|
return '''
|
||||||
|
<div class='registrasion-stripe-token' style='display:none;'
|
||||||
|
data-input-id='%s'
|
||||||
|
></div>
|
||||||
|
''' % (name, )
|
||||||
|
|
||||||
|
|
||||||
|
class CreditCardForm(forms.Form):
|
||||||
|
|
||||||
|
required_css_class = 'label-required'
|
||||||
|
|
||||||
|
def _media(self):
|
||||||
|
js = (
|
||||||
|
'https://js.stripe.com/v3/',
|
||||||
|
reverse("registripe_form_handler"),
|
||||||
|
)
|
||||||
|
|
||||||
|
return forms.Media(js=js)
|
||||||
|
|
||||||
|
media = property(_media)
|
||||||
|
|
||||||
|
card = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label="Credit card",
|
||||||
|
max_length=255,
|
||||||
|
widget=StripeCardElement()
|
||||||
|
)
|
||||||
|
|
||||||
|
stripe_token = forms.CharField(
|
||||||
|
max_length=255,
|
||||||
|
#required=True,
|
||||||
|
widget=StripeTokenWidget(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class StripeRefundForm(forms.Form):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
'''
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
user (User): The user whose charges we should filter to.
|
||||||
|
min_value (Decimal): The minimum value of the charges we should
|
||||||
|
show (currently, credit notes can only be cashed out in full.)
|
||||||
|
|
||||||
|
'''
|
||||||
|
user = kwargs.pop('user', None)
|
||||||
|
min_value = kwargs.pop('min_value', None)
|
||||||
|
super(StripeRefundForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
payment_field = self.fields['payment']
|
||||||
|
qs = payment_field.queryset
|
||||||
|
|
||||||
|
if user:
|
||||||
|
qs = qs.filter(
|
||||||
|
charge__customer__user=user,
|
||||||
|
)
|
||||||
|
|
||||||
|
if min_value is not None:
|
||||||
|
# amount >= amount_to_refund + amount_refunded
|
||||||
|
# No refunds yet
|
||||||
|
q1 = (
|
||||||
|
Q(charge__amount_refunded__isnull=True) &
|
||||||
|
Q(charge__amount__gte=min_value)
|
||||||
|
)
|
||||||
|
# There are some refunds
|
||||||
|
q2 = (
|
||||||
|
Q(charge__amount_refunded__isnull=False) &
|
||||||
|
Q(charge__amount__gte=(
|
||||||
|
F("charge__amount_refunded") + min_value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
qs = qs.filter(q1 | q2)
|
||||||
|
|
||||||
|
payment_field.queryset = qs
|
||||||
|
|
||||||
|
payment = forms.ModelChoiceField(
|
||||||
|
required=True,
|
||||||
|
queryset=models.StripePayment.objects.all(),
|
||||||
|
)
|
|
@ -9,7 +9,6 @@ class StripePayment(commerce.PaymentBase):
|
||||||
|
|
||||||
charge = models.ForeignKey(Charge)
|
charge = models.ForeignKey(Charge)
|
||||||
|
|
||||||
|
|
||||||
class StripeCreditNoteRefund(commerce.CreditNoteRefund):
|
class StripeCreditNoteRefund(commerce.CreditNoteRefund):
|
||||||
|
|
||||||
charge = models.ForeignKey(Charge)
|
charge = models.ForeignKey(Charge)
|
13
vendor/registripe/registripe/templates/registrasion/stripe/credit_card_payment.html
vendored
Normal file
13
vendor/registripe/registripe/templates/registrasion/stripe/credit_card_payment.html
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "registrasion/stripe/credit_card_payment_.html" %}
|
||||||
|
|
||||||
|
{% comment %}
|
||||||
|
Blocks that you can override:
|
||||||
|
|
||||||
|
- balance_due
|
||||||
|
|
||||||
|
You MUST include the following in your template:
|
||||||
|
- {{ form.media.js }}
|
||||||
|
- the payment form, where the form's id="payent-form"
|
||||||
|
- there is a div with id="payment-errors"
|
||||||
|
|
||||||
|
{% endcomment %}
|
55
vendor/registripe/registripe/templates/registrasion/stripe/credit_card_payment_.html
vendored
Normal file
55
vendor/registripe/registripe/templates/registrasion/stripe/credit_card_payment_.html
vendored
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
{% extends "registrasion/base.html" %}
|
||||||
|
{% load registrasion_tags %}
|
||||||
|
|
||||||
|
{% block title %}Credit card payment for invoice #{{ invoice.id}}{% endblock %}
|
||||||
|
{% block heading %}Credit card payment for invoice #{{ invoice.id}}{% endblock %}
|
||||||
|
{% block lede %}
|
||||||
|
Credit card payments are processed by <a href="https://stripe.com">Stripe</a>.
|
||||||
|
We do not store any of your credit card data locally, but instead Stripe will securely tokenise your card details. To allow this, you must allow JavaScript from <code>js.stripe.com</code>.
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% block balance_due_outer %}
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<p>
|
||||||
|
{% block balance_due %}
|
||||||
|
You have ${{ invoice.balance_due }} remaining to pay on this invoice.
|
||||||
|
{% endblock %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
<div class="panel panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Card details</h3>
|
||||||
|
</div>
|
||||||
|
<form id="payment-form" method="post">
|
||||||
|
|
||||||
|
<div class="panel-body">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% include "registrasion/form.html" %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-footer">
|
||||||
|
<input id="pay" class="btn btn-primary" type="submit" value="Pay {{ invoice.balance_due }}" />
|
||||||
|
<a class="btn btn-default" href='{% url "invoice" invoice.id invoice.user.attendee.access_code %}'>Return to invoice</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block form_scripts %}
|
||||||
|
{% block add_form_control_class_script %}
|
||||||
|
<script>
|
||||||
|
elements = document.getElementsByClassName("registrasion-stripe-element");
|
||||||
|
Array.prototype.forEach.call(elements, function(element) {
|
||||||
|
element.setAttribute("class", "{% block form_control_class %}form-control{% endblock %}");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{{ form.media.js }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% endblock %}
|
68
vendor/registripe/registripe/templates/registrasion/stripe/js/form_handler.js
vendored
Normal file
68
vendor/registripe/registripe/templates/registrasion/stripe/js/form_handler.js
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
var stripe = Stripe('{{ PINAX_STRIPE_PUBLIC_KEY }}');
|
||||||
|
var elements = stripe.elements();
|
||||||
|
|
||||||
|
function stripeify(elementId) {
|
||||||
|
var element = elements.create(elementId);
|
||||||
|
element.mount('#' + elementId);
|
||||||
|
|
||||||
|
var htmlElement = document.getElementById(elementId);
|
||||||
|
var errors = elementId + "-errors";
|
||||||
|
htmlElement.insertAdjacentHTML("afterend", "<div id='" + errors + "' role='alert' class='help-block'></div>");
|
||||||
|
var displayError = document.getElementById(errors);
|
||||||
|
|
||||||
|
//Handle real-time validation errors from the card Element.
|
||||||
|
element.addEventListener('change', function(event) {
|
||||||
|
toggleErrorMessage(displayError, event.error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a token or display an error when the form is submitted.
|
||||||
|
var paymentForm = document.getElementById('payment-form');
|
||||||
|
paymentForm.addEventListener('submit', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
stripe.createToken(element).then(function(result) {
|
||||||
|
if (result.error) {
|
||||||
|
// Inform the user if there was an error
|
||||||
|
toggleErrorMessage(displayError, result.error);
|
||||||
|
} else {
|
||||||
|
// Send the token to your server
|
||||||
|
stripeTokenHandler(result.token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleErrorMessage(errorElement, maybeError) {
|
||||||
|
errorClass = inputErrorClassName();
|
||||||
|
if (maybeError) {
|
||||||
|
errorElement.textContent = maybeError.message;
|
||||||
|
errorElement.parentNode.classList.add(errorClass);
|
||||||
|
} else {
|
||||||
|
errorElement.textContent = '';
|
||||||
|
errorElement.parentNode.classList.remove(errorClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function inputErrorClassName() {
|
||||||
|
return {% block form_control_error_class %}"has-error"{% endblock %};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function stripeTokenHandler(token) {
|
||||||
|
// Insert the token ID into the form so it gets submitted to the server
|
||||||
|
|
||||||
|
var form = document.getElementById('payment-form');
|
||||||
|
tokenHolder = form.getElementsByClassName('registrasion-stripe-token')[0];
|
||||||
|
inputId = tokenHolder.dataset.inputId;
|
||||||
|
|
||||||
|
var hiddenInput = document.createElement('input');
|
||||||
|
hiddenInput.setAttribute('type', 'hidden');
|
||||||
|
hiddenInput.setAttribute('name', inputId);
|
||||||
|
hiddenInput.setAttribute('value', token.id);
|
||||||
|
|
||||||
|
tokenHolder.appendChild(hiddenInput);
|
||||||
|
|
||||||
|
// Submit the form
|
||||||
|
form.submit();
|
||||||
|
}
|
6
vendor/registripe/registripe/templates/registrasion/stripe/link_to_payment.html
vendored
Normal file
6
vendor/registripe/registripe/templates/registrasion/stripe/link_to_payment.html
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{% extends "registrasion/stripe/link_to_payment_.html" %}
|
||||||
|
|
||||||
|
{% comment %}
|
||||||
|
Blocks that you can override:
|
||||||
|
|
||||||
|
{% endcomment %}
|
7
vendor/registripe/registripe/templates/registrasion/stripe/link_to_payment_.html
vendored
Normal file
7
vendor/registripe/registripe/templates/registrasion/stripe/link_to_payment_.html
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{% comment %}
|
||||||
|
This is used in the default credit_note.html file to display Stripe funcationality if the app is loaded.
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<a class="btn btn-primary" href='{% url "registripe_card" invoice_id access_code %}'>Pay this invoice with Stripe</a>
|
||||||
|
{% endblock %}
|
6
vendor/registripe/registripe/templates/registrasion/stripe/link_to_refunds.html
vendored
Normal file
6
vendor/registripe/registripe/templates/registrasion/stripe/link_to_refunds.html
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{% extends "registrasion/stripe/link_to_refunds_.html" %}
|
||||||
|
|
||||||
|
{% comment %}
|
||||||
|
Blocks that you can override:
|
||||||
|
|
||||||
|
{% endcomment %}
|
9
vendor/registripe/registripe/templates/registrasion/stripe/link_to_refunds_.html
vendored
Normal file
9
vendor/registripe/registripe/templates/registrasion/stripe/link_to_refunds_.html
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% comment %}
|
||||||
|
This is used in the default invoice.html file to display Stripe funcationality if the app is loaded.
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h3>Stripe Refund</h3>
|
||||||
|
|
||||||
|
<p><a href="{% url 'registripe_refund' credit_note_id %}">View Stripe refund options</a></p>
|
||||||
|
{% endblock %}
|
6
vendor/registripe/registripe/templates/registrasion/stripe/refund.html
vendored
Normal file
6
vendor/registripe/registripe/templates/registrasion/stripe/refund.html
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{% extends "registrasion/stripe/refund_.html" %}
|
||||||
|
|
||||||
|
{% comment %}
|
||||||
|
Blocks that you can override:
|
||||||
|
|
||||||
|
{% endcomment %}
|
24
vendor/registripe/registripe/templates/registrasion/stripe/refund_.html
vendored
Normal file
24
vendor/registripe/registripe/templates/registrasion/stripe/refund_.html
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{% extends "registrasion/base.html" %}
|
||||||
|
{% load registrasion_tags %}
|
||||||
|
|
||||||
|
{% block title %}Stripe refunds for credit note #{{ credit_note.id}}{% endblock %}
|
||||||
|
{% block heading %}Stripe refunds for credit note #{{ credit_note.id}}{% endblock %}
|
||||||
|
{% block lede %}
|
||||||
|
Currently credit notes can only be cashed out in full in a single
|
||||||
|
transaction. If you need to cash out to multiple small payments, you will
|
||||||
|
need to manually invoke the refunds from the Stripe Dashboard.
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<p>This credit note is valued at ${{ credit_note.value }}.</p>
|
||||||
|
|
||||||
|
<h3>Available refunds</h3>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% include "registrasion/form.html" %}
|
||||||
|
<input id="submit" class="btn btn-primary" type="submit" value="Refund {{ credit_note.value }} to payment source" />
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
3
vendor/registripe/registripe/tests.py
vendored
Normal file
3
vendor/registripe/registripe/tests.py
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -7,9 +7,8 @@ from pinax.stripe.views import Webhook
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^card/([0-9]*)/$", views.card, name="registripe_card"),
|
url(r"^card/([0-9]*)/$", views.card, name="registripe_card"),
|
||||||
url(r"^card/([0-9]*)/([0-9A-Za-z]*)/$", views.card,
|
url(r"^card/([0-9]*)/([0-9A-Za-z]*)/$", views.card, name="registripe_card"),
|
||||||
name="registripe_card"),
|
url(r"^form_handler.js", views.form_handler, name="registripe_form_handler"),
|
||||||
url(r"^pubkey/$", views.pubkey_script, name="registripe_pubkey"),
|
|
||||||
url(r"^refund/([0-9]*)/$", views.refund, name="registripe_refund"),
|
url(r"^refund/([0-9]*)/$", views.refund, name="registripe_refund"),
|
||||||
url(r"^webhook/$", Webhook.as_view(), name="pinax_stripe_webhook"),
|
url(r"^webhook/$", Webhook.as_view(), name="pinax_stripe_webhook"),
|
||||||
]
|
]
|
|
@ -1,5 +1,7 @@
|
||||||
from registripe import forms
|
from registripe import forms
|
||||||
from registripe import models
|
from registripe import models
|
||||||
|
import forms
|
||||||
|
import models
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -14,6 +16,8 @@ from registrasion.controllers.credit_note import CreditNoteController
|
||||||
from registrasion.controllers.invoice import InvoiceController
|
from registrasion.controllers.invoice import InvoiceController
|
||||||
|
|
||||||
from pinax.stripe import actions
|
from pinax.stripe import actions
|
||||||
|
from pinax.stripe.actions import refunds as pinax_stripe_actions_refunds
|
||||||
|
from registrasion.models import commerce
|
||||||
|
|
||||||
from stripe.error import StripeError
|
from stripe.error import StripeError
|
||||||
|
|
||||||
|
@ -28,8 +32,19 @@ def _staff_only(user):
|
||||||
return user.is_staff
|
return user.is_staff
|
||||||
|
|
||||||
|
|
||||||
def pubkey_script(request):
|
def form_handler(request):
|
||||||
''' Returns a JS snippet that sets the Stripe public key for Stripe.js. '''
|
''' Renders a js file to process Stripe payments. '''
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"PINAX_STRIPE_PUBLIC_KEY": settings.PINAX_STRIPE_PUBLIC_KEY,
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"registrasion/stripe/js/form_handler.js",
|
||||||
|
data,
|
||||||
|
content_type="text/javascript",
|
||||||
|
)
|
||||||
|
|
||||||
script_template = "Stripe.setPublishableKey('%s');"
|
script_template = "Stripe.setPublishableKey('%s');"
|
||||||
script = script_template % settings.PINAX_STRIPE_PUBLIC_KEY
|
script = script_template % settings.PINAX_STRIPE_PUBLIC_KEY
|
||||||
|
@ -65,7 +80,7 @@ def card(request, invoice_id, access_code=None):
|
||||||
|
|
||||||
if request.POST and form.is_valid():
|
if request.POST and form.is_valid():
|
||||||
try:
|
try:
|
||||||
inv.validate_allowed_to_pay()
|
inv.validate_allowed_to_pay() # Verify that we're allowed to do this.
|
||||||
process_card(request, form, inv)
|
process_card(request, form, inv)
|
||||||
return to_invoice
|
return to_invoice
|
||||||
except StripeError as e:
|
except StripeError as e:
|
||||||
|
@ -185,7 +200,7 @@ def process_refund(cn, form):
|
||||||
"the credit note."
|
"the credit note."
|
||||||
)
|
)
|
||||||
|
|
||||||
refund = actions.refunds.create(charge, to_refund) # noqa
|
refund = actions.refunds.create(charge, to_refund)
|
||||||
|
|
||||||
models.StripeCreditNoteRefund.objects.create(
|
models.StripeCreditNoteRefund.objects.create(
|
||||||
parent=cn.credit_note,
|
parent=cn.credit_note,
|
4
vendor/registripe/requirements.txt
vendored
Normal file
4
vendor/registripe/requirements.txt
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
django-countries==4.0
|
||||||
|
pinax-stripe==3.2.1
|
||||||
|
requests>=2.11.1
|
||||||
|
stripe==1.38.0
|
35
vendor/registripe/setup.py
vendored
Normal file
35
vendor/registripe/setup.py
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
import registripe
|
||||||
|
|
||||||
|
|
||||||
|
def read_file(filename):
|
||||||
|
"""Read a file into a string."""
|
||||||
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
filepath = os.path.join(path, filename)
|
||||||
|
try:
|
||||||
|
return open(filepath).read()
|
||||||
|
except IOError:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="registrasion-stripe",
|
||||||
|
author="Christopher Neugebauer",
|
||||||
|
author_email="_@chrisjrn.com",
|
||||||
|
version=registripe.__version__,
|
||||||
|
description="Stripe-based payments for the Registrasion conference registration package.",
|
||||||
|
url="http://github.com/chrisjrn/registrasion-stripe/",
|
||||||
|
packages=find_packages(),
|
||||||
|
include_package_data=True,
|
||||||
|
classifiers=(
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Framework :: Django",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"Natural Language :: English",
|
||||||
|
"License :: OSI Approved :: Apache Software License",
|
||||||
|
),
|
||||||
|
install_requires=read_file("requirements.txt").splitlines(),
|
||||||
|
)
|
|
@ -1 +1,2 @@
|
||||||
vendor/registrasion
|
vendor/registrasion
|
||||||
|
vendor/registripe
|
||||||
|
|
Loading…
Reference in a new issue