Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base: 8506166902
...
compare: dacb21d4d4
  • 2 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
View
15 hiicart/gateway/base.py
@@ -147,10 +147,12 @@ def __init__(self, type, url=None):
class SubmitResult(object):
"""
The result of a submit operation.
- Currently supported result types are url, form, and None.
+ Currently supported result types are url, form, direct, and None.
url: The user should to be redirected to result.url.
form: form_action is the target url; form_fields is a dict of form data.
+ direct: form_action is the form target; form_fields is a dict of hidden form
+ required by the gateway.
None: type is set to None if no further action is required.
"""
def __init__(self, type, url=None, form_data=None):
@@ -164,3 +166,14 @@ def __init__(self, type, url=None, form_data=None):
else:
self.form_action = None
self.form_fields = None
+
+
+class PaymentResult(object):
+ """
+ Result for a payment confirmation.
+ Currently only supported with direct payment gateways.
+ """
+ def __init__(self, success, status, errors=None):
+ self.success = success
+ self.status = status
+ self.errors = errors
View
71 hiicart/gateway/braintree/forms.py
@@ -0,0 +1,71 @@
+import braintree
+
+from django import forms
+from django.forms.util import ErrorDict
+
+class PaymentForm(forms.Form):
+ """
+ Braintree payment form.
+ """
+ tr_data = forms.CharField(widget=forms.HiddenInput)
+ transaction__credit_card__cardholder_name = forms.CharField()
+ transaction__credit_card__number = forms.CharField()
+ transaction__credit_card__cvv = forms.CharField(min_length=3, max_length=4)
+ transaction__credit_card__expiration_month = forms.CharField(min_length=1, max_length=2)
+ transaction__credit_card__expiration_year = forms.CharField(min_length=4, max_length=4)
+ transaction__billing__first_name = forms.CharField(max_length=255)
+ transaction__billing__last_name = forms.CharField(max_length=255)
+ transaction__billing__street_address = forms.CharField(max_length=80)
+ transaction__billing__extended_address = forms.CharField(max_length=80)
+ transaction__billing__locality = forms.CharField(max_length=50)
+ transaction__billing__region = forms.CharField(max_length=50)
+ transaction__billing__postal_code = forms.CharField(max_length=30)
+ transaction__billing__country_code_alpha2 = forms.CharField(max_length=2)
+ transaction__shipping__first_name = forms.CharField(max_length=255)
+ transaction__shipping__last_name = forms.CharField(max_length=255)
+ transaction__shipping__street_address = forms.CharField(max_length=80)
+ transaction__shipping__extended_address = forms.CharField(max_length=80)
+ transaction__shipping__locality = forms.CharField(max_length=50)
+ transaction__shipping__region = forms.CharField(max_length=50)
+ transaction__shipping__postal_code = forms.CharField(max_length=30)
+ transaction__shipping__country_code_alpha2 = forms.CharField(max_length=2)
+
+ def __init__(self, *args, **kwargs):
+ tr_data = kwargs.pop('tr_data', '')
+ super(PaymentForm, self).__init__(*args, **kwargs)
+
+ def set_transaction(self, tr_data):
+ if self.is_bound:
+ self.data['tr_data'] = tr_data
+ else:
+ self.fields['tr_data'].initial = tr_data
+
+ def set_result(self, result):
+ """
+ Use the results of the gateway payment confirmation to set
+ validation errors on the form.
+ """
+ self._errors = ErrorDict()
+ self.is_bound = True
+ if not result.success:
+ for name, error in result.errors.items():
+ if name == 'cardholder_name':
+ name = 'transaction__credit_card__cardholder_name'
+ elif name == 'number':
+ name = 'transaction__credit_card__number'
+ elif name == 'cvv':
+ name = 'transaction__credit_card__cvv'
+ elif name == 'expiration_month':
+ name = 'transaction__credit_card__expiration_month'
+ elif name == 'expiration_year':
+ name = 'transaction__credit_card__expiration_year'
+ elif name == 'non_field_errors':
+ name = forms.forms.NON_FIELD_ERRORS
+ self._errors[name] = self.error_class([error])
+
+ @property
+ def action(self):
+ """
+ Action to post the form to.
+ """
+ return braintree.TransparentRedirect.url()
View
41 hiicart/gateway/braintree/gateway.py
@@ -2,7 +2,8 @@
from django.template import Context, loader
-from hiicart.gateway.base import PaymentGatewayBase, CancelResult, SubmitResult
+from hiicart.gateway.base import PaymentGatewayBase, CancelResult, SubmitResult, PaymentResult
+from hiicart.gateway.braintree.forms import PaymentForm
from hiicart.gateway.braintree.ipn import BraintreeIPN
from hiicart.gateway.braintree.settings import SETTINGS as default_settings
@@ -35,32 +36,46 @@ def store_return_url(self, request):
return self.settings["RETURN_URL"]
def submit(self, collect_address=False, cart_settings_kwargs=None, submit=False):
- """Returns the type of Gateway"""
+ """Submits a transaction to Braintree."""
return SubmitResult("direct")
- def form_data(self, return_url):
+ @property
+ def form(self):
+ """Return the payment form for the Braintree gateway."""
+ return PaymentForm()
+
+ def start_transaction(self, request):
"""Submits transaction details to Braintree and gets form data."""
- submit_url = braintree.TransparentRedirect.url()
tr_data = braintree.Transaction.tr_data_for_sale({
"transaction": {"type": "sale",
"order_id": self.cart.cart_uuid,
"amount": self.cart.total,
"options": {"submit_for_settlement": True}}},
- return_url)
- return {"action": submit_url,
- "fields": {"tr_data": tr_data}}
+ request.build_absolute_uri(request.path))
+ return tr_data
def confirm_payment(self, request):
"""Confirms payment with Braintree."""
try:
result = braintree.TransparentRedirect.confirm(request.META['QUERY_STRING'])
- except:
- return False
-
+ except Exception, e:
+ errors = {'non_field_errors': 'Request to payment gateway failed.'}
+ return PaymentResult(success=False, status=None, errors=errors)\
+
if result.is_success:
handler = BraintreeIPN(self.cart)
created = handler.new_order(result.transaction)
if created:
- self.cart.set_state("SUBMITTED")
- return True
- return False
+ return PaymentResult(success=True, status=result.transaction.status)
+ errors = {}
+ if not result.transaction:
+ status = None
+ for error in result.errors.deep_errors:
+ errors[error.attribute] = error.message
+ else:
+ status = result.transaction.status
+ if result.transaction.status == "processor_declined":
+ errors = {'non_field_errors': result.transaction.processor_response_text}
+ elif result.transaction.status == "gateway_rejected":
+ errors = {'non_field_errors': result.transaction.gateway_rejection_reason}
+ return PaymentResult(success=False, status=status, errors=errors)
View
33 hiicart/gateway/braintree/ipn.py
@@ -48,21 +48,22 @@ def new_order(self, transaction):
"""Save a new order."""
if not self.cart:
return
- self.cart.ship_first_name = transaction.shipping["first_name"]
- self.cart.ship_last_name = transaction.shipping["last_name"]
- self.cart.ship_street1 = transaction.shipping["street_address"]
- self.cart.ship_street2 = transaction.shipping["extended_address"]
- self.cart.ship_city = transaction.shipping["locality"]
- self.cart.ship_state = transaction.shipping["region"]
- self.cart.ship_postal_code = transaction.shipping["postal_code"]
- self.cart.ship_country = transaction.shipping["country_code_alpha2"]
- self.cart.bill_first_name = transaction.billing["first_name"]
- self.cart.bill_last_name = transaction.billing["last_name"]
- self.cart.bill_street1 = transaction.billing["street_address"]
- self.cart.bill_street2 = transaction.billing["extended_address"]
- self.cart.bill_city = transaction.billing["locality"]
- self.cart.bill_state = transaction.billing["region"]
- self.cart.bill_postal_code = transaction.billing["postal_code"]
- self.cart.bill_country = transaction.billing["country_code_alpha2"]
+ self.cart.ship_first_name = transaction.shipping["first_name"] or self.cart.ship_first_name
+ self.cart.ship_last_name = transaction.shipping["last_name"] or self.cart.ship_last_name
+ self.cart.ship_street1 = transaction.shipping["street_address"] or self.cart.ship_street1
+ self.cart.ship_street2 = transaction.shipping["extended_address"] or self.cart.ship_street2
+ self.cart.ship_city = transaction.shipping["locality"] or self.cart.ship_city
+ self.cart.ship_state = transaction.shipping["region"] or self.cart.ship_state
+ self.cart.ship_postal_code = transaction.shipping["postal_code"] or self.cart.ship_postal_code
+ self.cart.ship_country = transaction.shipping["country_code_alpha2"] or self.cart.ship_country
+ self.cart.bill_first_name = transaction.billing["first_name"] or self.cart.bill_first_name
+ self.cart.bill_last_name = transaction.billing["last_name"] or self.cart.bill_last_name
+ self.cart.bill_street1 = transaction.billing["street_address"] or self.cart.bill_street1
+ self.cart.bill_street2 = transaction.billing["extended_address"] or self.cart.bill_street2
+ self.cart.bill_city = transaction.billing["locality"] or self.cart.bill_city
+ self.cart.bill_state = transaction.billing["region"] or self.cart.bill_state
+ self.cart.bill_postal_code = transaction.billing["postal_code"] or self.cart.bill_postal_code
+ self.cart.bill_country = transaction.billing["country_code_alpha2"] or self.cart.bill_country
+ self.cart._cart_state = "SUBMITTED"
self.cart.save()
self.create_payment(transaction)

No commit comments for this range

Something went wrong with that request. Please try again.