summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/modules.rst20
-rw-r--r--payments/braintree/__init__.py43
-rw-r--r--payments/braintree/forms.py33
-rwxr-xr-xsetup.py3
4 files changed, 98 insertions, 1 deletions
diff --git a/doc/modules.rst b/doc/modules.rst
index 599af57..35ece11 100644
--- a/doc/modules.rst
+++ b/doc/modules.rst
@@ -36,6 +36,26 @@ Example::
'endpoint': 'https://test.authorize.net/gateway/transact.dll'})}
+Braintree
+-------------
+
+.. class:: payments.braintree.BraintreeProvider(merchant_id, public_key, private_key)
+
+ This backend implements payments using `Braintree <https://www.braintreepayments.com/>`_.
+
+ :param merchant_id: Merchant ID assigned by Braintree
+ :param public_key: Public key assigned by Braintree
+ :param private_key: Private key assigned by Braintree
+
+Example::
+
+ # use sandbox
+ PAYMENT_VARIANTS = {
+ 'braintree': ('payments.braintree.BraintreeProvider', {
+ 'merchant_id': '112233445566',
+ 'public_key': '1234567890abcdef',
+ 'private_key': 'abcdef123456'})}
+
Dotpay
------
diff --git a/payments/braintree/__init__.py b/payments/braintree/__init__.py
new file mode 100644
index 0000000..6727dfd
--- /dev/null
+++ b/payments/braintree/__init__.py
@@ -0,0 +1,43 @@
+from django.shortcuts import redirect
+import braintree
+
+from .forms import BraintreePaymentForm
+from .. import get_payment_model, BasicProvider, RedirectNeeded
+
+
+Payment = get_payment_model()
+
+
+class BraintreeProvider(BasicProvider):
+
+ def __init__(self, *args, **kwargs):
+ self.merchant_id = kwargs.pop('merchant_id')
+ self.public_key = kwargs.pop('public_key')
+ self.private_key = kwargs.pop('private_key')
+
+ braintree.Configuration.configure(braintree.Environment.Sandbox,
+ merchant_id=self.merchant_id,
+ public_key=self.public_key,
+ private_key=self.private_key)
+
+ super(BraintreeProvider, self).__init__(*args, **kwargs)
+
+ def get_form(self, data=None):
+ kwargs = {
+ 'data': data,
+ 'payment': self.payment,
+ 'provider': self,
+ 'action': '',
+ }
+ form = BraintreePaymentForm(**kwargs)
+ if form.is_valid():
+ form.save()
+ raise RedirectNeeded(self.payment.get_success_url())
+ else:
+ self.payment.change_status('input')
+ return form
+
+ def process_data(self, request):
+ if self.payment.status == 'confirmed':
+ return redirect(self.payment.get_success_url())
+ return redirect(self.payment.get_failure_url())
diff --git a/payments/braintree/forms.py b/payments/braintree/forms.py
new file mode 100644
index 0000000..a7de66a
--- /dev/null
+++ b/payments/braintree/forms.py
@@ -0,0 +1,33 @@
+import braintree
+
+from ..forms import CreditCardPaymentForm as BaseCreditCardPaymentForm
+
+
+class BraintreePaymentForm(BaseCreditCardPaymentForm):
+
+ def clean(self):
+ data = self.cleaned_data
+
+ if not self.errors and not self.payment.transaction_id:
+ result = braintree.Transaction.sale({
+ "amount": self.payment.total,
+ "credit_card": {
+ "number": data.get("number").number,
+ "cvv": data.get('cvv2'),
+ "expiration_month": data.get('expiration').month,
+ "expiration_year": data.get('expiration').year,
+ },
+ })
+
+ if result.is_success:
+ self.transaction_id = result.transaction.id
+ else:
+ self._errors['__all__'] = self.error_class([result.message])
+ self.payment.change_status('error')
+
+ return data
+
+ def save(self):
+ braintree.Transaction.submit_for_settlement(self.transaction_id)
+ self.payment.transaction_id = self.transaction_id
+ self.payment.change_status('confirmed')
diff --git a/setup.py b/setup.py
index f15b7c1..8c24284 100755
--- a/setup.py
+++ b/setup.py
@@ -30,7 +30,8 @@ setup(
'pycrypto',
'PyJWT',
'requests>=1.2.0',
- 'stripe>=1.9.8'],
+ 'stripe>=1.9.8',
+ 'braintree'],
include_package_data=True,
test_suite='payments.tests',
zip_safe=False)