Braintree is one of the most popular ways to accept payments online, in this article we take a deep look how it works in Laravel framework.

In this tutorial we will create a few Braintree demos, so please create your testing account at Braintree, and let’s dive right in.

Preparation and Braintree Install

First, let’s create a new Laravel application

laravel new braintree-demo

Next – usual Laravel installation steps:

composer install
cp .env.example .env
php artisan key:generate
php artisan migrate

And then we install a special Braintree package for PHP:

composer require braintree/braintree_php

Now we need to set up our Braintree API information in .env file

BRAINTREE_ENV=sandbox
BRAINTREE_MERCHANT_ID=
BRAINTREE_PUBLIC_KEY=
BRAINTREE_PRIVATE_KEY=

Go to Braintree sandbox page and register an account. After account confirmation and login, just go to Settings -> API keys and there you’ll find all the needed information.

Now, fill in the data

BRAINTREE_ENV=sandbox
BRAINTREE_MERCHANT_ID=pxsff7htd4xwwcgs
BRAINTREE_PUBLIC_KEY=3m7dsyydgdz9nxcd
BRAINTREE_PRIVATE_KEY=cc2632a6b244d16eabbbcb4d08105bab

To setup Braintree in Laravel, go to App/Providers/AppServiceProvider.php and add the following code to your boot() method

Braintree_Configuration::environment(env('BRAINTREE_ENV'));
Braintree_Configuration::merchantId(env('BRAINTREE_MERCHANT_ID'));
Braintree_Configuration::publicKey(env('BRAINTREE_PUBLIC_KEY'));
Braintree_Configuration::privateKey(env('BRAINTREE_PRIVATE_KEY'));

Payment Routes and Forms

In our routes/web.php we need to add a new route for processing the payment

Route::get('/payment/process', 'PaymentsController@process')->name('payment.process');

Now we can add our application view in resources/views/welcome.blade.php

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Braintree-Demo</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

  <script src="https://js.braintreegateway.com/web/dropin/1.8.1/js/dropin.min.js"></script>

  <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
  <div class="container">
     <div class="row">
       <div class="col-md-8 col-md-offset-2">
         <div id="dropin-container"></div>
         <button id="submit-button">Request payment method</button>
       </div>
     </div>
  </div>
  <script>
    var button = document.querySelector('#submit-button');

    braintree.dropin.create({
      authorization: "{{ Braintree_ClientToken::generate() }}",
      container: '#dropin-container'
    }, function (createErr, instance) {
      button.addEventListener('click', function () {
        instance.requestPaymentMethod(function (err, payload) {
          $.get('{{ route('payment.process') }}', {payload}, function (response) {
            if (response.success) {
              alert('Payment successfull!');
            } else {
              alert('Payment failed');
            }
          }, 'json');
        });
      });
    });
  </script>
</body>
</html>

If the setup was successful, you should see Braintree “drop-in” appear – there you can enter your credit card information:


Processing Payment

To process the payment, we need to create a new payment controller

php artisan make:controller PaymentsController

And then we create process() method inside the controller

use Braintree_Transaction;

public function process(Request $request)
{
    $payload = $request->input('payload', false);
    $nonce = $payload['nonce'];

    $status = Braintree_Transaction::sale([
	'amount' => '10.00',
	'paymentMethodNonce' => $nonce,
	'options' => [
	    'submitForSettlement' => True
	]
    ]);

    return response()->json($status);
}

And that’s it – our simple payment system is created!

To try it out, just go to your application and enter some fake credit card data:

  • Braintree sandbox credit card number is 4111 1111 1111 1111
  • Expiration date can be whatever you want

Then click on “Request payment method” button:

Our front-end part of the application will send a request to Braintree and ask for a payment method and a “nonce” that we will use to execute the payment in our controller.

After we get a response from Braintree, we send a request to our application’s backend with information provided by Braintree, and try to make a payment. PaymentsController will return the status of the payment, and if it’s successful – we should see an alert, informing us about that.


Subscription payments – Cashier

Another way to pay for services is subscriptions. And here with Braintree we can use official Laravel Cashier package.

