Integrated PayPal in Laravel

Keywords: PHP Session REST SDK

Recently, I'm writing a mall project for foreign buyers. Since it's for foreign buyers, PayPal will be used as a payment platform. Because some problems and time have been spent in docking PayPal, I write down the docking process and hope to help my friends who use PayPal.

I integrated paypal/rest-api-sdk-php. PayPal's API has v1 and v2 versions, and this one I use is v1 version.

The following are shown in code form, no screenshots, but I try to explain it in code.
Suppose you already have a project written in laravel:

Step:1 Installation Extension Package

composer require paypal/rest-api-sdk-php

Step:2 Create paypal.php configuration file

Create a new paypal.php configuration file in the Config directory as follows

return [
    'paypal' => [
        /** set your paypal credential **/
        'client_id' =>'paypal client_id',
        'secret' => 'paypal secret ID',
        /**
         * SDK To configure
         */
        'settings' => array(
            /**
             * Sandbox test'sandbox'or'live'
             */
               'mode' => 'sandbox',
            /**
             * Request timeout
             */
            'http.ConnectionTimeOut' => 1000,
            /**
             * Whether to open logs: true open, false not open
             */
            'log.LogEnabled' => true,
            /**
             * Log-stored files
             */
            'log.FileName' => storage_path() . '/logs/paypal.log',
            /**
             * Log level'DEBUG','INFO','WARN'or'ERROR'
                *
             */
            'log.LogLevel' => 'INFO'
        ),
    ],
    
    '2checkout' => [
        //
    ]
];

Step:3 Create Routes

    // Step 1: Display the form. This is a simple form page. We enter the amount and then click Submit.
    Route::get('paypal-form', 'Payment\PayPalController@payPalShow')->name('paypal-form');

    // Step 2: The first step is to send a request after submission, requesting this method, which is used to create an order and a payment process.
    Route::post('paypal-pay', 'Payment\PayPalController@pay')->name('payment.paypay.pay');

    // Step 3: Asynchronous callback
    Route::post('paypal-notify', 'Payment\PayPalController@payPalNotify')->name('payment.paypal.notify');

    // Step 3: Front-end callback
    Route::get('paypal-return', 'Payment\PayPalController@payPalReturn')->name('payment.paypal.return');

    // Step 3: Cancel
    Route::get('paypal-cancel', 'Payment\PayPalController@payPalCancel')->name('payment.paypal.cancel');

Step:3 Create Controller

<?php

namespace App\Http\Controllers\Payment;

use App\Http\Controllers\BaseController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use PayPal\Api\Amount;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Rest\ApiContext;

class PayPalController extends BaseController
{
    private $_api_context;

    public function __construct()
    {
        $payPal_config = config('payment.payPal');
        // Initialize PayPal Api context
        $this->_api_context = new ApiContext(new OAuthTokenCredential(
            $payPal_config['client_id'],
            $payPal_config['secret']
        ));
        $this->_api_context->setConfig($payPal_config['setting']);
    }

    // display form
    public function payPalShow()
    {
        return view('payment.paypal');
    }
    
    // Step two, request here
    public function pay(Request $request)
    {
        $payer = new Payer();
        $payer->setPaymentMethod('paypal');

        // Product Name, Currency, Quantity, Single Product Amount
        $item1 = new Item();
        $item1->setName('item1')
            ->setCurrency('USD')
            ->setQuantity(1)
            ->setPrice($request->get('amount'));

        // Collecting all products into ItemList
        $item_list = new ItemList();
        $item_list->setItems([$item1]);

        $amount = new Amount();
        $amount->setCurrency('USD')
            ->setTotal($request->get('amount'));

        // Generate transactions
        $transaction = new Transaction();
        $transaction->setAmount($amount)
            ->setItemList($item_list)
            ->setDescription('Your deal')
            ->setNotifyUrl(route('notify_url')) // Note that the asynchronous callback address is set here
            ->setInvoiceNumber($order->order_number); // Set the order number here

        // Setting Front-end Callback Address and Canceling Payment Address
        $redirect_urls = new RedirectUrls();
        $redirect_urls->setReturnUrl(route('payment.paypal.cancel'))
        ->setCancelUrl(route('payment.paypal.cancel'));
        
        $payment = new Payment();
        $payment->setIntent('Sale')
            ->setPayer($payer)
            ->setRedirectUrls($redirect_urls)
            ->setTransactions(array($transaction));
        try {
            // Here the payment process is generated
            $payment->create($this->_api_context);
        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
            if (config('app.debug')) {
                session()->put('error','Connection timeout');
                return redirect()->route('paypal-form');

                /** echo "Exception: " . $ex->getMessage() . PHP_EOL; **/
                /** $err_data = json_decode($ex->getData(), true); **/
                /** exit; **/

            } else {
                session()->put('error','Some error occur, sorry for inconvenient');
                return redirect()->route('paypal-form');
            }
        }

        foreach($payment->getLinks() as $link) {
            if($link->getRel() == 'approval_url') {
                $redirect_url = $link->getHref();
                break;
            }
        }

        // $payment - > getId () gets the payment line number
        session()->put('paypal_payment_id', $payment->getId());

        if(isset($redirect_url)) {
            // Jump to Payment Page
            return redirect()->away($redirect_url);
        }

        session()->put('error','Unknown error occurred');
        return session()->route('paypal-form');
    }
    
    
    public function payPalReturn(Request $request)
    {
        // After successful payment, when the front page jumps back, the url address will have paymentID and PayerrID
        $payment_id = session()->get('paypal_payment_id');
        session()->forget('paypal_payment_id');

        if (empty(Input::get('PayerID')) || empty(Input::get('token'))) {
            session()->put('error','Payment failed');

            return redirect()->route('paypal-form');
        }
        $payment = Payment::get($payment_id, $this->_api_context);
        $execution = new PaymentExecution();
        $execution->setPayerId(Input::get('PayerID'));
        $result = $payment->execute($execution, $this->_api_context);


        // approved indicates successful payment when the status is received
        if ($result->getState() == 'approved') {

            session()->put('success','Payment success');
            return redirect()->route('paypal-form');
        }
        session()->put('error','Payment failed');

        return redirect()->route('paypal-form');
    }
    
    public function payPalNotify()
    {
        Log::info(12312, Input::get());
        // Here we write our business logic, order status updates, logistics information and so on.
    }
}

Step:4 Create Forms

<form class="form-horizontal" method="POST" id="payment-form" role="form" action="{!! URL::route('paypal-pay') !!}" >
    {{ csrf_field() }}
    
    <div class="form-group{{ $errors->has('amount') ? ' has-error' : '' }}">
        <label for="amount" class="col-md-4 control-label">Amount</label>
    
        <div class="col-md-6">
            <input id="amount" type="text" class="form-control" name="amount" value="{{ old('amount') }}" autofocus>
    
            @if ($errors->has('amount'))
                <span class="help-block">
                    <strong>{{ $errors->first('amount') }}</strong>
                </span>
            @endif
        </div>
    </div>
    
    <div class="form-group">
        <div class="col-md-6 col-md-offset-4">
            <button type="submit" class="btn btn-primary">
                Paywith Paypal
            </button>
        </div>
    </div>
</form>

The above is not only the docking process of PayPal when I was working on the mall project, but also a lot of problems will arise because of the poor English.
If English is good and you want to know more usage, you can see PayPal's developer documentation and demo demonstrations.

Posted by sidsel on Thu, 18 Apr 2019 18:18:33 -0700