diff options
-rw-r--r-- | doc/modules.rst | 20 | ||||
-rw-r--r-- | payments/braintree/__init__.py | 43 | ||||
-rw-r--r-- | payments/braintree/forms.py | 33 | ||||
-rwxr-xr-x | setup.py | 3 |
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') @@ -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) |