Stripe Payment Gateway Integration In Laravel 5.x

By | February 16, 2019

Hello Coders !! This article is about Stripe payment gateway integration in laravel website. So let’s start integrating it.

Stripe Payment Gateway Integration Laravel
Stripe Payment Gateway Integration Laravel

About Stripe: Stripe is a technology company. Its software allows people and businesses to receive payments over the web. Stripe provides the technical, fraud prevention, and banking infrastructure needed to work online payment systems.

Follow below steps to integrate Stripe easily in Laravel website.

Step 1. Install laravel application.

Initial step

Please refer article for this > [How to install Laravel 5.X] for how to install Laravel

Step 2. Create account in Stripe and generate key and secret

Go to https://stripe.com and signup with basic details step by step.

Run test mode as per the screenshot

Stripe account - get stripe key and secret key
Stripe account – get stripe key and secret key

The screenshot about to get the test mode API key’s credentials

Step 3. copy the credentials in .env file

Add the parameters in .env file

STRIPE_KEY=pk_test_stripe_key
STRIPE_SECRET=sk_test_stripe_secret

Note: For security, reason adds those credential only in .env file.

Step 4. Install Stripe package via composer

Install stripe package via composer

Run below command for install package

This will update all the dependency of the package according to our version.

$ composer require stripe/stripe-php

Step 5. Create Route and Controller with actions and view

Create MVC files

Run below command to generate a controller.

$ php artisan make:controller PaymentController
<?php
# Copy the code from below to that controller file located at app/Http/Controllers/PaymentController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PaymentController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        //$this->middleware('auth'); // if you want user to be logged in to use this function then uncomment this code.
    }
    
    public function handleonlinepay(Request $request){  
        
        $input = $request->input();
        try {
            \Stripe\Stripe::setApiKey(env('STRIPE_SECRET'));
                
                // Creating a customer - If you want to create customer uncomment below code.
                /*  $customer = \Stripe\Customer::create(array(
                        'email' => $request->stripeEmail,
                        'source' => $request->stripeToken,
                        'card' => $request->stripeCard
                    ));

                    $stripe_id = $customer->id;
                
                // Card instance
                // $card = \Stripe\Card::create($customer->id, $request->tokenId); 
                */
            
                $unique_id = uniqid(); // just for tracking purpose incase you want to describe something.
            
                // Charge to customer
                $charge = \Stripe\Charge::create(array(
                    'description' => "Plan: ".$input['plan']." - Amount: ".$input['amount'].' - '. $unique_id,
                    'source' => $request->stripeToken,                    
                    'amount' => (int)($input['amount'] * 100), // the mount will be consider as cent so we need to multiply with 100
                    'currency' => 'USD'
                ));
                               
                // Insert into the database
                \App\PaymentLogs::create([                                         
                    'amount'=> $input['amount'],
                    'plan'=> $input['plan'],
                    'charge_id'=>$charge->id,
                    'stripe_id'=>$unique_id,                     
                    'quantity'=>1
                ]);

                return response()->json([
                    'message' => 'Charge successful, Thank you for payment!',
                    'state' => 'success'
                ]);                
            } catch (\Exception $ex) {
                return response()->json([
                    'message' => 'There were some issue with the payment. Please try again later.',
                    'state' => 'error'
                ]);
            }             
                
    }
}

