• iconJakarta, Indonesia
  • iconlaratech.channel@gmail.com

+62081290348080

icon

Need Help?

+62081290348080

How to Integrate PayPal Payment Gateway with Laravel Application Step by Step

How to Integrate PayPal Payment Gateway with Laravel Application Step by Step

How to Integrate PayPal Payment Gateway with Laravel Application Step by Step


Adding PayPal to LMS Using Laravel

 

Hello guys, thank you for all your support, in this tutorial I will be adding a feature called payment gateway and we will be using a PayPal payment gateway, I have so many requests from the audience, So I decided to write this article and create a separate video about how to integrate PayPal to your laravel project. I hope this article will help you to understand the steps. 

 

So, in this Article, I will take you guys through a step-by-step process to integrate PayPal into any of your laravel projects as easily as it is.

 

So, to get started with this implementation we have to install two packages.

 

1. ( srmklive/laravel-paypal ). Which will help us to integrate PayPal in less than a few minutes.

 

To Install it is very simple let use the following commands to install it.

 

composer require srmklive/paypal:~3.0

 

To Publish the Asset let us use the following command:

 

php artisan vendor:publish --provider "Srmklive\PayPal\Providers\PayPalServiceProvider"

 

More About the Laravel-PayPal  Read Documentation


 

2. ( /agent ). Which will help us to get the users that are not registered or login to the system to able to add product to cart before checking out.

 

To Install it is very simple let use the following commands to install it.

 

composer require jenssegers/agent

 

More About the Agent Package  Read Documentation


 

After installing the package, we will now have to create an account or login into our existing PayPal developer account to Retrieve our sandbox credentials.

 

The steps are as follows:

 

Step 1: Login to PayPal Sandbox Dashboard

 

Open the browser and type (developer.paypal.com ) and I will leave the link in the video description below.

 

Step 2: Create New  PayPal App

 

Create a new testing App. Inside the PayPal developer dashboard.

 

Step 3: Configure .ENV

 

Open the .Env file and add the app credential:

            App Client Id:

            App Secret Key:

 

Step 4: AddToCart Model

 

Create AddToCart Model along with the migrations by using the following command.

           

php artisan make:model AddToCart -m

 

The -m flag will create the migration file for the add to cart model.

 

Step 5: Order Model

 

Create Order Model by using the following command.

           

php artisan make:model  Order -m

 

The -m flag will create the migration file for the order model.

 

Step 6: OrderCourse Model

 

Create OrderCourse Model by using the following command.

           

php artisan make:model  OrderProduct -m

 

The -m flag will create the migration file for the order courses model.

 

Step 7:  PaymentController 

 

Create a PaymentController by using the below command:

 

php artisan make:controller PaymentController

 

Open the Payment controller and define two new functions as follows:

 

  1. Success Method.

 

Copy and paste the following code snippets inside the success function.

 

// Import the class namespaces first, before using it directly

use Jambasangsang\Flash\Facades\LaravelFlash;
use Srmklive\PayPal\Services\PayPal as PayPalClient;


use App\Models\AddToCart;
use App\Models\Order;
use App\Models\CourseOrder;


    public function success(Request $request)
    {
        $provider = new PayPalClient;
        $provider->setApiCredentials(config('paypal'));
        $provider->getAccessToken();
        $response = $provider->capturePaymentOrder($request['token']);

        // dd($response);

        if (isset($response['status']) && isset($response['status']) == 'COMPLETED') {
            $productInCart = AddToCart::where(['user_id' =>  auth()->user()->id,
                            'payment_id' => $response['id']])->with('course')->get();

            $order = Order::create(['user_id' => auth()->user()->id, 
                     'status' => \constPayPalStatus::SUCCESS, 'date' => now(),
                     'payment_id' => $response['id']]);

            foreach ($productInCart as $key => $cart) {
                CourseOrder::create([
                    'course_id' => $cart->course_id,
                    'payment_id' => $cart->payment_id,
                    'order_id' => $order->id,
                    'discount' => $cart->discount,
                    'qty' => $cart->qty,
                    'price' => $cart->course->price  * $cart->qty
                ]);
            }

            AddToCart::where([
                'user_id' =>  auth()->user()->id,
                'payment_id' => $response['id']
            ])->delete();

            LaravelFlash::withSuccess('Payment Completed Successfully');

            return  redirect()->route('home', ['cart']);
        }

        LaravelFlash::withError('Whops!! Something went wrong please try again');

        return  redirect()->back();
    }

 

  1. Cancel Method.

 