First, let’s install the package:

composer require laravel/cashier-braintree

To track our subscriptions, we’ll need to update our database and add some fields:

php artisan make:migration add_braintree_fields

Fill the up method with the following code:

Schema::table('users', function ($table) {
    $table->string('braintree_id')->nullable();
    $table->string('paypal_email')->nullable();
    $table->string('card_brand')->nullable();
    $table->string('card_last_four')->nullable();
    $table->timestamp('trial_ends_at')->nullable();
});

Schema::create('subscriptions', function ($table) {
    $table->increments('id');
    $table->integer('user_id');
    $table->string('name');
    $table->string('braintree_id');
    $table->string('braintree_plan');
    $table->integer('quantity');
    $table->timestamp('trial_ends_at')->nullable();
    $table->timestamp('ends_at')->nullable();
    $table->timestamps();
});

Also, to test our app, we’ll need a user, so let’s create one in database/seeds/DatabaseSeeder.php

User::create([
    'name' => 'First user',
    'email' => 'user@user.com',
    'password' => bcrypt('password')
]);

At this point, we can run the migrations

php artisan migrate --seed

Now, add Billable trait to our User model:

use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;
}

Next: add service configuration code in config/services.php:

'braintree' => [
    'model'  => App\User::class,
    'environment' => env('BRAINTREE_ENV'),
    'merchant_id' => env('BRAINTREE_MERCHANT_ID'),
    'public_key' => env('BRAINTREE_PUBLIC_KEY'),
    'private_key' => env('BRAINTREE_PRIVATE_KEY'),
],

Notice: we added these env variables in .env file in the first part of the tutorial.

Now, routing: add a subscription route in routes/web.php:

Route::get('/payment/subscribe', 'PaymentsController@subscribe')->name('payment.subscribe');

And a subscribe() method in PaymentsController – the same that we created earlier:

public function subscribe(Request $request)
{
    try {
        $payload = $request->input('payload', false);
        $nonce = $payload['nonce'];

        $user = User::first();
        $user->newSubscription('main', 'bronze')->create($nonce);

        return response()->json(['success' => true]);
    } catch (\Exception $ex) {
        return response()->json(['success' => false]);
    }
}

The view can stay the same, we just need to change the route from

{{ route('payment.process') }}

To

{{ route('payment.subscribe') }}

One last thing. In our PaymentsController we are subscribing to our ‘bronze’ subscription, but we haven’t created one in Braintree, so before we can make a payment – we need to go to our sandbox and find Plans at the end of the menu.

Go to plans and click New, create your plan there. Important thing: Plan ID has to be the same as $user->newSubscription(‘main’, ‘bronze’) second parameter.

Now that our backend is set up, we can add front-end subscription form.
It’s basically the same code as in single payment form, only difference being the route we are submitting to.

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Braintree-Demo</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

  <script src="https://js.braintreegateway.com/web/dropin/1.8.1/js/dropin.min.js"></script>

  <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
  <div class="container">
     <div class="row">
       <div class="col-md-8 col-md-offset-2">
         <div id="dropin-container"></div>
         <button id="submit-button">Request payment method</button>
       </div>
     </div>
  </div>
  <script>
    var button = document.querySelector('#submit-button');

    braintree.dropin.create({
      authorization: "{{ Braintree_ClientToken::generate() }}",
      container: '#dropin-container'
    }, function (createErr, instance) {
      button.addEventListener('click', function () {
        instance.requestPaymentMethod(function (err, payload) {
          $.get('{{ route('payment.subscribe') }}', {payload}, function (response) {
            if (response.success) {
              alert('Payment successfull!');
            } else {
              alert('Payment failed');
            }
          }, 'json');
        });
      });
    });
  </script>
</body>
</html>

Enter dummy credit card data, click Subscribe, and that’s it – Braintree will now bill the user based on your subscription settings that you entered while setting up subscription plan in Braintree.

You can visit you Braintree Sandbox and you should find our subscription there.


So, that’s it! That was an overview of how you can use Braintree inside of Laravel. Was it helpful?

Read more: