Search code examples
pythondjangodjango-viewsbraintreebraintree-sandbox

Is this the right way to create a subscription for Braintree in Python using the API


In an effort to bring some clarity, I'm asking this question here and sharing what I've learned so far.

First, if you want a simple, easy to develop transaction system, Braintree is it. Really easy, and plays very nicely with Django.

However, the subscription side of things has not been so clear. So, I'm sharing some code to get feedback on and help streamline.

First.. some assumptions.

Work Flow

The process for creating a subscription with the API is as follows:

(please don't send me documentation on how to do it in the control panel. A very broad description of the Subscription workflow can be found here: https://developers.braintreepayments.com/guides/recurring-billing/create/python)

  1. Create a Client token with braintree.ClientToken.generate()
  2. Create a customer with braintree.Customer.create() that adds a payment method
  3. Get the customer id from the Customer.create() response
  4. Create a subscription with braintree.Subscription.create() passing in the new customer and the new customer's token called payment_method_token

If you're wondering, this is Django and I'm trying to do this all in one view.

Sample Code

custy_result = braintree.Customer.create({
    "first_name": self.request.POST.get('first_name'),
    "last_name": self.request.POST.get('last_name'),
    "company": self.request.POST.get('company_name'),
    "email": self.request.POST.get('office_email'),
    "phone": self.request.POST.get('office_phone'),
    'payment_method_nonce': 'fake-valid-nonce', # for testing
    "credit_card": {
        "billing_address": {
            "street_address": self.request.POST.get('address'),
            "locality": self.request.POST.get('city'),
            "region": self.request.POST.get('state'),
            "postal_code": self.request.POST.get('postal'),
        }
    }
})

if custy_result.is_success:
    print("Customer Success!")
else:
    for error in custy_result.errors.deep_errors:
        print(error.code)
        print(error.message)

# Create the subscription in braintree
sub_result = braintree.Subscription.create({
    "payment_method_token": "the_token", # <-- How do I get this token?
    "plan_id": "the_plan_id_in_braintree"
})

if sub_result.is_success:
    print("Subscription Success!")
else:
    for error in sub_result.errors.deep_errors:
        print(error.code)
        print(error.message)

The Question(s)?

How do I get that token? What is "the_token"? Where does it come from?

I can't see how it's created and I can't see where it's pulled from. I want to do something like custy_result.customer.token but that is clearly wrong.

For reference, here is what I've been looking at in the documentation:

Customers

Payment Methods

Recurring Payments

Testing

Create Subscription

Customer.response

Credit Card Response


Solution

  • Your custy_result should have payment_methods attribute:

    result = braintree.Subscription.create({
        "payment_method_token": custy_result.payment_methods[0].token,
        "plan_id": "planID"
    })