Copy and paste the following code snippets inside the cancel function.

 

// Import the class namespaces first, before using it directly

use Jambasangsang\Flash\Facades\LaravelFlash;
use Srmklive\PayPal\Services\PayPal as PayPalClient;  

use App\Models\AddToCart;


    public function cancel(Request $request)
    {
        if ($request['token']) {

            AddToCart::where(['payment_id' => $request->token])
                ->update(['payment_id' => '', 'status' => \constPayPalStatus::PENDING]);

            LaravelFlash::withInfo('Payment has been Cancelled');

            return  redirect()->route('home', ['cart']);
        }

        LaravelFlash::withError('Whops!! Something went wrong please try again');

        return  redirect()->route('home', ['cart']);
    }

 

Step 8: Open web.php file

 

Create two new routes inside the web.php  file as follows:

 

Route::get('payment-success', [PaypalController::class, 'success'])->name('payment.success');

 

            Paypal.success     

 

The PayPal success route will be the route that would redirect us to the PayPal endpoint.

 

 Route::get('payment-cancel', [PaypalController::class, 'cancel'])->name('payment.cancel');

 

            Paypal.cancel

 

The PayPal cancel route will be the route that will redirect us back to our application when something got wrong or when you decide to cancel your purchase.

 

Step 9:  Cart.php  Livewire Component

 

Create a Livewire Component and give it a name as Cart.php by using the following command.

 

php artisan make:livewire Cart.php

 

Add the follwing code snippets inside the componet as follows:

 

<?php

namespace App\Http\Livewire;


use Livewire\Component;
use Illuminate\Support\Facades\Auth;

use Srmklive\PayPal\Services\PayPal as PayPalClient;
use Jenssegers\Agent\Agent;

use App\Models\Course;
use App\Models\AddToCart;


class Cart extends Component
{
    public $getUserAddToCartProduct;



    public function render()
    {

        if (Auth::check()) {
            $this->updateCartAfterUserLogin();
        }
        $this->getAddToCartProducts();

        return view('livewire.cart');
    }



    public function removeCourseFromCart($id)
    {
        $addToCart =  AddToCart::find($id);

        $addToCart->delete();
        $this->emit('updateAddToCartCount');

        session()->flash('success', 'Product removed from cart !!!');
    }



    public function getAddToCartProducts()
    {
        $agent = new Agent();

        $this->getUserAddToCartProduct = Auth::check()
            ? AddToCart::with('course')->whereUserId(auth()->user()->id)
            ->whereStatus('!=', \constPayPalStatus::SUCCESS)
            ->get()
            : AddToCart::with('course')->whereBrowserName($agent->browser())
            ->whereStatus('!=', \constPayPalStatus::SUCCESS)->get();
    }



    public function addToCartButton($course_id)
    {
        $agent = new Agent();

        // dd($course_id);

        $course = Course::find($course_id);


        // Sorry here is if the course is already inside tha cart

        if (count(AddToCart::where(['browser_name' => $agent->browser(), 
             'course_id' => $course_id])->get()) > 0) {

            session()->flash('info', 'The Course' . $course->name . 
                             ' is already available in cart');

            return;
        }

        // Sorry here is if the authenticated users course is already inside tha cart

        elseif (Auth::check() && count(AddToCart::where(['user_id' => auth()->user()->id, 
                'course_id' => $course_id])->get()) > 0) {

            session()->flash('info', 'The Course ' . $course->name . 
                             ' is already available in cart');
            return;
        }


        // Check if the user is not logged in add to cart with the broswer name
        if (!Auth::check()) {
            AddToCart::create(['browser_name' => $agent->browser(), 
                'course_id' => $course_id, 'price' => $course->price, 'qty' => 1]);
        }

        // If the user is logged in add to cart with User Id;
        else {
            AddToCart::create(['user_id' => auth()->user()->id, 
                'course_id' => $course_id, 'price' => $course->price, 'qty' => 1]);
        }

        session()->flash('success', 'The Course' . $course->name . ' added to cart');
        $this->emit('updateAddToCartCount');
    }