Now Create View file as below at file in your [resources/views/] folder with [pay.blade.php].

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css">
        <link href="{{ URL::asset('css/developer.css') }}" rel="stylesheet" type="text/css">
        <!-- Styles -->

        <script
            src="https://code.jquery.com/jquery-3.3.1.js"
            integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
        crossorigin="anonymous"></script>

        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    </head>
    <body>

        <section class="pricing py-5">
            <div class="container"> 
                    <form action="{{ route('dopay') }}" method="POST" id="subscribe-form" onsubmit="return submitpayment()" >
                    @csrf
                    
                    <div style="text-align: center; margin-bottom: 20px">
                        <span id="alert-danger" class="alert alert-danger d-none"></span>
                        <span id="alert-success" class="alert alert-success d-none"></span>
                    </div>
                    <div class="row">
                        <div class="col-lg-3"></div> 
                        <div class="col-lg-3">
                            <div class="card mb-5 mb-lg-0">
                                <div class="card-body">
                                    <h5 class="card-title text-muted text-uppercase text-center">Basic Plan</h5>
                                    <h6 class="card-price text-center">$9<span class="period">/year</span></h6>
                                    <hr>
                                    <ul class="fa-ul">
                                        <li><span class="fa-li"><i class="fas fa-check"></i></span>Single User</li>
                                        <li><span class="fa-li"><i class="fas fa-check"></i></span>5GB Storage</li>
                                        <li class="text-muted"><span class="fa-li"><i class="fas fa-times"></i></span>Free Subdomain</li>
                                        <li class="text-muted"><span class="fa-li"><i class="fas fa-times"></i></span>Monthly Status Reports</li>
                                        <li class="text-muted"><span class="fa-li"><i class="fas fa-times"></i></span>Free premium support</li>
                                    </ul>
                                    <input type="submit" id="submit-btn-1" name="submit-btn" value="Pay" class="btn btn-block btn-success text-uppercase" />        
                                </div>
                            </div>
                        </div>
                        <div class="col-lg-3">
                            <div class="card mb-5 mb-lg-0">
                                <div class="card-body">
                                    <h5 class="card-title text-muted text-uppercase text-center">Premium Plan</h5>
                                    <h6 class="card-price text-center">$19<span class="period">/year</span></h6>
                                    <hr>
                                    <ul class="fa-ul">
                                        <li><span class="fa-li"><i class="fas fa-check"></i></span>5 Users</li>
                                        <li><span class="fa-li"><i class="fas fa-check"></i></span>15GB Storage</li>
                                        <li class="text-muted"><span class="fa-li"><i class="fas fa-times"></i></span>Free Subdomain</li>
                                        <li class="text-muted"><span class="fa-li"><i class="fas fa-times"></i></span>Monthly Status Reports</li>
                                        <li class="text-muted"><span class="fa-li"><i class="fas fa-times"></i></span>Free premium support</li>
                                    </ul>
                                    <input type="submit" id="submit-btn-2" name="submit-btn" value="Pay" class="btn btn-block btn-success text-uppercase" />        
                                </div>
                            </div>
                        </div>  
                        <div class="col-lg-3"></div>
                    </div>
                    <input type="hidden" name="amount" id="amount" value="" />
                    <input type="hidden" name="plan" id="plan" value="" />
                    <input type="hidden" name="stripeToken" id="stripeToken" value="" /> 
                </form> 
            </div>  
            <br/><br/><br/>
        </section>           
    </div>
</body>


<script src="https://checkout.stripe.com/checkout.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.js"></script> 


<script type="text/javascript">
function showProcessing() {
    $('.subscribe-process').show();
}
function hideProcessing() {
    $('.subscribe-process').hide();
}

// Handling and displaying error during form submit.
function subscribeErrorHandler(jqXHR, textStatus, errorThrown) {
    try {
        var resp = JSON.parse(jqXHR.responseText);
        if ('error_param' in resp) {
            var errorMap = {};
            var errParam = resp.error_param;
            var errMsg = resp.error_msg;
            errorMap[errParam] = errMsg;
        } else {
            var errMsg = resp.error_msg;
            $("#alert-danger").addClass('alert alert-danger').removeClass('d-none').text(errMsg);
        }
    } catch (err) {
        $("#alert-danger").show().text("Error while processing your request");
    }
}

// Forward to thank you page after receiving success response.
function subscribeResponseHandler(responseJSON) {
//window.location.replace(responseJSON.successMsg);
    if (responseJSON.state == 'success') {
        $("#alert-success").addClass('alert alert-success').removeClass('d-none').text(responseJSON.message);
        $("#alert-danger").addClass('d-none');
    }
    if (responseJSON.state == 'error') {
        $("#alert-danger").addClass('alert alert-danger').removeClass('d-none').text(responseJSON.message);
        $("#alert-success").addClass('d-none');
    }

}
var handler = StripeCheckout.configure({
//Replace it with your stripe publishable key
    key: "{{ env('STRIPE_KEY') }}",
    image: 'https://networkprogramming.files.wordpress.com/2018/10/twitter.png', // add your company logo here
    allowRememberMe: false,
    token: handleStripeToken
});

