What is braintree?

Braintree is a payment gateway service that helps you store your client credit card information and process your client credit card charges for service you provide.

If you are building an e-commerce website where you need to charge your customer based on their subscriptions you can save their credit card details and then you can charge them on monthly or annually or one time depending on your requirements.

If you are an advance laravel developer and want to learn how to integrate braintree in your laravel application I will walk you through step by step tutorial.

Let's understand the flow for our laravel braintree app:

  • add two columns to users table to save braintree customer id and credit card nounce
  • when user purchase something and goes to checkout page
  • on checkout page he enters credit card info
  • when he clicks on checkout button we will save his credit card info
  • next time when user purchase something we will use their existing credit card or
  • they can enter new credit card by replacing existing one
  • we process their payment using braintree

Import braintree php library using composer

Braintree provides php library that you can integrate in your laravel project. To install their library open the terminal window and using composer command install following library:

composer require braintree/braintree_php​

Next, create your brain tree account and get credentials that we need for our laravel project. If you don't know how to get these credentials follow the link below:

Braintree Private/Public Key

we have to add some .env configuration to our project. Open .env file and add following constants:

BTREE_ENVIRONMENT=
BTREE_MERCHANT_ID=
BTREE_PUBLIC_KEY=
BTREE_PRIVATE_KEY=

How to load braintree configuration?

After you have setup your constants in .env file you have to find a best place in laravel to load these configuration when laravel application runs.

It is a good practise to place these configuration in boot method of AppServiceProvider. Open your AppServiceProvider file located in app/Providers/AppServiceProviders.php  and add following lines:

namespace App\Providers;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        \Braintree_Configuration::environment(env('BTREE_ENVIRONMENT'));
        \Braintree_Configuration::merchantId(env('BTREE_MERCHANT_ID'));
        \Braintree_Configuration::publicKey(env('BTREE_PUBLIC_KEY'));
        \Braintree_Configuration::privateKey(env('BTREE_PRIVATE_KEY'));
    }
}

Now, whenever laravel application runs it will run above boot method before it gets to the controller. By the time it reaches to controller method we will have braintree setup.

How to save braintree customer_id ?

For your application let say that you have a users table where all of your website customers are located. You have to create a new column called customer_id in your user table.

In application when your customer signs up in that controller you have to add following logic to create a customer on braintree side and get their customer_id and save it on your users table.

Add following code where you create your customer account:

// get current logged in customer
$customer = Auth::user();

// using your customer id we will create
// brain tree customer id with same id
$response = \Braintree_Customer::create([
   'id' => $customer->id
]);

// save your braintree customer id
if( $response->success) {
    $customer->braintree_customer_id = $response->customer->id;
    $customer->save();
}

Saving braintree customer_id in our users table will allow us to charge our customer later when we need using these customer_id.

Braintree payment demo with laravel

Let's create a demo application which allow us to charge our customer for service they use. Let's create a new route for our checkout page in routes/web.php file:

Route::get('/', 'PaymentController@checkout');
Route::post('/', 'PaymentController@checkout');

Let's now create PaymentController with checkout method that will be called when customer gets to checkout page. Our checkout method accepts both GET and POST requests.

When a customer lands on checkout page it will be a GET request. On checkout page they will fill out their credit card info and hit purchase button.

We will save their credit card info so that next time when they come on checkout page they can process without adding their credit card again however they will have an option to replace their existing card.

Let's add our checkout page logic to our PaymentController:

namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;

class PaymentController extends Controller
{
     public function checkout(Request $request) 
     {
           // get your logged in customer
           $customer = Auth::user();

           // when client hit checkout button
           if( $request->isMethod('post') ) 
           {
                // brain tree customer payment nouce
                $payment_method_nonce = $request->get('payment_method_nonce');

                // make sure that if we do not have customer nonce already
                // then we create nonce and save it to our database
                if ( !$customer->braintree_nonce ) 
                {
                      // once we recieved customer payment nonce
                      // we have to save this nonce to our customer table
                      // so that next time user does not need to enter his credit card details
                      $result = \Braintree_PaymentMethod::create([
                        'customerId' => $customer->braintree_customer_id,
                        'paymentMethodNonce' => $payment_method_nonce
                      ]);

                      // save this nonce to customer table
                      $customer->braintree_nonce = $result->paymentMethod->token;
                      $customer->save();
                }
                
                // process the customer payment
                $client_nonce = \Braintree_PaymentMethodNonce::create($customer->braintree_nonce);
                $result = \Braintree_Transaction::sale([
                     'amount' => 100,
                     'options' => [ 'submitForSettlement' => True ],
                     'paymentMethodNonce' => $client_nonce->paymentMethodNonce->nonce
                ]);

                // check to see if braintree has processed
                // our client purchase transaction
                if( !empty($result->transaction) ) {
                    // your customer payment is done successfully  
                }
           }

           return view('checkout', [
              'braintree_customer_id' => $customer->braintree_customer_id
           ]);
     }
}

Let's create a view file for our application demo. Create a file called checkout.blade.php in resources/views with following html contents:

<html>
<head>
    <title>Braintree Payment Demo</title>
    <script src="https://static.opentok.com/v2/js/opentok.js"></script>
</head>
<body>
    <form>
       <div id="payment-form"></div>
       <button type="submit">Submit Order</button>
    </form>

    <script src="https://js.braintreegateway.com/js/braintree-2.32.1.min.js"></script>
    <script type="text/javascript">
        $(function () {
            braintree.setup('{{ $braintree_customer_id }}', 'dropin', {
                container: 'payment-form'
            });
        });
    </script>
</body>
</html>

That is it. We have successfully integrated braintree in our laravel project.