DEV Community

Cover image for Integrating PayPal Payments with Laravel: A Comprehensive Guide
bmtmadushanka
bmtmadushanka

Posted on

Integrating PayPal Payments with Laravel: A Comprehensive Guide

In this tutorial, we will walk through the process of integrating PayPal payments into a Laravel application. This will include setting up the PayPal button on the frontend, handling payment authorization and capturing on the server, and updating the user’s wallet balance. By the end of this guide, you’ll have a working PayPal payment system seamlessly integrated into your Laravel application.

Prerequisites
Before we start, make sure you have the following:

A Laravel application set up
A PayPal developer account
Basic knowledge of JavaScript and PHP
Step 1: Setting Up PayPal SDK
First, we need to include the PayPal JavaScript SDK in our Blade File. You can include it directly from PayPal’s CDN.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PayPal Integration</title>
    <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"></script>
</head>
<body>
    <div class="w-100 text-right" id="paypal_button_container">
        <div id="paypal-button"></div>
    </div>
    <input type="text" id="amount" placeholder="Enter amount" />
    <div id="amount_validation_status"></div>
    <div id="payment_success_alert" class="d-none">Payment successful!</div>

    <script>
        document.addEventListener('DOMContentLoaded', (event) => {
            paypal.Buttons({
                env: 'sandbox', // Or 'production'
                style: {
                    size: 'medium',
                    color: 'gold',
                    shape: 'pill',
                    label: 'pay',
                    tagline: false
                },
                onCancel: function (data) {
                    // Show a cancel page, or return to cart
                },
                createOrder: function(data, actions) {
                    let amount = document.getElementById("amount").value;
                    if (amount < 10) {
                        document.getElementById('amount_validation_status').innerText = 'Deposit amount should be greater than $10.';
                        return actions.reject();
                    }
                    return actions.order.create({
                        purchase_units: [{
                            amount: {
                                value: amount
                            }
                        }]
                    });
                },
                onApprove: function(data, actions) {
                    return actions.order.capture().then(function(details) {
                        console.log(details); // Log the entire details object to inspect its structure

                        // Extract necessary information
                        let payer = details.payer;
                        let transaction = details.purchase_units[0].payments.captures[0];

                        // Log extracted details for debugging
                        console.log('Payer:', payer);
                        console.log('Transaction:', transaction);

                        // Prepare data for server-side request
                        let invoice_id = transaction.id; // Assuming transaction ID as invoice_id
                        let top_up_amount = transaction.amount.value;
                        let payer_email = payer.email_address;
                        let payer_first_name = payer.name.given_name;
                        let payer_last_name = payer.name.surname;
                        let payee_email = details.purchase_units[0].payee.email_address;
                        let transaction_date_time = transaction.update_time;

                        return fetch("{{ route('wallet.payment.execute') }}", {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'X-CSRF-TOKEN': '{{ csrf_token() }}'
                            },
                            body: JSON.stringify({
                                paymentID: transaction.id,
                                payerID: payer.payer_id,
                                invoice_id: invoice_id,
                                top_up_amount: top_up_amount,
                                payer_email: payer_email,
                                payer_first_name: payer_first_name,
                                payer_last_name: payer_last_name,
                                payee_email: payee_email,
                                transaction_date_time: transaction_date_time
                            })
                        }).then(response => {
                            console.log('Server Response:', response);
                            return response.json();
                        }).then(response => {
                            if (response.success) {
                                document.getElementById("amount").classList.remove("is-valid");
                                document.getElementById("amount").value = null;
                                document.getElementById("payment_success_alert").classList.remove("d-none");

                                setTimeout(function() {
                                    window.location.href = "{{ route('advertiser.wallet.index') }}";
                                }, 2000);
                            } else {
                                alert("Payment update failed.");
                            }
                        }).catch(error => {
                            console.error('Error:', error);
                            alert("Payment failed. Something went wrong.");
                        });
                    });
                },
                onError: function (err) {
                    console.error('PayPal Error:', err);
                    alert("Payment failed. Something went wrong.");
                }
            }).render('#paypal-button');
        });
    </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Explanation
PayPal SDK Script: The script tag loads the PayPal SDK.
PayPal Buttons: Initializes and renders the PayPal buttons.
Order Creation: Validates the amount and creates an order.
Order Approval: Captures the payment and sends the necessary data to the server for further processing.
Step 2: Server-Side Handling in Laravel
In your Laravel controller, create a method to handle the payment execution. This method will update the user’s wallet and save the transaction details.


use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use App\Models\WalletTopUpHistory;
use App\Mail\AdvertiserDeposit;

public function executePayment(Request $request) {
    DB::beginTransaction();

    try {
        $top_up_amount = $request->top_up_amount;

        $user = Auth::user();
        $user->wallet = $user->wallet + $top_up_amount;
        $user->save();

        $transaction_date_time = date("Y-m-d H:i:s", strtotime($request->transaction_date_time));

        $wallet_top_up_history = new WalletTopUpHistory();
        $wallet_top_up_history->advertiser_id = Auth::id();
        $wallet_top_up_history->invoice_id = $request->invoice_id;
        $wallet_top_up_history->top_up_amount = $request->top_up_amount;
        $wallet_top_up_history->payer_email = $request->payer_email;
        $wallet_top_up_history->payer_first_name = $request->payer_first_name;
        $wallet_top_up_history->payer_last_name = $request->payer_last_name;
        $wallet_top_up_history->payee_email = $request->payee_email;
        $wallet_top_up_history->transaction_date_time = $transaction_date_time;
        $wallet_top_up_history->save();

        $email = $user->email;
        $amount = $request->top_up_amount;

        Mail::to($email)->send(new AdvertiserDeposit("emails.advertiser.deposit", $amount, $user));

        DB::commit();

        return response()->json(['success' => true]);

    } catch (\Exception $e) {
        DB::rollBack();
        return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
    }
}

Enter fullscreen mode Exit fullscreen mode

Explanation
Transaction Management: Wraps the operations in a database transaction to ensure data integrity.
Wallet Update: Updates the user’s wallet balance.
Transaction History: Saves the transaction details in WalletTopUpHistory.
Email Notification: Sends a confirmation email to the user.
Error Handling: Rolls back the transaction in case of any errors and returns a JSON response

Conclusion
Integrating PayPal payments into your Laravel application involves setting up the PayPal SDK on the frontend and handling the payment processing on the backend. By following this guide, you can seamlessly integrate PayPal payments and provide a smooth experience for your users.

Top comments (1)

Collapse
 
websilvercraft profile image
websilvercraft

This is how a structure the code, in order to be able to switch between different payment processors like Stripe and Paypal: How to Add and Implement Payment Processing Interfaces in Laravel 11: The Part 1 with Hardcoded Binding