How to Integrate PayPal Payment Gateway in Laravel 8.x
Tags: laravel, php, paypal
Published: 2021-08-23 17:49:17

On my current datetime of writing this blog post I have shown the images of paypal dashboard. It may change on future. Paypal have changed many things on past.

![Paypalcheckout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5exsviy1q69onbej216q.jpg)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Above image give us the idea how PayPal work on behind


**Step 1** : Create a PayPal account.
#### select business on account creation.

**Step 2** : got to developer dashboard from your business dashboard. See The Below Images.

 ![PayPal Business Dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nf2xkwj1osreuw93l2em.png)

**Step 3** : now we are on developer dashboard 
![Developer dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/891638npubjyzd275jq2.png)
**Step 3.1** : now create a rest API App buy clicking on  My App and credential. see the image below.
![App creation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pakhyn3ozehlr50ns5yo.png)
![APP creation page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzxf3l856kww0rxozf3u.png)

## when app is created PayPal also created two sandox account for us. Step-4 can be skip if we want use the default accounts

**Step 4** : create sandbox account
![menusandbox](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1kk7f9t1yneadcubx3kb.png)
![Sandox1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/77etw3g9tgpgtiwepfc5.png)


##Step: 5 accessing the accounts
After creating sandbox account we will have two user email
###1  business email
###2 personal email
we will use the business email to login to our PayPal merchant account.
And personal email to do purchase, order from our Laravel application. 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;watch the below images
![accounts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xjfn91iaz6sr3fl2izcm.png)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from here we get the email pass. The modal open when we click the edit button on  `....` I have shown on above image see **click here** 
![emailpassword](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0bbvt45ivala2nqsxfnq.png)