    public function checkOut($course_id = null)
    {
        if (!empty($course_id)) {
            $this->addToCartButton($course_id);  // is a function
        }

        // if (!Auth::check()) {
        //     return   $this->dispatchBrowserEvent('loginModal');
        // }

        $this->getUserAddToCartProduct = AddToCart::with('course')
            ->whereUserId(auth()->user()->id)
            ->where('status', '!=', \constPayPalStatus::SUCCESS)
            ->get();


        $provider = new PayPalClient([]);
        $token  = $provider->getAccessToken();
        $provider->setAccessToken($token);

        // dd($provider);

        $payPalOrder = $provider->createOrder([
            'intent' => 'CAPTURE',
            'purchase_units' => [
                [
                    "amount" => [
                        "currency_code" => 'USD',
                        "value" => $this->getUserAddToCartProduct->sum('price'),
                    ]
                ]
            ],
            'application_context' => [
                'cancel_url' => route('payment.cancel'),
                'return_url' => route('payment.success'),
            ]

        ]);

        // dd($payPalOrder);


        if ($payPalOrder['status']  == 'CREATED') {

            foreach ($this->getUserAddToCartProduct as $key => $cartCourse) {
                $cartCourse->status = \constPayPalStatus::IN_PROCESS;
                $cartCourse->payment_id = $payPalOrder['id'];
                $cartCourse->save();
            }
            return redirect($payPalOrder['links'][1]['href']);
        } else {
            return redirect()->back()->with("Whoops!! Something got wrong");
        }
    }



    public function updateAddToCartAfterUserLogin()
    {
        $agent = new Agent();

        $coursesInCartByIpBrowserName = AddToCart::with('course')
            ->whereBrowserName($agent->browser());

        if (count($coursesInCartByIpBrowserName->get()) > 0) {
            $coursesInCartByIpBrowserName->update(
                ['user_id' => auth()->user()->id, 'browser_name' => Null]
            );
        }
    }
}

 

Step 10:  AddToCartCounter.php Livewire Component

 

Create another Livewire Component and give it a name as AddToCartCounter.php by using the following command:

 

 php artisan make:livewire AddToCartCounter

 

Add the following code snippets inside the component as following:

 

<?php

namespace App\Http\Livewire;


use Livewire\Component;

use Jenssegers\Agent\Agent;
use Illuminate\Support\Facades\Auth;

use App\Models\AddToCart;



class AddToCartCounter extends Component
{

    public $cardCount = 0;


    protected $listeners = ['updateAddToCartCount' => 'getAddToCartProductCount'];



    public function getAddToCartProductCount()
    {
        $agent = new Agent();

        $this->cardCount = Auth::check() ? AddToCart::whereUserId(auth()->user()->id)
            ->where('status', '!=', \constPayPalStatus::SUCCESS)
            ->count() : AddToCart::whereBrowserName($agent->browser())
            ->where('status', '!=', \constPayPalStatus::SUCCESS)
            ->count();
    }


    public function render()
    {
        $this->getAddToCartProductCount();

        return view('livewire.add-to-cart-counter');
    }
}

 

Add the following code snippets inside the add-to-counter blade view file as following:

 

<div>
    {{ $cardCount }}
</div>

 

Step 11:   Payment.php Livewire Component

 

Add the following code snippets inside the component as following:

 

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Illuminate\Support\Facades\Auth;

class Payment extends Cart
{

    public function render()
    {
        return view('livewire.payment');
    }
}

 

Step 12: Define AddToCart Migration File:

 

Add the following code snippet inside.

 

<?php

use App\Models\Course;
use App\Models\Order;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('course_orders', function (Blueprint $table) {
            $table->id();
            $table->foreignIdFor(Order::class)->constrained()
                                ->cascadeOnUpdate()->cascadeOnDelete();
            $table->foreignIdFor(Course::class)->constrained()
                                ->cascadeOnUpdate()->cascadeOnDelete();
            $table->string('payment_id')->nullable();
            $table->integer('price');
            $table->integer('qty');
            $table->string('discount')->nullable()->default(0);
            $table->string('status')->nullable()->default(1);
            $table->timestamps();
        });
    }

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

 

Step 14: Define Orders Migration File:

 

Add the following code snippet inside.

 

<?php

use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->id();
            $table->string('order_number')->nullable();
            $table->foreignIdFor(User::class)->nullable()->constrained()
                                ->cascadeOnUpdate()->cascadeOnDelete();
            $table->string('payment_id')->nullable();
            $table->timestamp('date')->nullable();
            $table->string('status')->nullable()->default(0);
            $table->timestamps();
        });
    }

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

 

