Laravel Stripe Integration

What is stripe?

If you are running an internet business and you have to deal with customer payments stripe is the best tool. It is a platform that provides payment services.

Stripe is free however they take little fees on every transaction. Signup for stripe using following link and get API Keys we needed for our laravel application.

Signup for Stripe

How does stripe work?

Before we start jumping in code we have to understand how it works in general. Following is a sample flow of our application:

  • Your application has checkout page
  • Your client buys some stuff and goes to checkout page
  • On checkout page you show an option to pay with stripe
  • When use fills the stripe credit card info we create a customer account on stripe using api
  • We store this stripe client in our database with id
  • We also store credit card nounce so that we can charge the client later for any other purchases

Create a new laravel project

First of all, to integrate stripe with our laravel app we need to create a new laravel project. If you dont know how to create a new laravel project use following link to learn how to create one:

Setup New Laravel Project

Once you have a new project setup we have to use stripe php api to talk with stripe.

Let's open terminal window and run following commands while we are in laravel root project:

# go to your project root directory
cd /var/www/my_project

# add composer dependency
composer require stripe/stripe-php​

Now, we have to add api keys that we have got from stripe and add them to our .env file as show below:

STRIPE_API_KEY=
STRIPE_PRIVATE_KEY=​

Setup private key in service provider

Service providers are great place in laravel to load site wise settings. For our stripe application we will load our private key in AppServiceProvider.php file.

Open app/providers/AppServiceProvider.php file and add following line:

namespace App\Providers;

use Stripe\Stripe;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Stripe::setApiKey(env('STRIPE_PRIVATE_KEY'));
    }
}

Creating checkout page

To see how our stripe integration will work we have to create a sample checkout page with stripe form.

To create a new page in laravel we need to first define a new route that we will use for our new page.

Create routes

Let's open routes/web.php file and add following to get and post routes for our checkout page:

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

Create a controller class

Now, let's create a new controller for our checkout page. Open the terminal window and run following command:

php artisan make:controller PaymentController​

Open the created controller file and add following method:

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

class PaymentController extends Controller
{
     public function checkout(Request $request) 
     {
           return view('checkout');
     }
}

Create view file

Finally, we will add a view file called checkout.blade.php in resources/views with following contents:

<html>
<head>
    <title>Braintree Payment Demo</title>
    <style>
        StripeElement {
           background-color: white;
           padding: 8px 12px;
           border-radius: 4px;
           border: 1px solid transparent;
           box-shadow: 0 1px 3px 0 #e6ebf1;
          -webkit-transition: box-shadow 150ms ease;
          transition: box-shadow 150ms ease;
       }

       .StripeElement--focus {
           box-shadow: 0 1px 3px 0 #cfd7df;
       }

       .StripeElement--invalid {
           border-color: #fa755a;
       }

       .StripeElement--webkit-autofill {
           background-color: #fefde5 !important;
       }
    </style>
    <script src="https://js.stripe.com/v3/"></script>
</head>
<body>
    <form action="/checkout" method="post" id="payment-form">
        <div class="form-row">
            <label for="card-element">Credit or debit card</label>
           <div id="card-element"></div>
           <div id="card-errors" role="alert"></div>
        </div>
        <button>Submit Payment</button>
     </form>

     <script>

         // Create a Stripe client
         var stripe = Stripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh');

         // Create an instance of Elements
         var elements = stripe.elements();

         // Custom styling can be passed to options when creating an Element.
         // (Note that this demo uses a wider set of styles than the guide below.)
         var style = {
             base: {
                 color: '#32325d',
                 lineHeight: '24px',
                 fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                 fontSmoothing: 'antialiased',
                 fontSize: '16px',
                 '::placeholder': {
                    color: '#aab7c4'
                 }
            },
            invalid: {
               color: '#fa755a',
               iconColor: '#fa755a'
            }
     };

     // Create an instance of the card Element
     var card = elements.create('card', {style: style});

     // Add an instance of the card Element into the `card-element` <div>
     card.mount('#card-element');

     // Handle real-time validation errors from the card Element.
     card.addEventListener('change', function(event) {
         var displayError = document.getElementById('card-errors');
         if (event.error) {
             displayError.textContent = event.error.message;
         } else {
           displayError.textContent = '';
         }
     });

     // Handle form submission
     var form = document.getElementById('payment-form');
     form.addEventListener('submit', function(event) {
           event.preventDefault();
           stripe.createToken(card).then(function(result) {
           if (result.error) {
               // Inform the user if there was an error
               var errorElement = document.getElementById('card-errors');
               errorElement.textContent = result.error.message;
           } else {
              // Send the token to your server
              stripeTokenHandler(result.token);
           }
        });
    });
    </script>
</body>
</html>

At this stage, we have a new checkout page. Let's have a look at the page and see how it looks.

Run following command to run default php server:

php artisan serve​

Go to your browser and hit http://localhost:8000/checkout and you will be able to see stripe form.

How to create stripe customer using API?

Now, we have not added any logic that handle our post request for checkout page. When your client hit Submit Payment button it will send a post request to our checkout page.

We will add some logic here that will create a stripe customer using stripe api and if user added a new card info we will add a new card using stripe api and save this info on our side.

We have to have following columns in our customer table:

  • stripe_id
  • stripe_token

Let's modify our controller logic and add following logic:

namespace App\Http\Controllers;
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') ) 
           {
                // stripe customer payment token
                $stripe_token = $request->get('stripe_token');

                // make sure that if we do not have customer token already
                // then we create nonce and save it to our database
                if ( !$customer->stripe_token ) 
                {
                      // once we received 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 = \Stripe\Customer::create(array(
                          "email"  => $customer->email,
                          "source" => $stripe_token
                      ));

                      if( $result && $result->id )
                      {
                          $client->stripe_id = $result->id;
                          $client->stripe_token = $stripe_token;
                          $client->save();
                      }
                }

                if( $customer->stripe_token) 
                {
                    // charge customer with your amount
                    $result = \Stripe\Charge::create(array(
                         "currency" => "cad",
                         "customer" => $customer->stripe_id,
                         "amount"   => 200 // amount in cents                                                 
                    ));

                    // store transaction info for logs
                }             
           }

           return view('checkout');
     }
}

If you follow my comments in above logic you will see that we create a new client on stripe and if we have a stripe token already we charge our client with token or if user provides new credit card info we overwrite existing info.

This is how you can easily integrate stripe with laravel application.