Braintree Payments Tutorial: Managing Subscriptions with the Server-to-Server (S2S) API

Note: this post was previewed and approved by the customer.

Braintree Logo White Background
Braintree Payments Logo

Recently we integrated Braintree Payments as part of a sales lead routing site project . Here is a small tutorial based on the example we wrote to learn how their API works. Their documentation is great and easy to follow, but we found that it sometimes lacked detail so I had to find some things looking at their (excellent) PHP library source code.

The code is just a quick demo, so it’s far from perfect. However it will be fine for the purposes of this tutorial.

If you need help integrating Braintree in your site, feel free to contact us.

1. Set up a plan in the sandbox.

After signing up with Braintree, you will get an email with your sandbox credentials. For this tutorial, we will create one plan with one add-on.

Go to Recurring Billing → Add-ons and Discounts → New Add-on and create a new one. You should end with something like:

Braintree Create Add-on
Braintree add-on created. Click to enlarge.

Next, go to Recurring Billing → Plans → New and do the same but selecting the add-on you just created in the step above in the “add-ons” section. You should get something like:

Braintree Create a Plan
Braintree plan created. Click to enlarge.

Now we can start to code.

2. The configuration file.

You will find the api keys in their sandbox. Just go to Account → My User → Authorization → Api Keys.

Now, download or clone from Github their PHP Client Library (I used version 2.12.3 for this tutorial) and install it in your server (I used the braintree-lib directory).

In the root of your site (or in your test dir) create a braintree.config.php file with the following:

require_once('braintree-lib/Braintree.php');

Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('yourmerchantId');
Braintree_Configuration::publicKey('yourpublicKey');
Braintree_Configuration::privateKey('yourprivateKey');

3. Create a customer record with a credit card.

You can do this in separate steps, but in this example we will do at once. Check that I have split the code in several parts, so you will have to join them.

require_once 'braintree.config.php';

$planId = 2000;
$addOnId = 1000;
$includeAddOn = false;

try {
    /* First we create a new user using the BT API */
    $result = Braintree_Customer::create(array(
                'firstName' => 'My First Name',
                'lastName' => 'My Last Name',
                'company' => 'My Company',
                // we can create a credit card at the same time
                'creditCard' => array(
                    'cardholderName' => 'My Name On Card',
                    'number' => '5105105105105100',
                    'expirationMonth' => "02",
                    'expirationYear' => "15",
                    'cvv' => '123',
                    'billingAddress' => array(
                        'firstName' => 'My Billing Address First Name',
                        'lastName' => 'My Billing Address Last Name',
                        'company' => 'My Billing Address Company',
                        'streetAddress' => 'My Billing Address Address',
                        'locality' => 'My Billing Address City',
                        'region' => 'IL', // Two letter code
                        'postalCode' => '60622',
                        'countryCodeAlpha2' => 'US'
                    )
                )
            ));
    if ($result->success) {
        echo("Customer ID: " . $result->customer->id . "
");
        echo("Credit card ID: " . $result->customer->creditCards[0]->token . "
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }

4. Create a subscription.

By default the subscription includes all associated add-ons, but you can remove them using an option.

    // Now we create a subscription
    $subscriptionData = array(
        'paymentMethodToken' => $result->customer->creditCards[0]->token,
        'planId' => $planId
    );

    // The addons are included by default, but we can remove them
    if (!$includeAddOn) {
        $subscriptionData['addOns'] = array(
            'remove' => array($addOnId)
        );
    }

    $result = Braintree_Subscription::create($subscriptionData);

    if ($result->success) {
        echo("Subscription ID: " . $result->subscription->id . "
");
        echo("Transaction ID: " . $result->subscription->transactions[0]->id . "
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }

5. Modify the subscription.

We add or remove the add-on depending on whether it had been added in the previous step.

When adding it, we can decide if we prorate the addon value. If not it will be charged next month.

    // we add or remove the addon depending on its state
    if (!$includeAddOn) {
        // add
        $result = Braintree_Subscription::update($result->subscription->id, array(
                    'options' => array(
                        'prorateCharges' => true,
                        'revertSubscriptionOnProrationFailure' => true
                    ),
                    'addOns' => array(
                        'add' => array(
                            array(
                                'inheritedFromId' => $addOnId
                            )
                        )
                    )
                ));
    } else {
        // remove
        $result = Braintree_Subscription::update($result->subscription->id, array(
                    'addOns' => array(
                        'remove' => array($addOnId)
                    )
                ));
    }

    if ($result->success) {
        echo("Subscription ID: " . $result->subscription->id . " updated
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }

6. Cancel the subscription.

This is pretty straightforward. In the last catch the getMessage() method of the thrown exception returns an empty string (a client library bug maybe?).

    // Finnally we cancel the subscription
    $result = Braintree_Subscription::cancel($result->subscription->id);

    if ($result->success) {
        echo("Subscription ID: " . $result->subscription->id . " cancelled
");
    } else {
        foreach ($result->errors->deepAll() as $error) {
            echo($error->code . ": " . $error->message . "
");
        }
        exit;
    }
} catch (Exception $e) {
    echo 'Caught exception: ' . $e . "
"; // $e->getMessage() is empty
}

7 .Check the result in the sandbox.

Go to Search → Subscriptions, click on “Search”, and then select the subscription id to be found in the output of the PHP program. If everything went right, you should find something like this:

Braintree Subscription Page
Braintree subscription page after running the program. Click to enlarge.

 

Advertisements

9 thoughts on “Braintree Payments Tutorial: Managing Subscriptions with the Server-to-Server (S2S) API

    1. No, once you set up the subscriptions, Braintree will charge the user periodically (you can specify a billing period other than a month) until you cancel the subscription, or you reach the ending date or the number of billing cycles you can set in the subscription create request. There is no need to send any signal if everything is properly set up.

      Like

  1. How do you integrate the customer subscription information into your website? Is there a confirmation notice from braintree that will send to a php page that we can capture some of the customer data like transaction ID and amount and start date etc so we can integrate and store in a database? Will future recurring subscription transactions send a call out to a script so we can verify that the subscription is active? Is there the posibility of letting the customer cancel their subscription directly from my website?Thanks for the great tutorial.

    Like

  2. Hi, I’m doing the exact same thing. Thanks. Was stuck getting the payment method token and no help with the documentation: $result->customer->creditCards[0]->token.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s