Paypal payment gateway integration in Laravel 5.7 step by step

  • Brijpal Sharma

    March 13th, 2019 , Posted On:- Web Development

    php laravel


In this post, we learn Paypal payment gateway integration in Laravel 5.7 step by step, Paypal Is a world-famous payment gateway and this is too easy with Laravel.

For this tutorial, we use omnipay/paypal package to payment integration in Laravel 5.7 we start with a fresh Laravel project so we need to create a new Laravel Project. To create a fresh project use this command.

We are going to integrate PayPal Express Checkout in this article below.

Step:1 Create a new Project

laravel new paypal

 

Step:2  install the package omnipay via the composer.

composer require league/omnipay omnipay/paypal

And generate the default layout of Laravel using the flowing command.

php artisan make:auth

Step: 3 Create some routes

Now add new routes for the PayPal integration under app/routes/web.php

Route::get('/paypal/{order?}','PayPalController@form')->name('order.paypal');
Route::post('/checkout/payment/{order}/paypal','PayPalController@checkout')->name('checkout.payment.paypal');
Route::get('/paypal/checkout/{order}/completed','PayPalController@completed')->name('paypal.checkout.completed');
Route::get('/paypal/checkout/{order}/cancelled','PayPalController@cancelled')->name('paypal.checkout.cancelled');
Route::post('/webhook/paypal/{order?}/{env?}','PayPalController@webhook')->name('webhook.paypal.ipn');
Route::get('payment-completed/{order}','PayPalController@paymentCompleted')->name('paymentCompleted');

 

Step: 4 Create Order table.

Create a  migration, modal, and Controller for an order using this command.

php artisan make:model Order -mcr

Adding the required models for this implementation.

app/Order.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    const PAYMENT_COMPLETED = 1;
    const PAYMENT_PENDING = 0;

    /**
     * @var string
     */
    protected $table = 'orders';

    /**
     * @var array
     */
    protected $dates = ['deleted_at'];

    /**
     * @var array
     */
    protected $fillable = ['transaction_id', 'amount', 'payment_status'];
}

 

Step: 5 Update migration table 

We already generated a new migration table for order, now add some columns.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTableOrders extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->integer('service_id');
            $table->string('transaction_id')->nullable();
            $table->float('amount')->unsigned()->nullable();
            $table->integer('payment_status')->unsigned()->default(0);
            $table->timestamps();
            $table->softDeletes();
        });
    }

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

 

Step:8 Create new Migration table Service

Using this flowing command.

php artisan make:model Service -mcr

Now, add some columns in Service table.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateServicesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('services', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('amount');
            $table->timestamps();
        });
    }

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

then use this flowing command to migrate this service table.

php artisan migrate

Add some dummy data into the Service table.

Paypal payment gateway integration in Laravel 5.7 step by step

Step: 7 Add helper 

Adding a new helper class for generating gateway object and routes to interact with PayPal API.

app/PayPal.php

<?php

namespace App;

use Omnipay\Omnipay;

/**
 * Class PayPal
 * @package App
 */
class PayPal
{
    /**
     * @return mixed
     */
    public function gateway()
    {
        $gateway = Omnipay::create('PayPal_Express');

        $gateway->setUsername(config('services.paypal.username'));
        $gateway->setPassword(config('services.paypal.password'));
        $gateway->setSignature(config('services.paypal.signature'));
        $gateway->setTestMode(config('services.paypal.sandbox'));

        return $gateway;
    }

    /**
     * @param array $parameters
     * @return mixed
     */
    public function purchase(array $parameters)
    {
        $response = $this->gateway()
            ->purchase($parameters)
            ->send();

        return $response;
    }

    /**
     * @param array $parameters
     */
    public function complete(array $parameters)
    {
        $response = $this->gateway()
            ->completePurchase($parameters)
            ->send();

        return $response;
    }

    /**
     * @param $amount
     */
    public function formatAmount($amount)
    {
        return number_format($amount, 2, '.', '');
    }

    /**
     * @param $order
     */
    public function getCancelUrl($order)
    {
        return route('paypal.checkout.cancelled', $order->id);
    }

    /**
     * @param $order
     */
    public function getReturnUrl($order)
    {
        return route('paypal.checkout.completed', $order->id);
    }

    /**
     * @param $order
     */
    public function getNotifyUrl($order)
    {
        $env = config('services.paypal.sandbox') ? "sandbox" : "live";

        return route('webhook.paypal.ipn', [$order->id, $env]);
    }
}

 

Step: 7 updates config/service.php

Laravel comes with a config file  config/service.php to be used with third-party API services. For this implementation add following credentials under the same file as below.

'paypal' => [
        'username' => env('PAYPAL_USERNAME'),
        'password' => env('PAYPAL_PASSWORD'),
        'signature' => env('PAYPAL_SIGNATURE'),
        'sandbox' => env('PAYPAL_SANDBOX'),
    ],

 

Step:8 Create a new controller 

To create a new controller use this flowing command.

php artisan make:controller PayPalController

To handle and maintain the request coming into the application we need to pass information to the controller. We are update PayPalController.php 

<?php

namespace App\Http\Controllers;

use App\Order;
use App\PayPal;
use App\Service;
use App\User;
use Illuminate\Http\Request;

/**
 * Class PayPalController
 * @package App\Http\Controllers
 */