Step 14: Define CourseOrders Migration File:

 

Add the following code snippet inside.

 

<?php

use App\Models\Course;
use App\Models\Order;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('course_orders', function (Blueprint $table) {
            $table->id();
            $table->foreignIdFor(Order::class)->constrained()
                               ->cascadeOnUpdate()->cascadeOnDelete();
            $table->foreignIdFor(Course::class)->constrained()
                               ->cascadeOnUpdate()->cascadeOnDelete();
            $table->string('payment_id')->nullable();
            $table->integer('price');
            $table->integer('qty');
            $table->string('discount')->nullable()->default(0);
            $table->string('status')->nullable()->default(1);
            $table->timestamps();
        });
    }

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

 

Video Summary 

 

Hello guys, welcome back to programming with Singhateh. In this tutorial, I will go back to the LMS project that was uploaded a few days ago. I will add a feature called "payment gateway" to it. And the payment gateway that I will be using will be PayPal. After uploading the project, I had so many requests from the audience. So I also decided to write an article and create a separate video about how to integrate PayPal into your Laravel project. I hope this article will help you understand the steps.

 

Let's get a recap of the LMS project before starting the integration. I will take you through the system to see when the user purchases a course it's directly enrolled without a payment procedure,  So in this video, we will include a payment procedure to it.

 

So let's get started. I will be following the article that I wrote to make things easier. You can also go through the article for a better understanding of how to integrate PayPal into your Laravel project.

 

So, to get started with this implementation we have to install two packages.

The first package is laravel-paypal. and the second package is Jens Segers agent. these two packages will make things easier for us.

 

After installing the first package which is the laravel-paypal. now we have to publish the config file. so that we can able to customize things based on our needs.

 

Again, let's now install the second package which is the Jens Segers agent. this package will help us to get the users that are not login to the system and want to add courses to the cart before login into their account. So this package will give us the ability to perform such. To add a course based on your browser name and when you want to check out the browse name will be replaced with your logged-in ID.

 

You can read more about the package through its documentation. the link will be provided to explore more.

 

After installing both packages. Now we can move to the PayPal section. If you don't have a PayPal sandbox account make sure to create one and follow along. I will be using my existing PayPal sandbox account for testing purposes. After logging into our sandbox account. We have to create an App. You can give the app any name you wish. I will give mine LMS and press create button.

 

After the app is created successfully. We will now see our PayPal client ID and PayPal Secret Key. We will copy that Client ID and the Secret key into our Laravel project. To connect the project with PayPal through their API. To put these Credentials we have to open the .env file and place these credentials in. so that laravel will know the link between the framework and PayPal.

 

Now, Laravel will know that PayPal is part of the framework because we linked them using API.  Now the next step we have to create the models. start with the Add to cart model along with its migration file. After that, we will create Order Model along with its migration file. again create CourseOrder Model along with its migration file.

 

Now, Let's create a Plain Payment Controller. Inside the Payment Controller, we will have two methods. the first method will be the PayPal success method. which will capture our payment and create order data inside the database. And the second method will be the Cancel method. which will redirect the user after canceling any purchase from their PayPal account when using our platform.

 

Now I will copy the Success method code snippet and paste it inside the Payment Controller and make some changes.  Again copy the Cancel Method code snippet and paste it inside the Payment controller and make some changes.

 

We have to define PayPal Status as constants so that we can avoid using numbers everywhere in your project.  Open the constant file and define the PayPal status values.

 

After registering the routes. now we have to create a livewire component and name it a cart.php. After creating the component copy the below code snippet and paste it inside and make some changes. make sure to import all the classes to avoid errors.

 

Again, let's create another livewire component and name it as Add to cart counter. and copy the below code snippets and paste them inside.

 

Now, let’s start defining the columns inside each migration file so that can able to start adding courses into the cart and perform PayPal Checkout. I will open each migration file and define columns based on what each need. So, follow along or you can get all the source code step by step on our website.

Thank you for reading this article, if you have anything that you wanted to ask leave your comment and we discuss it. I hope you understand a How to Integrate PayPal Payment Gateway with Laravel Application Step by Step by now.
{"id":1,"name":"Laratech","username":"admin","avatar":"users\\June2022\\WSYjSsq966HbiJIgJyhx.png"}

About the author:

Laratech is a fullstack developer based in Indonesia.
You can find more about him at Twitter

0 Comments

Leave a comment

Tags