Stripe Payment Gateway Integration in Laravel

If you are running an online store or some kind of paid service then probably you need to accept credit card payments on your application. Stripe is one of the popular payment gateways which accept credit or debit card payments online. Additionally, the user doesn’t need to leave your website to make the card payment. In this article, we study Stripe payment gateway integration in Laravel.

For integrating Stripe gateway in Laravel we are going to use the Omnipay library which is popular among the developers. So without any further delay let’s start with our integration.

Get API Keys for Stripe Integration

At first, you need to create a Stripe account if you don’t have one already. For integrating Stripe gateway you first need to grab your secret and publishable key. You will get these keys from the Developers->API Keys page.

Stripe API Keys

It is always recommended to test the online transactions first with sandbox keys and if everything works well then go for live keys.

Basic Setup in Laravel for Stripe Integration

Before starting accepting online payments using Stripe, you need to perform a basic setup. We will require stripe keys during API integration so add these keys in .env file.

STRIPE_PUBLISHABLE_KEY=PASTE_PUBLISHABLE_KEY
STRIPE_SECRET_KEY=PASTE_SECRET_KEY
STRIPE_CURRENCY=USD

Whenever we add new constants in the environment file, we should run the below command to clear the configuration cache.

php artisan config:cache

When it comes to online payments, one should store the transaction details in the database. For this, create a migration using the command:

php artisan make:migration create_payments_table

In the migration file edit the up method as follow:

public function up()
{
    Schema::create('payments', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('payment_id');
        $table->string('payer_email');
        $table->float('amount', 10, 2);
        $table->string('currency');
        $table->string('payment_status');
        $table->timestamps();
    });
}

Next, run the below command to execute migration.

php artisan migrate

We will require an HTML form where a user can enter their card details and other information. Create a payment.blade.php file and add the code below in it.

<link rel="stylesheet" href="{{ asset('/css/style.css') }}" />
<script src="https://js.stripe.com/v3/"></script>
<form action="{{ url('charge') }}" method="post" id="payment-form">
    <div class="form-row">
        <p><input type="text" name="amount" placeholder="Enter Amount" /></p>
        <p><input type="email" name="email" placeholder="Enter Email" /></p>
        <label for="card-element">
        Credit or debit card
        </label>
        <div id="card-element">
        <!-- A Stripe Element will be inserted here. -->
        </div>
     
        <!-- Used to display form errors. -->
        <div id="card-errors" role="alert"></div>
    </div>
    <button>Submit Payment</button>
    {{ csrf_field() }}
</form>
<script>
var publishable_key = '{{ env('STRIPE_PUBLISHABLE_KEY') }}';
</script>
<script src="{{ asset('/js/card.js') }}"></script>

In the blade file, we included CSS and JS files directly. You can include it in another way as per your project flow. Finally, define the routes as follows.

routes/web.php

Route::get('/payment', 'PaymentController@index');
Route::post('/charge', 'PaymentController@charge');

We will create the controller PaymentController in the next steps.

Generate Stripe Card Elements

Stripe provides its own prebuilt UI components that collect customer card data securely without handling sensitive data. The card details are converted to ‘Token’ which then needs to be sent to your servers. Using this ‘Token’ you can charge the customers. This is a way secure as your application doesn’t need to store or interact with customer card details.

You may have noticed in the blade file we included card.js file. Create this JS file under the public directory and add the below code to it.

js/card.js

// Create a Stripe client.
var stripe = Stripe(publishable_key);
 
// 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',
        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);
        }
    });
});
 
// Submit the form with the token ID.
function stripeTokenHandler(token) {
    // Insert the token ID into the form so it gets submitted to the server
    var form = document.getElementById('payment-form');
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'stripeToken');
    hiddenInput.setAttribute('value', token.id);
    form.appendChild(hiddenInput);
 
    // Submit the form
    form.submit();
}

The blade file has also included style.css file. Create style.css inside the public folder. This CSS will have the below code.

css/style.css

.StripeElement {
    box-sizing: border-box;
    
    height: 40px;
    
    padding: 10px 12px;
    
    border: 1px solid transparent;
    border-radius: 4px;
    background-color: white;
    
    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;
}

Stripe is providing different kinds of UI elements for building a checkout form with credit card details. Read more about it on their documentation.

Stripe Payment Gateway Integration in Laravel

We all set with the required configuration. Now we can go ahead and integrate the Stripe payment gateway in Laravel. Run the command below to install the Omnipay library in your project.

composer require league/omnipay omnipay/stripe

To call the blade file and charge the transaction create a PaymentController using the artisan command:

php artisan make:controller PaymentController

As we should store transaction details in the database, create a model Payment which is associated with the payments table in the database.

php artisan make:model Payment

Finally, PaymentController.php will have the following code which charges the transaction and insert the transaction details in your database.

PaymentController.php

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use Omnipay\Omnipay;
use App\Models\Payment;
 
class PaymentController extends Controller
{
    public function index()
    {
        return view('payment');
    }
 
    public function charge(Request $request)
    {
        if ($request->input('stripeToken')) {
 
            $gateway = Omnipay::create('Stripe');
            $gateway->setApiKey(env('STRIPE_SECRET_KEY'));
          
            $token = $request->input('stripeToken');
          
            $response = $gateway->purchase([
                'amount' => $request->input('amount'),
                'currency' => env('STRIPE_CURRENCY'),
                'token' => $token,
            ])->send();
          
            if ($response->isSuccessful()) {
                // payment was successful: insert transaction data into the database
                $arr_payment_data = $response->getData();
                 
                $isPaymentExist = Payment::where('payment_id', $arr_payment_data['id'])->first();
          
                if(!$isPaymentExist)
                {
                    $payment = new Payment;
                    $payment->payment_id = $arr_payment_data['id'];
                    $payment->payer_email = $request->input('email');
                    $payment->amount = $arr_payment_data['amount']/100;
                    $payment->currency = env('STRIPE_CURRENCY');
                    $payment->payment_status = $arr_payment_data['status'];
                    $payment->save();
                }
 
                return "Payment is successful. Your payment id is: ". $arr_payment_data['id'];
            } else {
                // payment failed: display message to customer
                return $response->getMessage();
            }
        }
    }
}

For the sandbox mode, Stripe provides dummy credit cards to test a transaction.

Once you are done with testing of sandbox mode, replace your test API keys with the live one and your application will start accepting real payments automatically.

That’s it! You are all done with the Stripe payment gateway integration in Laravel. I would like to hear your thoughts and suggestions in the comment section below.

Related Articles

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

11 thoughts on “Stripe Payment Gateway Integration in Laravel

  1. Hi,

    I followed your tutorial but I got this error:

    Please call Stripe() with your publishable key. You used an empty string

    Can you please help

      1. Yes, and it was about the publish key that (I don’t know why) was unable to read from the .env file.
        I’ve copied/pasted and now it’s everything running.
        Thank you for the tutorial (stay coding!) and I hope that this post would help someone else 😀

          1. While deploying the Laravel project on the production server, you must set doc root to the public folder. It restricted accessing the `.env` file outside the world.

  2. hello ,
    My name is animesh mana from kolkata,India.i am a php developer. in API related coding i always take help from here.i like this website.

Leave a Reply

Your email address will not be published. Required fields are marked *