class PayPalController extends Controller
{
    
    
    public function form(Request $request, $service_id)
    {

        $service = Service::findOrFail($service_id);


       
        $order = new Order;
        $transaction_id = rand(10000000,99999999);
        $order->user_id = 1 ;  //user id
        $order->transaction_id = $transaction_id;
        $order->service_id    = $service->id;
        $order->amount    = $service->amount;
        $order->save();

        // the above order is just for example.
        return view('form', compact('service','transaction_id'));
    }

    /**
     * @param $order_id
     * @param Request $request
     */
    public function checkout($transaction_id, Request $request)
    {
            $order = Order::where('transaction_id', decrypt($transaction_id))->first();

            $paypal = new PayPal;

            $response = $paypal->purchase([
                'amount' => $paypal->formatAmount($order->amount),
                'transactionId' => $order->transaction_id,
                'currency' => 'USD',
                'cancelUrl' => $paypal->getCancelUrl($order),
                'returnUrl' => $paypal->getReturnUrl($order),
            ]);

            if ($response->isRedirect()) {
                $response->redirect();
            }

            return redirect()->back()->with([
                 'message' => $response->getMessage(),
                
            ]);
    }

    /**
     * @param $order_id
     * @param Request $request
     * @return mixed
     */
    public function completed($order_id, Request $request)
    {

        $order = Order::findOrFail($order_id);

        $paypal = new PayPal;

        $response = $paypal->complete([
            'amount' => $paypal->formatAmount($order->amount),
            'transactionId' => $order->transaction_id,
            'currency' => 'USD',
            'cancelUrl' => $paypal->getCancelUrl($order),
            'returnUrl' => $paypal->getReturnUrl($order),
            'notifyUrl' => $paypal->getNotifyUrl($order),
        ]);

        if ($response->isSuccessful()) {
            $order->update([
                'transaction_id' => $response->getTransactionReference(),
                'payment_status' => Order::PAYMENT_COMPLETED,
            ]);

            return redirect()->route('paymentCompleted', encrypt($order_id))->with([
                'message' => 'You recent payment is sucessful with reference code ' . $response->getTransactionReference(),
            ]);
        }

        return redirect()->back()->with([
            'message' => $response->getMessage(),
        ]);

    }
    public function paymentCompleted($order)
    {
        # code...
        return "Thanks! payment completed";
    }

    /**
     * @param $order_id
     */
    public function cancelled($order_id)
    {
        $order = Order::findOrFail($order_id);

        return redirect()->route('order.paypal', encrypt($order_id))->with([
            'message' => 'You have cancelled your recent PayPal payment !',
        ]);
    }

        /**
     * @param $order_id
     * @param $env
     * @param Request $request
     */
    public function webhook($order_id, $env, Request $request)
    {
        // to do with new release of sudiptpa/paypal-ipn v3.0 (under development)
    }
    
}

 

Step:9 Create the view

Here we create two views one for send amount to Paypal and one for land after payment

form.blade.php

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="gateway--info">
            <div class="gateway--desc">
                @if(session()->has('message'))
                    <p class="message">
                        {{ session('message') }}
                    </p>
                @endif
                <div class="row">
                    <div class="col">
                        <img src="{{ asset('images/paypal.png') }}" class="img-responsive gateway__img">
                    </div>
                    <div class="col">
                        <img src="{{ asset('images/laravel.png') }}" class="img-responsive gateway__img">
                    </div>
                </div>
                <p><strong>Order Overview !</strong></p>
                <hr>
                <p>Item : Yearly Subscription cost !</p>
                <p>Amount : ${{ $service->amount }}</p>
                <hr>
            </div>
            <div class="gateway--paypal">
                <form method="POST" action="{{ route('checkout.payment.paypal', ['transaction_id' => encrypt($transaction_id)]) }}">
                    {{ csrf_field() }}
                    <button class="btn btn-pay">
                        <i class="fa fa-paypal" aria-hidden="true"></i> Pay with PayPal
                    </button>
                </form>
            </div>
        </div>
    </div>
@stop

Ok, Now We almost have done. 

Step:10 Update .env file with PayPal credential details.

PAYPAL_USERNAME = your_user_mail
PAYPAL_PASSWORD = your_password
PAYPAL_SIGNATURE = your_signature
PAYPAL_SANDBOX  = sandbox

Now, everything is ok, now visit this URL  http://localhost:8000/paypal/1 Here 1 is service in which you want to buy.

Paypal payment gateway integration in Laravel 5.7 step by step

Here we store some record of failed and success payment payment_status = 1 show success payment and 0 show failed.

So here we complete tutorials Paypal payment gateway integration in Laravel 5.7 step by step

 


About Author
  • user profile
    Brijpal Sharma

    brijpalsharma99@gmail.com, January 29th, 2018

    Hello, My Name is Brijpal Sharma. I am a Web Developer, Professional Blogger and Digital Marketer from India. I am the founder of Codermen. I started this blog to help web developers & bloggers by providing easy and best tutorials, articles and offers for web developers and bloggers...

3 Comments

user profile image
March 19th, 2019 - 12:39AM

Brijpal, thank you for a clear explanation! It is helpful for me.


user profile image
July 11th, 2019 - 9:31AM

Hey , great post. I have two questions. I sandbox this work prefectly but i live not. I have the error en live "This transaction couldn't be completed. Please redirect your customer to PayPal. " I dont know how can resolve it. Also how switch from sandbox to live. thanks


user profile image
August 15th, 2019 - 10:48PM

Hi, It's not working for me. I keep getting this error message: Trying to get property 'amount' of non-object


You must be logged in to post a comment.