Going to the PayPal sandbox dasboard. which will give a real look of PayPal merchant Dashboard.
[www.sandbox.paypal.com](https://www.sandbox.paypal.com/)

![sandboxpage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o27q835a9acs0t97jq7o.png)
![login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kxp6v1thzd1s1zy5fjsx.png)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Marchent/Seller Dashboard
![SellerDashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/803y4nubhp964brcpflo.png)

![payer/buyer/personal account](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbkuyeo6b4arno5fyvoy.png)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Buyer/Payer/Personal Dashboard
![Buyer/Payer/Personal Dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/13uuroondvggp04rjm7k.png)

> Hurray we have completed all the PayPal account procedure and sandbox Utilities. Congratulations
[https://developer.paypal.com/docs/business/get-started/](https://developer.paypal.com/docs/business/get-started/)

```
Note :
When we create our  PayPal Rest Api App from the My app and Credential menu.
 By Default PayPal give us two accounts One personal,
 second business.
```
## Now lets jump to the business logic and other essentials.

* Step-6 : get the CLIENT_ID and CLIENT_SECRET from our created on
click the My Apps & Credentials menu on you dashboad and then click to the created app which will redirect to the below image pages
![clientIdAndSecre](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xt1z9g1dn1l6a51kf0fv.png)

* step-7 : puth the CLIENT_ID and CLIENT_SECRET on your laravel .env file 
```
PAYPAL_MODE=sandbox
PAYPAL_SANDBOX_CLIENT_ID=
PAYPAL_SANDBOX_CLIENT_SECRET=

```
* step-8 : Install the [https://github.com/srmklive/laravel-paypal](https://github.com/srmklive/laravel-paypal)

`composer require srmklive/paypal`
> which a wrapper on PayPal SDK 
[https://github.com/paypal/Checkout-PHP-SDK](https://github.com/paypal/Checkout-PHP-SDK)

* step-9 : now publish the config of our srmklive/laravel-paypal

```
php artisan vendor:publish --provider "Srmklive\PayPal\Providers\PayPalServiceProvider"
```
* step-10 : go to app config folder on paypal.php file
`config/paypal.php`
![config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b6yybng9z8owo3nzp19h.png)

* Step-11 : add client_id, secret to paypal.php file

```
'mode'    => env('PAYPAL_MODE', 'sandbox'), // Can only be 'sandbox' Or 'live'. If empty or invalid, 'live' will be used.
    'sandbox' => [
        'client_id'         => env('PAYPAL_SANDBOX_CLIENT_ID'),
        'client_secret'    =>env('PAYPAL_SANDBOX_CLIENT_SECRET',),
    ],
```

* Step-11.1 : create route on api.php file
> we will be sending api request to our server side laravel app from our javascript paypal sdk. That's why we create route on api.php. benefit of doing these we don't need to send CSRF token to our laravel app when we make the fetch post request to our laravel server side application. In laravel api.php route don't work with session.so we will can not use the session() on this route.  we can also write route on web.php file then we have to send csrf token with our post from our javascript.

* step-11.2 : creating route on api.php 
```php
Route::group(['prefix'=>'paypal'], function(){
    Route::post('/order/create',[\App\Http\Controllers\Front\PaypalPaymentController::class,'create']);
    Route::post('/order/capture/',[\App\Http\Controllers\Front\PaypalPaymentController::class,'capture']);
});
```

* Step-11.2.1 : add the PayPal Javascript SDK on your blade file/page. where usually user want to pay. Example checkout page of our product.
[PayPal Javascript SDK](https://developer.paypal.com/demo/checkout/#/pattern/server)

```js
<body>
    <!-- Set up a container element for the button -->
    <div id="paypal-button-container"></div>

    <!-- Include the PayPal JavaScript SDK -->
    <script src="https://www.paypal.com/sdk/js?client-id=test&currency=USD"></script>

    <script>
        // Render the PayPal button into #paypal-button-container
        paypal.Buttons({
 // Call your server to set up the transaction
             createOrder: function(data, actions) {
                return fetch('/api/paypal/order/create', {
                    method: 'POST',
                    body:JSON.stringify({
                        'course_id': "{{$course->id}}",
                        'user_id' : "{{auth()->user()->id}}",
                        'amount' : $("#paypalAmount").val(),
                    })
                }).then(function(res) {
                    //res.json();
                    return res.json();
                }).then(function(orderData) {
                    //console.log(orderData);
                    return orderData.id;
                });
            },

            // Call your server to finalize the transaction
            onApprove: function(data, actions) {
                return fetch('/api/paypal/order/capture' , {
                    method: 'POST',
                    body :JSON.stringify({
                        orderId : data.orderID,
                        payment_gateway_id: $("#payapalId").val(),
                        user_id: "{{ auth()->user()->id }}",
                    })
                }).then(function(res) {
                   // console.log(res.json());
                    return res.json();
                }).then(function(orderData) {
                    
                    // Successful capture! For demo purposes:
                  //  console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
                    var transaction = orderData.purchase_units[0].payments.captures[0];
                    iziToast.success({
                        title: 'Success',
                        message: 'Payment completed',
                        position: 'topRight'
                    });
                });
            }
            
        }).render('#paypal-button-container');
    </script>
</body>
```


![checkoutPage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jl53m0z2r649stlufqsn.png)

* Step-11.2.2 : when we importing the paypal javascirpt sdk
at the bottom of our body tag replace client_id=test with client-id=<?php echo config('services.paypal.client_id') ?>

```js

    <script src="https://www.paypal.com/sdk/js?client-id=test&currency=USD"></script>
```

```js
client-id={{config('services.paypal.client_id')}}
```


* step-11.2 on Javascript SDK at createOrder we write /api/paypal/order/create url which send a post request to our larave app.
```js
createOrder: function(data, actions) {
                return fetch('/api/paypal/order/create', {
                    method: 'POST',
                    body:JSON.stringify({
                        'course_id': "{{$course->id}}",
                        'user_id' : "{{auth()->user()->id}}",
                        'amount' : $("#paypalAmount").val(),
                    })
                }).then
```

* step-11.3 : create the PaypalPaymentController
`php artisan make:controller PaypalPaymentController`
* step-11.4 : writhe the create  method on PaypalPaymentController

* Step-11.5 : write logic and make request to paypal using the package we are using

```php
  public function create(Request $request)
    {
        $data = json_decode($request->getContent(), true);

        $this->paypalClient->setApiCredentials(config('paypal'));
        $token = $this->paypalClient->getAccessToken();
        $this->paypalClient->setAccessToken($token);
        $order = $this->paypalClient->createOrder([
            "intent"=> "CAPTURE",
            "purchase_units"=> [
                 [
                    "amount"=> [
                        "currency_code"=> "USD",
                        "value"=> $data['amount']
                    ],
                     'description' => 'test'
                ]
            ],
        ]);
        $mergeData = array_merge($data,['status' => TransactionStatus::PENDING, 'vendor_order_id' => $order['id']]);
        DB::beginTransaction();
        Order::create($mergeData);
        DB::commit();
        return response()->json($order);


        //return redirect($order['links'][1]['href'])->send();
       // echo('Create working');
    }
```

below code snippet setup the config and send a post request to paypal to get the access token
```php
$this->paypalClient->setApiCredentials(config('paypal'));
        $token = $this->paypalClient->getAccessToken();
        $this->paypalClient->setAccessToken($token);
```
below code create a order on paypal on paypal gives us the order object which have a `id` order id
```php
$order = $this->paypalClient->createOrder([
            "intent"=> "CAPTURE",
            "purchase_units"=> [
                 [
                    "amount"=> [
                        "currency_code"=> "USD",
                        "value"=> $data['amount']
                    ],
                     'description' => 'test'
                ]
            ],
        ]);
```
saving the order with the paypal order id on our database

```php
$mergeData = array_merge($data,['status' => TransactionStatus::PENDING, 'vendor_order_id' => $order['id']]);
        DB::beginTransaction();
        Order::create($mergeData);
        DB::commit();
        return response()->json($order);
```

### after creating the order a paypal payment modal open up.login as personal then paypal payment form will appear.

![loignasPersonal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8u22wc0u3xv6wb26mcs0.png)
![Transaction](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e0cc38nxppyxfp8f7rd5.png)

When we click on the paypment button on the paypal form model.
The javascript Paypal Sdk at onApprove we make a post request to our laravel app with the order which was provided by our laravel app from paypal on create order process.

```js
 onApprove: function(data, actions) {
                return fetch('/api/paypal/order/capture' , {
                    method: 'POST',
                    body :JSON.stringify({
                        orderId : data.orderID,
                        payment_gateway_id: $("#payapalId").val(),
                        user_id: "{{ auth()->user()->id }}",
                    })
                }).
```
the post goes to api/paypal/order/capture which lead to create us new method on PayPalPaymentController 
` public function capture(Request $request)`

on that method we write our business logic

```php

public function capture(Request $request)
    {
        $data = json_decode($request->getContent(), true);
        $orderId = $data['orderId'];
        $this->paypalClient->setApiCredentials(config('paypal'));
        $token = $this->paypalClient->getAccessToken();
        $this->paypalClient->setAccessToken($token);
        $result = $this->paypalClient->capturePaymentOrder($orderId);

//            $result = $result->purchase_units[0]->payments->captures[0];
        try {
            DB::beginTransaction();
            if($result['status'] === "COMPLETED"){
                $transaction = new Transaction;
                $transaction->vendor_payment_id = $orderId;
                $transaction->payment_gateway_id  = $data['payment_gateway_id'];
                $transaction->user_id   = $data['user_id'];
                $transaction->status   = TransactionStatus::COMPLETED;
                $transaction->save();
                $order = Order::where('vendor_order_id', $orderId)->first();
                $order->transaction_id = $transaction->id;
                $order->status = TransactionStatus::COMPLETED;
                $order->save();
                DB::commit();
            }
        } catch (Exception $e) {
            DB::rollBack();
            dd($e);
        }
        return response()->json($result);
    }

```







Again we make a post request to paypal to get the access token using the below snippet

```php
 $data = json_decode($request->getContent(), true);
        $orderId = $data['orderId'];
        $this->paypalClient->setApiCredentials(config('paypal'));
        $token = $this->paypalClient->getAccessToken();
        $this->paypalClient->setAccessToken($token);
```

then we make our payment using capturePaymentOrder()

`$result = $this->paypalClient->capturePaymentOrder($orderId);`

then do our database saving stuff 

```php
 DB::beginTransaction();
            if($result['status'] === "COMPLETED"){
                $transaction = new Transaction;
                $transaction->vendor_payment_id = $orderId;
                $transaction->payment_gateway_id  = $data['payment_gateway_id'];
                $transaction->user_id   = $data['user_id'];
                $transaction->status   = TransactionStatus::COMPLETED;
                $transaction->save();
                $order = Order::where('vendor_order_id', $orderId)->first();
                $order->transaction_id = $transaction->id;
                $order->status = TransactionStatus::COMPLETED;
                $order->save();
                DB::commit();
```

Happy coding. Thank you to read my post. Leave a comment for a feedback. Give a unicorn.

> Reference
[developer.paypal.com/docs/business/checkout/set-up-standard-payments](https://developer.paypal.com/docs/business/checkout/set-up-standard-payments/)
[https://developer.paypal.com/docs/business/checkout/set-up-standard-payments/#1-add-payment-buttons](https://developer.paypal.com/docs/business/checkout/set-up-standard-payments/#1-add-payment-buttons)
[https://github.com/paypal/Checkout-PHP-SDK#code](https://github.com/paypal/Checkout-PHP-SDK#code)
[https://github.com/srmklive/laravel-paypal/issues/407#issuecomment-864521831](https://github.com/srmklive/laravel-paypal/issues/407#issuecomment-864521831)
[https://www.youtube.com/watch?v=_7YBIRQfSN0&ab_channel=AndreMadarang](https://www.youtube.com/watch?v=_7YBIRQfSN0&ab_channel=AndreMadarang)