PayPal Payments Pro Integration in Laravel

I have written an article about accepting credit card payments using PayPal Payments Pro in PHP. One of the readers asked me how to do the same integration in Laravel. Though Laravel is built in PHP, you have to follow their own standards. On the Laravel framework, you have to tweak a code written for plain PHP. So I decided to write about this PayPal Pro topic for Laravel users. 

For websites that are collecting online payments, PayPal is the secure option for online transactions. It is reliable for both buyers and sellers. Using PayPal Payments Pro you can accept direct payment from credit cards.

In this tutorial, we will walk through integrating PayPal Payments Pro into the Laravel application. The PayPal Pro integration allows you to accept online credit card payments on your Laravel website.

Getting Started

Note: The PayPal Payments Pro is available for merchants in the US, UK, and Canada.

To get started, you need to get your PayPal API credentials. It’s always recommended to first test the payments on the sandbox mode and if everything works as expected then make the payment live. That being said, let’s grab the sandbox API credentials.

Login to the PayPal Developer account. After login, go to Testing Tools >> SANDBOX Accounts and create a business account.

On creating a business account, upgrade the account type to ‘Business-Pro’. PayPal Payments Pro integration requires a ‘Business-Pro’ account type. Click on the ‘Upgrade to Pro’ link and PayPal will convert your account type to ‘Business-Pro’.

Next, copy your API credentials. Copy all 3 values – Username, Password, and Signature.

paypal-api-credentials

Open .env of your Laravel project and add the copied credentials to it.

PAYPAL_API_USERNAME=""
PAYPAL_API_PASSWORD=""
PAYPAL_API_SIGNATURE=""

To handle the payment flow on the Laravel website, add a few routes in the routes/web.php file.

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

Generate the PaymentController using the Artisan command:

php artisan make:controller PaymentController

Create a Payment Form

To perform online transactions, you have to give users a form where they can enter their card details. I will design this payment form using this codepen example.

Create a css and js folder inside the public directory of the Laravel project. Copy the CSS code from the codepen and add it to the css/card.css file.

@import url(https://fonts.googleapis.com/css?family=Roboto:400,900,700,500);
 
body {
  padding: 60px 0;
  background-color: rgba(178,209,229,0.7);
  margin: 0 auto;
  width: 600px;
}
.body-text {
  padding: 0 20px 30px 20px;
  font-family: "Roboto";
  font-size: 1em;
  color: #333;
  text-align: center;
  line-height: 1.2em;
}
.form-container {
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.card-wrapper {
  background-color: #6FB7E9;
  width: 100%;
  display: flex;
 
}
.personal-information {
  background-color: #3C8DC5;
  color: #fff;
  padding: 1px 0;
  text-align: center;
}
h1 {
  font-size: 1.3em;
  font-family: "Roboto"
}
input {
  margin: 1px 0;
  padding-left: 3%;
  font-size: 14px;
}
input[type="text"]{
  display: block;
  height: 50px;
  width: 97%;
  border: none;
}
input[type="email"]{
  display: block;
  height: 50px;
  width: 97%;
  border: none;
}
input[type="submit"]{
  display: block;
  height: 60px;
  width: 100%;
  border: none;
  background-color: #3C8DC5;
  color: #fff;
  margin-top: 2px;
  curson: pointer;
  font-size: 0.9em;
  text-transform: uppercase;
  font-weight: bold;
  cursor: pointer;
}
input[type="submit"]:hover{
  background-color: #6FB7E9;
  transition: 0.3s ease;
}
#column-left {
  width: 46.8%;
  float: left;
  margin-bottom: 2px;
}
#column-right {
  width: 46.8%;
  float: right;
}
 
@media only screen and (max-width: 480px){
  body {
    width: 100%;
    margin: 0 auto;
  }
  .form-container {
    margin: 0 2%;
  }
  input {
    font-size: 1em;
  }
  #input-button {
    width: 100%;
  }
  #input-field {
    width: 96.5%;
  }
  h1 {
    font-size: 1.2em;
  }
  input {
    margin: 2px 0;
  }
  input[type="submit"]{
    height: 50px;
  }
  #column-left {
    width: 96.5%;
    display: block;
    float: none;
  }
  #column-right {
    width: 96.5%;
    display: block;
    float: none;
  }
}

Similarly, add JavaScript code from the codepen into the js/card.js file.

$('form').card({
    container: '.card-wrapper',
    width: 280,
 
    formSelectors: {
        nameInput: 'input[name="first-name"], input[name="last-name"]'
    }
});

Get a copy of jquery.card.js from this GitHub repository. This JS file adds nice effects to the payment form. Store this file under your js directory.

Next, create a payment.blade file and add the code below to it.

<link rel="stylesheet" href="{{ asset('css/card.css') }}">
 
