> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sitestorepro.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuring PayPal Smart Payment Buttons in Site Store Pro

> Enable PayPal Smart Buttons in Site Store Pro without Composer packages. Add Client ID and Secret to .env to accept PayPal, Venmo, cards, and Pay Later.

PayPal is a built-in payment processor in Site Store Pro (processor ID 3). No Composer packages are required — Site Store Pro communicates with the PayPal Orders API v2 using Laravel's native HTTP client. At checkout, the official PayPal JS SDK renders Smart Payment Buttons, giving buyers the option to pay with PayPal, Venmo, cards, or Pay Later depending on their eligibility.

## Overview

Site Store Pro's PayPal integration uses **Laravel's native `Http` client** to communicate with the PayPal Orders API v2. No external Composer packages are required.

At checkout, the official **PayPal JS SDK** renders Smart Payment Buttons inline, giving buyers the option to pay with:

* PayPal wallet
* Venmo (US)
* Credit and debit cards
* PayPal Pay Later (availability depends on buyer region)

***

## Setup

### Step 1 — Add Credentials to `.env`

```ini theme={null}
# Production
PAYPAL_CLIENT_ID=your_live_client_id
PAYPAL_CLIENT_SECRET=your_live_client_secret
PAYPAL_WEBHOOK_ID=your_live_webhook_id

# Sandbox / Test
PAYPAL_SANDBOX_CLIENT_ID=your_sandbox_client_id
PAYPAL_SANDBOX_CLIENT_SECRET=your_sandbox_client_secret
PAYPAL_SANDBOX_WEBHOOK_ID=your_sandbox_webhook_id
```

<Info>
  Obtain credentials from the [PayPal Developer Dashboard](https://developer.paypal.com/dashboard/). Create a REST API app to receive your Client ID and Secret for both sandbox and production environments.
</Info>

### Step 2 — Activate in Admin

Navigate to **Admin → Checkout → Processors**, set **PayPal** as the Primary processor, and toggle **Production** ON or OFF depending on your environment.

***

## Checkout Flow

PayPal uses a client-side order creation + server-side capture pattern to ensure payment integrity.

<Steps>
  <Step title="createOrder() — Server Call">
    `PayPalProcessor::createOrder()` sends a request to the PayPal Orders API v2, creates a new order object, and returns:

    * The **PayPal Order ID**
    * The **Client ID** (used to initialize the JS SDK)
  </Step>

  <Step title="Smart Buttons Render — Client Side">
    The PayPal JS SDK loads and renders **Smart Payment Buttons** inside `#paypal-button-container`. Buttons displayed are automatically determined by buyer eligibility (PayPal, Venmo, card, Pay Later).
  </Step>

  <Step title="placeOrder($gatewayToken) — Server Call">
    After the buyer approves the payment in the PayPal popup, `placeOrder()` captures the order server-side via the PayPal API. The full capture authorization code is verified and recorded in `order_payments` before the Site Store Pro order is placed.
  </Step>
</Steps>

<Warning>
  The order is never placed in Site Store Pro until `placeOrder()` completes server-side capture verification. Client-side approval alone is not sufficient.
</Warning>

***

## PayPal Smart Payment Buttons

The PayPal JS SDK is loaded with the `buttons` component. Button rendering is entirely automatic — PayPal determines which payment methods to display based on:

* Buyer's PayPal account region and eligibility
* Merchant account capabilities
* Cart currency and amount

No additional configuration is required to enable Venmo, Pay Later, or card buttons — they appear automatically when eligible.

***

## Extension Override

To customize PayPal behavior without editing the built-in class, create an extension file at:

```text theme={null}
payment-processors/paypal/PayPalProcessorExtension.php
```

The platform auto-detects this file on boot — no changes to `config/payment_processors.php` are needed.

<Tip>
  The `payment-processors/` directory sits outside `app/` by design. Its contents are never overwritten by platform updates.
</Tip>

***

**Note on Webhook IDs:** Unlike Stripe or Paddle, PayPal does not use a shared secret hash for webhooks. Instead, PayPal generates a unique **Webhook ID** (e.g. `4JH27391KJ109283K`) when you register the webhook URL. This ID is passed to PayPal's REST API (`/v1/notifications/verify-webhook-signature`) to verify cryptographic authenticity.

***

## Webhook Configuration

### Webhook Endpoint URL

Register this URL in the [PayPal Developer Dashboard](https://developer.paypal.com/dashboard/) under your REST App (**Webhooks → Add Webhook**):

```
https://yourdomain.com/webhooks/paypal
```

* **Route:** `POST /webhooks/paypal` (defined in `routes/web.php`)
* **CSRF Exemption:** Automatically exempted via `webhooks/*` in `bootstrap/app.php`.

### Recommended Events to Subscribe

Select the following event types in your PayPal webhook setup:

| Event Type                       | Description / Action Taken                                                       |
| :------------------------------- | :------------------------------------------------------------------------------- |
| `PAYMENT.CAPTURE.COMPLETED`      | Confirms one-time order payments and marks order status as active.               |
| `PAYMENT.SALE.COMPLETED`         | Records initial and recurring subscription billing payments in `order_payments`. |
| `BILLING.SUBSCRIPTION.ACTIVATED` | Activates recurring subscriptions and activates the associated order.            |
| `BILLING.SUBSCRIPTION.CREATED`   | Logs and validates initial subscription creation.                                |
| `BILLING.SUBSCRIPTION.CANCELLED` | Logs cancellation and updates subscription record status.                        |
| `BILLING.SUBSCRIPTION.SUSPENDED` | Logs suspension and flags subscription status.                                   |
| `BILLING.SUBSCRIPTION.EXPIRED`   | Logs subscription expiration.                                                    |
| `CHECKOUT.ORDER.APPROVED`        | Fallback notification for approved checkout orders.                              |

***

## Webhook  Key Components & Architecture

1. **`app/Http/Controllers/PayPalWebhookController.php`**
   * Receives incoming POST payloads from PayPal.
   * Detects active processor environment (Sandbox vs. Production).
   * Validates webhook transmission signatures against PayPal REST API when `PAYPAL_WEBHOOK_ID` or `PAYPAL_SANDBOX_WEBHOOK_ID` is set.
   * Dispatches events to their respective handlers (`handleSubscriptionActivated`, `handleSaleCompleted`, `handleCaptureCompleted`, etc.).

2. **`app/Services/Payments/Processors/PayPalProcessor.php`**
   * Default built-in payment processor driver (`processor_id = 3`).
   * Manages PayPal authentication, order capture, subscription creation/cancellation, catalog products, and billing plans.
   * Exposes public helper methods `getAccessToken()` and `getBaseUrl()` for API calls.

3. **`config/services.php`**
   * Configures the `paypal` array with client credentials and webhook IDs mapped from `.env`.

4. **`routes/web.php`**
   * Registers named route `webhooks.paypal`.

***