function submitpayment() {
    var form = $("#subscribe-form");
    if (parseInt($("#amount").val()) <= 0) {
        return false;
    }
    handler.open({
        name: 'Laravel Stripe Payment',
        description: $("#plan").val()+' Plan',
        amount: ($("#amount").val() * 100)
    });
    return false;
}

function handleStripeToken(token, args) {
    form = $("#subscribe-form");
    $("input[name='stripeToken']").val(token.id);
    var options = {
        beforeSend: showProcessing,
        // post-submit callback when error returns
        error: subscribeErrorHandler,
        // post-submit callback when success returns
        success: subscribeResponseHandler,
        complete: hideProcessing,
        contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
        dataType: 'json'
    };

    form.ajaxSubmit(options);
    return false;
}

$("#submit-btn-1").click(function(){
   $("#amount").val('9');
   $("#plan").val('Basic');
});
$("#submit-btn-2").click(function(){
   $("#amount").val('19');
   $("#plan").val('Premium');
});
</script>
</html>

We need to customize this based on our requirement. like I used it for a subscription plan.

Please add routes as per following code in routes/web.php file.

Route::get('/', function () {
    return view('pay');
});

# handle payment response from the backend side of it
Route::post('/dopay', 'PaymentController@handleonlinepay')->name('dopay');

Step 6. Create migration file as below

Run below migration command in terminal

$ php artisan make:migration payment_log

Add below code as below

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class PaymentLogs extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('payment_logs', function (Blueprint $table) {
            $table->increments('id');
            $table->float('amount',8,2);
            $table->enum('plan', ['Basic', 'Premium'])->default('Basic');
            $table->string('charge_id')->collation('utf8mb4_bin');
            $table->string('stripe_id')->comment('customer stripe id')->collation('utf8mb4_bin'); // for now we will store             
            $table->integer('quantity');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('payment_logs');
    }
}

After creating migration run it with below command.

$ php arisan migrate

Step 7. Run demo

Final step

Finally, we are done with the integration. now run Laravel application using below command.

$ php artisan serve

Now in the browser manually type below URL.

http://127.0.0.1/

To run the above URL it will display the result like below screenshot.

Pricing plan selection
Pricing plan selection – we can customize it as per the need

Clicking on the PAY button it will open a popup.

Payment popup using stripe checkout
Payment popup using stripe checkout

Use below card information for testing mode.

Card No: 4242 4242 4242 4242
Expiry Date: 12/20 #We can use any date which greater than today
CVC: 123 #We can use any 3 digits here 

After submitting valid card information we will get a success message as below.

Success message after payment
A success message will render after submitting valid card information

For payment confirmation check the database table and stripe payment log as below.

We can confirm payment inside the database.
We can confirm payment inside the database.
check payment in stripe account using charge id
The same way we can also check payment in stripe account using charge id.
detail information of charge id
Clicking on detail charge id it will open detail information regarding all the inputs from the user.

So Finally, we are done with the example tutorial of Stripe payment integration in Laravel. I have also attached code on Github, so you can find it from there too.

So you are now done with Stripe payment gateway integration in laravel website. Enjoy !!

6 thoughts on “Stripe Payment Gateway Integration In Laravel 5.x

  1. Pingback: Instamojo payment gateway integration in Laravel - < CodesCompanion >

  2. alex

    I’ve been exploring for a bit for any high-quality articles or blog posts on this sort of space .
    Exploring in Yahoo I eventually stumbled upon this website.

    Studying this info So i am satisfied to show that I’ve a very excellent uncanny feeling I found out exactly
    what I needed. I so much surely will make certain to don?t disregard this site and provides it a look on a constant basis.

    Reply
  3. uk news

    I like what you guys are usually up too. This sort of clever work
    and coverage! Keep up the good works guys I’ve incorporated you guys to blogroll.

    Reply

Leave a Reply

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