Skip to main content

Overview

PayPal is one of the world’s most popular payment platforms, enabling customers to pay using their PayPal balance, credit cards, or debit cards. Ecom uses the PayPal Checkout SDK for seamless integration.

Prerequisites

  • PayPal Business account (Sign up here)
  • PayPal API credentials (Client ID and Secret)
  • SSL certificate for production

Configuration

Step 1: Get PayPal API Credentials

1

Login to PayPal Developer

2

Create an App

Navigate to Apps & Credentials and click Create App
3

Copy Credentials

Copy your Client ID and Secret from the app details
4

Choose Environment

Toggle between Sandbox (testing) and Live (production)

Step 2: Configure Environment Variables

Add PayPal credentials to your .env file:
.env
# PayPal Configuration
PAYPAL_CLIENT_ID=AZD...
PAYPAL_CLIENT_SECRET=EL...
PAYPAL_SANDBOX=1  # Set to 0 for production
Set PAYPAL_SANDBOX=1 for testing with sandbox accounts, and PAYPAL_SANDBOX=0 when going live.

Step 3: Enable PayPal in Admin Panel

1

Access Admin Dashboard

Login to your admin panel
2

Navigate to Payment Methods

Go to Setup & ConfigurationsPayment Methods
3

Activate PayPal

Enable PayPal and configure sandbox mode in business settings

Implementation Details

Controller Location

app/Http/Controllers/Payment/PaypalController.php

Payment Flow

1

Initialize PayPal Client

System creates PayPal HTTP client with environment configuration
app/Http/Controllers/Payment/PaypalController.php
public function pay()
{
    // Creating an environment
    $clientId = env('PAYPAL_CLIENT_ID');
    $clientSecret = env('PAYPAL_CLIENT_SECRET');

    if (get_setting('paypal_sandbox') == 1) {
        $environment = new SandboxEnvironment($clientId, $clientSecret);
    } else {
        $environment = new ProductionEnvironment($clientId, $clientSecret);
    }
    $client = new PayPalHttpClient($environment);
}
2

Create PayPal Order

Prepare order details and create PayPal order
app/Http/Controllers/Payment/PaypalController.php
if (Session::has('payment_type')) {
    if (Session::get('payment_type') == 'cart_payment') {
        $combined_order = CombinedOrder::findOrFail(Session::get('combined_order_id'));
        $amount = $combined_order->grand_total;
    }
}

$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = [
    "intent" => "CAPTURE",
    "purchase_units" => [[
        "reference_id" => rand(000000, 999999),
        "amount" => [
            "value" => number_format($amount, 2, '.', ''),
            "currency_code" => \App\Models\Currency::findOrFail(get_setting('system_default_currency'))->code
        ]
    ]],
    "application_context" => [
        "cancel_url" => url('paypal/payment/cancel'),
        "return_url" => url('paypal/payment/done')
    ]
];
3

Redirect to PayPal

Customer is redirected to PayPal for payment
app/Http/Controllers/Payment/PaypalController.php
try {
    $response = $client->execute($request);
    return Redirect::to($response->result->links[1]->href);
} catch (\Exception $ex) {
    flash(translate('Something was wrong'))->error();
    return redirect()->route('home');
}
4

Capture Payment

After customer approves payment, capture the order
app/Http/Controllers/Payment/PaypalController.php
public function getDone(Request $request)
{
    $clientId = env('PAYPAL_CLIENT_ID');
    $clientSecret = env('PAYPAL_CLIENT_SECRET');

    if (get_setting('paypal_sandbox') == 1) {
        $environment = new SandboxEnvironment($clientId, $clientSecret);
    } else {
        $environment = new ProductionEnvironment($clientId, $clientSecret);
    }
    $client = new PayPalHttpClient($environment);

    $ordersCaptureRequest = new OrdersCaptureRequest($request->token);
    $ordersCaptureRequest->prefer('return=representation');
    
    try {
        $response = $client->execute($ordersCaptureRequest);

        if ($request->session()->has('payment_type')) {
            if ($request->session()->get('payment_type') == 'cart_payment') {
                return (new CheckoutController)->checkout_done($request->session()->get('combined_order_id'), json_encode($response));
            }
        }
    } catch (\Exception $ex) {
        // Handle error
    }
}

Amount Formatting

PayPal requires amounts in decimal format with 2 decimal places:
"value" => number_format($amount, 2, '.', '')  // Correct: "100.00"
"value" => $amount  // May cause errors

Currency Support

PayPal supports 25+ currencies. The system uses your default currency:
"currency_code" => \App\Models\Currency::findOrFail(get_setting('system_default_currency'))->code
Supported currencies include:
  • USD, EUR, GBP, CAD, AUD
  • JPY, CNY, INR, MXN, BRL
  • And many more

