diff --git a/.gitignore b/.gitignore index 0d20b64..13f461a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +config.py *.pyc diff --git a/config.py b/config.py new file mode 100644 index 0000000..2665df5 --- /dev/null +++ b/config.py @@ -0,0 +1,5 @@ +config = { + 'BRAINTREE_MERCHANT_ID':"your_merchant_id", + 'BRAINTREE_PUBLIC_KEY':"your_public_key", + 'BRAINTREE_PRIVATE_KEY':"your_private_key", +} \ No newline at end of file diff --git a/tr_checkout/checkout.py b/tr_checkout/checkout.py index c1cd837..40124cb 100644 --- a/tr_checkout/checkout.py +++ b/tr_checkout/checkout.py @@ -3,15 +3,20 @@ import urllib2 urllib2.install_opener(urllib2.build_opener()) +import os +parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +os.sys.path.insert(0,parentdir) +from config import config + import braintree import web import payment_form braintree.Configuration.configure( braintree.Environment.Sandbox, - "your_merchant_id", - "your_public_key", - "your_private_key" + config['BRAINTREE_MERCHANT_ID'], + config['BRAINTREE_PUBLIC_KEY'], + config['BRAINTREE_PRIVATE_KEY'], ) urls = ( diff --git a/tr_subscription/README.md b/tr_subscription/README.md new file mode 100644 index 0000000..aceebb3 --- /dev/null +++ b/tr_subscription/README.md @@ -0,0 +1,24 @@ +# tr_subscription + +## Overview + +This code is a demonstration of creating one time transactions using the +Braintree transparent redirect API. We decided to use the +[web.py](http://webpy.org/) framework because its simplicity +allows us to clearly demonstrate concepts without added noise. + +Assuming you have a plan with the following details: + + plan_id: "plan_1" + +## Getting started + +* pip install braintree +* pip install web.py +* Update config.py with your merchant_id, public_key and private_key +* cd tr_subscription +* python subscription.py +* Visit [http://localhost:8080/payments/new](http://localhost:8080/payments/new) + + + diff --git a/tr_subscription/payment_form.py b/tr_subscription/payment_form.py new file mode 100644 index 0000000..33a192b --- /dev/null +++ b/tr_subscription/payment_form.py @@ -0,0 +1,120 @@ +import web +import braintree + + +class PaymentForm(object): + def __init__(self, params={}, errors=braintree.ValidationErrorCollection()): + self.params = params + self.errors = errors + + def form(self): + form = self.__build_form() + return form() + + def __build_form(self): + return web.form.Form( + web.form.Textbox( + description="First Name", + name="customer[first_name]", + id="customer_customer_first_name", + value=self.__get_nested_param("customer", "first_name"), + post=self.__error_message(self.errors.for_object("customer").for_object("customer").on("first_name")), + class_=self.__error_class(self.errors.for_object("customer").for_object("customer").on("first_name")), + ), + web.form.Textbox( + description="Last Name", + name="customer[last_name]", + id="customer_customer_last_name", + value=self.__get_nested_param("customer", "last_name"), + post=self.__error_message(self.errors.for_object("customer").for_object("customer").on("last_name")), + class_=self.__error_class(self.errors.for_object("customer").for_object("customer").on("last_name")) + ), + web.form.Textbox( + description="Email", + name="customer[email]", + id="customer_customer_email", + value=self.__get_nested_param("customer", "email"), + post=self.__error_message(self.errors.for_object("customer").for_object("customer").on("email")), + class_=self.__error_class(self.errors.for_object("customer").for_object("customer").on("email")) + ), + web.form.Textbox( + description="Number", + name="customer[credit_card][number]", + id="customer_credit_card_number", + value=self.__get_nested_param("customer", "credit_card", "number"), + post=self.__error_message(self.errors.for_object("customer").for_object("credit_card").on("number")), + class_=self.__error_class(self.errors.for_object("customer").for_object("credit_card").on("number")) + ), + web.form.Textbox( + description="Expiration Date", + name="customer[credit_card][expiration_date]", + id="customer_credit_card_exipration_date", + value=self.__get_nested_param("customer", "credit_card", "expiration_date"), + post=self.__error_message(self.errors.for_object("customer").for_object("credit_card").on("expiration_date")), + class_=self.__error_class(self.errors.for_object("customer").for_object("credit_card").on("expiration_date")) + ), + web.form.Textbox( + description="CVV", + name="customer[credit_card][cvv]", + id="customer_credit_card_cvv", + value=self.__get_nested_param("customer", "credit_card", "cvv"), + post=self.__error_message(self.errors.for_object("customer").for_object("credit_card").on("cvv")), + class_=self.__error_class(self.errors.for_object("customer").for_object("credit_card").on("cvv")) + ), + web.form.Textbox( + description="Cardholder name", + name="customer[credit_card][cardholder_name]", + id="customer_credit_card_cardholder_name", + value=self.__get_nested_param("customer", "credit_card", "cardholder_name"), + post=self.__error_message(self.errors.for_object("customer").for_object("credit_card").on("cardholder_name")), + class_=self.__error_class(self.errors.for_object("customer").for_object("credit_card").on("cardholder_name")) + ), + web.form.Textbox( + description="Street", + name="customer[credit_card][billing_address][street_address]", + id="customer_credit_card_billing_address_street_address", + value=self.__get_nested_param("customer", "credit_card", "billing_address", "street_address"), + post=self.__error_message(self.errors.for_object("customer").for_object("credit_card").for_object("billing_address").on("street_address")), + class_=self.__error_class(self.errors.for_object("customer").for_object("credit_card").for_object("billing_address").on("street_address")) + ), + web.form.Textbox( + description="Country code", + name="customer[credit_card][billing_address][country_code_alpha2]", + id="customer_credit_card_billing_address_country_code_alpha2", + value=self.__get_nested_param("customer", "credit_card", "billing_address", "country_code_alpha2"), + post=self.__error_message(self.errors.for_object("customer").for_object("credit_card").for_object("billing_address").on("country_code_alpha2")), + class_=self.__error_class(self.errors.for_object("customer").for_object("credit_card").for_object("billing_address").on("country_code_alpha2")) + ), + web.form.Textbox( + description="Postal Code", + name="customer[credit_card][billing_address][postal_code]", + id="customer_credit_card_billing_address_postal_code", + value=self.__get_nested_param("customer", "credit_card", "billing_address", "postal_code"), + post=self.__error_message(self.errors.for_object("customer").for_object("credit_card").for_object("billing_address").on("postal_code")), + class_=self.__error_class(self.errors.for_object("customer").for_object("credit_card").for_object("billing_address").on("postal_code")) + ), + web.form.Hidden( + "tr_data", + value=braintree.Customer.tr_data_for_create({}, "http://localhost:8080/subscriptions/confirm/") + ) + ) + + def __error_class(self, errors): + if len(errors) == 0: + return "" + else: + return "error" + + def __error_message(self, errors): + if len(errors) == 0: + return "" + else: + message = "
Thank you for your subscription.
+ ++# Customer + +customer.first_name $customer.first_name +customer.last_name $customer.last_name +customer.email $customer.email + +# Addresses + +first_name, +last_name, +country_code_alpha2, +country_code_alpha3, +extended_address, +locality, +country_code_numeric, +postal_code, +gateway, +country_name, +region, +customer_id, +company, +street_address + +# Subscription + +subscription.balance $subscription.balance +subscription.merchant_account_id $subscription.merchant_account_id +subscription.payment_method_token $subscription.payment_method_token +subscription.plan_id $subscription.plan_id +subscription.price $subscription.price +subscription.status $subscription.status +subscription.trial_duration $subscription.trial_duration +subscription.trial_duration_unit $subscription.trial_duration_unit +subscription.trial_period $subscription.trial_period +\ No newline at end of file diff --git a/tr_subscription/templates/layout.html b/tr_subscription/templates/layout.html new file mode 100644 index 0000000..5b7cea9 --- /dev/null +++ b/tr_subscription/templates/layout.html @@ -0,0 +1,11 @@ +$def with (page) + + + +