Laravel 8 Stripe Integration

Setup New Laravel 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.