Routes Configuration

Required routes in routes/web.php:
routes/web.php
// PayPal Payment Routes
Route::get('paypal/payment', [PaypalController::class, 'pay'])->name('paypal.pay');
Route::get('paypal/payment/done', [PaypalController::class, 'getDone'])->name('paypal.done');
Route::get('paypal/payment/cancel', [PaypalController::class, 'getCancel'])->name('paypal.cancel');

Dependencies

PayPal Checkout SDK is included via Composer:
composer.json
"require": {
    "paypal/paypal-checkout-sdk": "dev-master"
}
If not installed, run:
composer require paypal/paypal-checkout-sdk

Testing with Sandbox

Sandbox Configuration

Enable sandbox mode in .env:
PAYPAL_SANDBOX=1
The system automatically uses sandbox environment:
if (get_setting('paypal_sandbox') == 1) {
    $environment = new SandboxEnvironment($clientId, $clientSecret);
} else {
    $environment = new ProductionEnvironment($clientId, $clientSecret);
}

Create Sandbox Accounts

1

Access Sandbox Accounts

Go to PayPal Developer Dashboard → SandboxAccounts
2

Create Test Buyer

Create a personal (buyer) sandbox account
3

Create Test Seller

Create a business (seller) sandbox account (optional)
4

Get Credentials

View account credentials for testing

Test Sandbox Payments

Use sandbox account credentials to test:
  1. Add items to cart on your test site
  2. Select PayPal at checkout
  3. Login with sandbox buyer account
  4. Complete payment
  5. Verify order completion

Payment Cancellation

When customers cancel payment:
app/Http/Controllers/Payment/PaypalController.php
public function getCancel(Request $request)
{
    $request->session()->forget('order_id');
    $request->session()->forget('payment_data');
    flash(translate('Payment cancelled'))->success();
    return redirect()->route('home');
}

Supported Payment Types

PayPal integration supports all payment types:

Cart Payment

if (Session::get('payment_type') == 'cart_payment') {
    $combined_order = CombinedOrder::findOrFail(Session::get('combined_order_id'));
    $amount = $combined_order->grand_total;
}

Wallet Payment

elseif (Session::get('payment_type') == 'wallet_payment') {
    $amount = Session::get('payment_data')['amount'];
}

Package Payments

elseif (Session::get('payment_type') == 'customer_package_payment') {
    $customer_package = CustomerPackage::findOrFail(Session::get('payment_data')['customer_package_id']);
    $amount = $customer_package->amount;
}

Error Handling

The controller handles errors gracefully:
try {
    $response = $client->execute($request);
    return Redirect::to($response->result->links[1]->href);
} catch (\Exception $ex) {
    flash(translate('Something was wrong'))->error();
    return redirect()->route('home');
}

Troubleshooting

Cause: Invalid Client ID or SecretSolution:
  • Verify credentials in .env match PayPal Developer Dashboard
  • Ensure no extra spaces in credentials
  • Check you’re using correct environment (Sandbox vs Live)
Cause: Selected currency not supported by PayPalSolution:
Cause: Incorrect amount formattingSolution:
// Use number_format for proper formatting
"value" => number_format($amount, 2, '.', '')
Cause: Incorrect callback URLsSolution:
  • Ensure URLs use HTTPS in production
  • Verify routes are properly registered
  • Check .htaccess or nginx configuration

Going Live

1

Complete PayPal Business Account

Verify your business account with PayPal
2

Get Live API Credentials

Switch to Live in PayPal Developer Dashboard and get live credentials
3

Update Environment Variables

.env
PAYPAL_CLIENT_ID=<your-live-client-id>
PAYPAL_CLIENT_SECRET=<your-live-secret>
PAYPAL_SANDBOX=0
4

Update Business Settings

Disable sandbox mode in admin panel business settings
5

Test Live Payment

Make a small test transaction with real PayPal account

Webhooks (Advanced)

For real-time payment notifications:
1

Create Webhook in PayPal

Go to PayPal Developer Dashboard → Webhooks
2

Set Webhook URL

https://yourdomain.com/paypal/webhook
3

Select Events

Subscribe to:
  • PAYMENT.CAPTURE.COMPLETED
  • PAYMENT.CAPTURE.DENIED
  • CHECKOUT.ORDER.APPROVED

Security Best Practices

Protect Your API Credentials
  • Never commit .env file to version control
  • Use different credentials for sandbox and production
  • Implement webhook signature verification
  • Enable HTTPS for all payment pages
  • Regularly rotate API credentials

Payment Overview

Learn about payment architecture

Stripe Integration

Configure Stripe as alternative

Build docs developers (and LLMs) love