summaryrefslogtreecommitdiff
path: root/payments
diff options
context:
space:
mode:
authorMichał Ociepka <michal@ociepka.info>2015-11-03 18:48:18 +0100
committerMichał Ociepka <michal@ociepka.info>2015-11-10 11:52:08 +0100
commit77bef1d701cf8bcc7cc5e1839ed3d55e9183c13c (patch)
treec5fbf9ee2fc5960bb4f098593928cdbabdafb17f /payments
parente178c0c618857ed4fbb68e2a6606d4c36e58c741 (diff)
downloaddjango-payments-taler-77bef1d701cf8bcc7cc5e1839ed3d55e9183c13c.tar.gz
django-payments-taler-77bef1d701cf8bcc7cc5e1839ed3d55e9183c13c.tar.bz2
django-payments-taler-77bef1d701cf8bcc7cc5e1839ed3d55e9183c13c.zip
Add Stripe without modal provider
Diffstat (limited to 'payments')
-rw-r--r--payments/forms.py4
-rw-r--r--payments/static/js/payments/stripe.js59
-rw-r--r--payments/stripe/__init__.py50
-rw-r--r--payments/stripe/forms.py41
-rw-r--r--payments/stripe/widgets.py13
5 files changed, 109 insertions, 58 deletions
diff --git a/payments/forms.py b/payments/forms.py
index 0f1bfd5..cb19465 100644
--- a/payments/forms.py
+++ b/payments/forms.py
@@ -51,8 +51,8 @@ class CreditCardPaymentForm(PaymentForm):
' For American Express the four digits found on the front side.'))
def __init__(self, *args, **kwargs):
- super(CreditCardPaymentForm, self).__init__(
- hidden_inputs=False, *args, **kwargs)
+ kwargs['hidden_inputs'] = False
+ super(CreditCardPaymentForm, self).__init__(*args, **kwargs)
if hasattr(self, 'VALID_TYPES'):
self.fields['number'].valid_types = self.VALID_TYPES
diff --git a/payments/static/js/payments/stripe.js b/payments/static/js/payments/stripe.js
index ce29e0d..af9d4c2 100644
--- a/payments/static/js/payments/stripe.js
+++ b/payments/static/js/payments/stripe.js
@@ -1,31 +1,32 @@
-(function() {
-
- function purchase() {
- var stripe_input = document.getElementById('stripe-id');
- stripe_input.value = '';
-
- StripeCheckout.open({
- key: stripe_input.getAttribute('data-key'),
- address: false,
- amount: stripe_input.getAttribute('data-amount'),
- currency: stripe_input.getAttribute('data-currency'),
- name: stripe_input.getAttribute('data-name'),
- description: stripe_input.getAttribute('data-description'),
- panelLabel: 'Checkout',
- token: function(result) {
- stripe_input.value = result.id;
- },
- closed: function() {
- stripe_input.form.submit();
+document.addEventListener('DOMContentLoaded', function () {
+ var stripeInput = document.getElementById('id_stripeToken');
+ var form = stripeInput.form;
+ var publishableKey = stripeInput.attributes['data-publishable-key'].value;
+ Stripe.setPublishableKey(publishableKey);
+ form.addEventListener('submit', function (e) {
+ var button = this.querySelector('[type=submit]');
+ button.disabled = true;
+ Stripe.card.createToken({
+ name: this.elements['name'].value,
+ number: this.elements['number'].value,
+ cvc: this.elements['cvv2'].value,
+ exp_month: this.elements['expiration_0'].value,
+ exp_year: this.elements['expiration_1'].value,
+ address_line1: stripeInput.attributes['data-address-line1'].value,
+ address_line2: stripeInput.attributes['data-address-line2'].value,
+ address_city: stripeInput.attributes['data-address-city'].value,
+ address_state: stripeInput.attributes['data-address-state'].value,
+ address_zip: stripeInput.attributes['data-address-zip'].value,
+ address_country: stripeInput.attributes['data-address-country'].value
+ }, function (status, response) {
+ if (400 <= status && status <= 500) {
+ alert(response.error.message);
+ button.disabled = false;
+ } else {
+ stripeInput.value = response.id;
+ form.submit();
}
});
- }
-
- $ = this.jQuery || this.Zepto || this.ender || this.$;
-
- if($) {
- $(purchase);
- } else {
- window.onload = purchase;
- }
-})();
+ e.preventDefault();
+ }, false);
+}, false);
diff --git a/payments/stripe/__init__.py b/payments/stripe/__init__.py
index 6a60f06..55be5ee 100644
--- a/payments/stripe/__init__.py
+++ b/payments/stripe/__init__.py
@@ -1,36 +1,60 @@
from __future__ import unicode_literals
+from decimal import Decimal
-from django.core.exceptions import ImproperlyConfigured
+import stripe
-
-from .forms import PaymentForm
-from .. import RedirectNeeded
+from .forms import ModalPaymentForm, PaymentForm
+from .. import RedirectNeeded, PaymentError
from ..core import BasicProvider
class StripeProvider(BasicProvider):
+ form_class = ModalPaymentForm
+
def __init__(self, public_key, secret_key, image='', name='', **kwargs):
+ stripe.api_key = secret_key
self.secret_key = secret_key
self.public_key = public_key
self.image = image
self.name = name
super(StripeProvider, self).__init__(**kwargs)
- if not self._capture:
- raise ImproperlyConfigured(
- 'Stripe does not support pre-authorization.')
def get_form(self, payment, data=None):
if payment.status == 'waiting':
payment.change_status('input')
- kwargs = {
- 'data': data,
- 'payment': payment,
- 'provider': self,
- 'hidden_inputs': False}
- form = PaymentForm(**kwargs)
+ form = self.form_class(
+ data=data, payment=payment, provider=self)
if form.is_valid():
form.save()
raise RedirectNeeded(payment.get_success_url())
return form
+
+ def capture(self, payment, amount=None):
+ amount = int((amount or payment.total) * 100)
+ charge = stripe.Charge.retrieve(payment.transaction_id)
+ try:
+ charge.capture(amount=amount)
+ except stripe.InvalidRequestError as e:
+ payment.change_status('refunded')
+ raise PaymentError('Payment already refunded')
+ payment.attrs.capture = stripe.util.json.dumps(charge)
+ return Decimal(amount) / 100
+
+ def release(self, payment):
+ charge = stripe.Charge.retrieve(payment.transaction_id)
+ charge.refund()
+ payment.attrs.release = stripe.util.json.dumps(charge)
+
+ def refund(self, payment, amount=None):
+ amount = int((amount or payment.total) * 100)
+ charge = stripe.Charge.retrieve(payment.transaction_id)
+ charge.refund(amount=amount)
+ payment.attrs.refund = stripe.util.json.dumps(charge)
+ return Decimal(amount) / 100
+
+
+class StripeCardProvider(StripeProvider):
+
+ form_class = PaymentForm
diff --git a/payments/stripe/forms.py b/payments/stripe/forms.py
index 5f4ea42..eaef15d 100644
--- a/payments/stripe/forms.py
+++ b/payments/stripe/forms.py
@@ -4,24 +4,16 @@ from django import forms
from django.utils.translation import ugettext as _
import stripe
-from .widgets import StripeWidget
+from .widgets import StripeCheckoutWidget, StripeWidget
from .. import RedirectNeeded
-from ..forms import PaymentForm as BasePaymentForm
+from ..forms import PaymentForm as BasePaymentForm, CreditCardPaymentFormWithName
from ..models import FRAUD_CHOICES
-class PaymentForm(BasePaymentForm):
+class StripeFormMixin(object):
charge = None
- def __init__(self, *args, **kwargs):
- super(PaymentForm, self).__init__(*args, **kwargs)
- widget = StripeWidget(provider=self.provider, payment=self.payment)
- self.fields['stripeToken'] = forms.CharField(widget=widget)
- if self.is_bound and not self.data.get('stripeToken'):
- self.payment.change_status('rejected')
- raise RedirectNeeded(self.payment.get_failure_url())
-
def _handle_potentially_fraudulent_charge(self, charge, commit=True):
fraud_details = charge['fraud_details']
if fraud_details.get('stripe_report', None) == 'fraudulent':
@@ -72,3 +64,30 @@ class PaymentForm(BasePaymentForm):
self.payment.transaction_id = self.charge.id
self.payment.captured_amount = self.payment.total
self.payment.change_status('confirmed')
+
+
+class ModalPaymentForm(StripeFormMixin, BasePaymentForm):
+
+ def __init__(self, *args, **kwargs):
+ super(StripeFormMixin, self).__init__(hidden_inputs=False, *args, **kwargs)
+ widget = StripeCheckoutWidget(provider=self.provider, payment=self.payment)
+ self.fields['stripeToken'] = forms.CharField(widget=widget)
+ if self.is_bound and not self.data.get('stripeToken'):
+ self.payment.change_status('rejected')
+ raise RedirectNeeded(self.payment.get_failure_url())
+
+
+class PaymentForm(StripeFormMixin, CreditCardPaymentFormWithName):
+
+ stripeToken = forms.CharField(widget=StripeWidget())
+
+ def __init__(self, *args, **kwargs):
+ super(PaymentForm, self).__init__(*args, **kwargs)
+ stripe_attrs = self.fields['stripeToken'].widget.attrs
+ stripe_attrs['data-publishable-key'] = self.provider.public_key
+ stripe_attrs['data-address-line1'] = self.payment.billing_address_1
+ stripe_attrs['data-address-line2'] = self.payment.billing_address_2
+ stripe_attrs['data-address-city'] = self.payment.billing_city
+ stripe_attrs['data-address-state'] = self.payment.billing_country_area
+ stripe_attrs['data-address-zip'] = self.payment.billing_postcode
+ stripe_attrs['data-address-country'] = self.payment.billing_country_code
diff --git a/payments/stripe/widgets.py b/payments/stripe/widgets.py
index e7d5071..bc7fd44 100644
--- a/payments/stripe/widgets.py
+++ b/payments/stripe/widgets.py
@@ -4,13 +4,13 @@ try:
from django.forms.utils import flatatt
except ImportError:
from django.forms.util import flatatt
-from django.forms.widgets import Input
+from django.forms.widgets import Input, HiddenInput
from django.utils.html import format_html
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
-class StripeWidget(Input):
+class StripeCheckoutWidget(Input):
is_hidden = True
def __init__(self, provider, payment, *args, **kwargs):
@@ -26,7 +26,7 @@ class StripeWidget(Input):
'data-currency': payment.currency
}
kwargs['attrs'].update(attrs)
- super(StripeWidget, self).__init__(*args, **kwargs)
+ super(StripeCheckoutWidget, self).__init__(*args, **kwargs)
def render(self, name, value, attrs=None):
if value is None:
@@ -38,3 +38,10 @@ class StripeWidget(Input):
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_text(self._format_value(value))
return format_html('<script{0}></script>', flatatt(final_attrs))
+
+
+class StripeWidget(HiddenInput):
+
+ class Media:
+ js = ['https://js.stripe.com/v2/',
+ 'js/payments/stripe.js']