<form method="POST" action="{{ url('charge') }}">
    @csrf
    <div class="form-container">
        <div class="personal-information">
            <h1>Payment Information</h1>
        </div> <!-- end of personal-information -->
          
        <input id="column-left" type="text" name="first-name" placeholder="First Name" required="required" />
        <input id="column-right" type="text" name="last-name" placeholder="Surname" required="required" />
        <input id="input-field" type="text" name="number" placeholder="Card Number" required="required" />
        <input id="column-left" type="text" name="expiry" placeholder="MM / YY" required="required" />
        <input id="column-right" type="text" name="cvc" placeholder="CCV" required="required" />
 
        <div class="card-wrapper"></div>
 
        <input id="input-field" type="text" name="streetaddress" required="required" autocomplete="on" maxlength="45" placeholder="Street Address" />
        <input id="column-left" type="text" name="city" required="required" autocomplete="on" maxlength="20" placeholder="City" />
        <input id="column-right" type="text" name="zipcode" required="required" autocomplete="on" pattern="[0-9]*" maxlength="5" placeholder="ZIP code" />
        <input id="input-field" type="email" name="email" required="required" autocomplete="on" maxlength="40" placeholder="Email" />
        <input id="input-field" type="text" name="amount" required="required" autocomplete="on" maxlength="40" placeholder="Amount"/>
        <input id="input-button" name="submit" type="submit" value="Submit" />
    </div>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<script src="{{ asset('js/jquery.card.js') }}"></script>
<script src="{{ asset('js/card.js') }}"></script>

In the above code, I included CSS and JS files from the respective directory. I also added jQuery via CDN. The form action is set to the charge route.

PayPal Payments Pro integration in Laravel

We have completed the basic setup required to accept credit card payments. Now in the controller, we have to write a code that interacts with the PayPal Pro API. Usually, it needs to study the payment vendor documentation and then integrate it accordingly. When it comes to PayPal, their documentation is too vast that anyone can be lost easily. 

Fortunately, the team behind Omnipay built a fantastic payment-processing library for PHP. The library itself handles all payment-related stuff which saves a ton of time for developers. All we need to do is follow their guidelines. I will write a code provided by Omnipay to the PaymentController. But before that, install the Omnipay library using the below command.

composer require league/omnipay omnipay/paypal

Upon library installation, the PaymentController will have the following code as per the Omnipay structure.

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use Omnipay\Omnipay;
 
class PaymentController extends Controller
{
    public $gateway;
 
    public function __construct()
    {
        $this->gateway = Omnipay::create('PayPal_Pro');
        $this->gateway->setUsername(env('PAYPAL_API_USERNAME'));
        $this->gateway->setPassword(env('PAYPAL_API_PASSWORD'));
        $this->gateway->setSignature(env('PAYPAL_API_SIGNATURE'));
        $this->gateway->setTestMode(true); // here 'true' is for sandbox. Pass 'false' when go live
    }
 
    public function index()
    {
        return view('payment');
    }
 
    public function charge(Request $request)
    {
        $arr_expiry = explode("/", $request->input('expiry'));
 
        $formData = array(
            'firstName' => $request->input('first-name'),
            'lastName' => $request->input('last-name'),
            'number' => $request->input('number'),
            'expiryMonth' => trim($arr_expiry[0]),
            'expiryYear' => trim($arr_expiry[1]),
            'cvv' => $request->input('cvc')
        );
 
        try {
            // Send purchase request
            $response = $this->gateway->purchase([
                'amount' => $request->input('amount'),
                'currency' => 'USD',
                'card' => $formData
            ])->send();

            // Process response
            if ($response->isSuccessful()) {
                // Payment was successful
                $arr_body = $response->getData();
                $amount = $arr_body['AMT'];
                $currency = $arr_body['CURRENCYCODE'];
                $transaction_id = $arr_body['TRANSACTIONID'];
 
                echo "Payment of $amount $currency is successful. Your Transaction ID is: $transaction_id";
            } else {
                // Payment failed
                echo "Payment failed. ". $response->getMessage();
            }
        } catch(Exception $e) {
            echo $e->getMessage();
        }
    }
}

Here in the constructor, we build a $gateway variable and pass the credentials through it to different Omnipay methods. When a user submits a form, the control goes to the charge() method. In this function, Omnipay calls the PayPal Pro API in the background, processes the payment, and gives a final response.

Go ahead and give it a try. To test the payment in sandbox mode, click here to get dummy credit card details. Upon submitting a form, you should see the success message along with your transaction id.

Accept Live Payment with PayPal Payments Pro

Once your payments are working successfully in the sandbox mode, you can go to live mode. For this, you need to replace sandbox credentials with the live details in the .env file. Also, pass a ‘false’ value to the setTestMode() method in the constructor. It will disable sandbox mode and activate the live mode.

It’s all about accepting credit card payments with PayPal Payments Pro in Laravel. I hope this tutorial helps you to integrate PayPal Pro into your Laravel project. I would like to hear your thoughts in the comment section below.

Related Articles

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

2 thoughts on “PayPal Payments Pro Integration in Laravel

  1. This article is really good, thank you very much.. But I have some question..
    I am from Europe and I do not have option to upgrade account to pro Business..
    So my question is, can I make new account and select that I come from USA, but to left empty fields where is credic card (because I want to do this just for testing).. Will it work?
    Thanks in advance, I would really appreciate, if you would set aside time to answer on my question..

Leave a Reply

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