> ## 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.

# Stripe Payments: Setup and Configuration for Site Store Pro

> Enable Stripe in Site Store Pro for payments and subscriptions. Add .env API keys, register the webhook endpoint, and override behavior using an extension file.

Stripe is a built-in payment processor in Site Store Pro (processor ID 1) supporting one-time payments and recurring subscriptions via Stripe Elements. Setup requires installing the Stripe PHP SDK, adding your API keys to `.env`, and registering a webhook endpoint in the Stripe Dashboard.

## Setup

### Step 1 — Install the SDK

```bash theme={null}
composer require stripe/stripe-php
```

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

```ini theme={null}
# Production
STRIPE_PUBLISHABLE_KEY=pk_live_xxxxxxxxxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxx

# Sandbox / Test
STRIPE_SANDBOX_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxx
STRIPE_SANDBOX_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxx
STRIPE_SANDBOX_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxx
```

<Info>
  The webhook secret is required for both sandbox and production environments. See [Webhook Registration](#webhook-registration) below.
</Info>

### Step 3 — Activate in Admin

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

***

## Stripe-Specific Options

The **Stripe Address Requirement Toggle** is found in the Processors list under the **Stripe Specific Settings** card. It controls which Stripe Elements are rendered at checkout.

<Tabs>
  <Tab title="Disabled — Simple Payment Form">
    Renders a `PaymentElement` with billing address collection set to `never`.

    * Shows only payment method fields (card number, expiry, CVC)
    * Fastest checkout experience
    * Use when you collect billing details separately or don't need them
  </Tab>

  <Tab title="Enabled — Forced Billing Address Form">
    Renders a `PaymentElement` **plus** an `AddressElement` (mode: `'billing'`).

    * Forces full billing address with **Google Maps autocomplete**
    * Use when you need verified billing addresses for tax or compliance purposes
  </Tab>
</Tabs>

***

# Stripe Subscription Trial Periods & Custom Pricing Guide

***

## 1. Overview & Architecture

SiteStorePro supports a flexible **dual-tier pricing model** for recurring subscription products powered by Stripe:

1. **Initial Trial Period**:
   * Configurable duration (in days, e.g., 7, 14, 30 days).
   * Configurable upfront trial price (e.g., `$0.00` for 100% Free Trials, or a nominal fee like `$1.00` for introductory paid trials).
   * Optional **Display Label** (e.g., `Free Trial`, `7-Day Free Trial`, or `$1 Intro Offer`) that replaces the numeric price display throughout the customer storefront.
2. **Post-Trial Recurring Subscription**:
   * Automatically begins when the trial period concludes on Stripe.
   * Billed at the variant's regular **Public Price** (or wholesale/discounted price as applicable) on the chosen billing interval (monthly, yearly, or weekly).

***

## 2. Database Schema

The `product_variants` table contains the following columns for Stripe trial management:

| Column                 | Type              | Default | Description                                                                        |
| ---------------------- | ----------------- | ------- | ---------------------------------------------------------------------------------- |
| `stripe_trial_enabled` | `TINYINT` / `INT` | `0`     | Toggle enabling (`1`) or disabling (`0`) the Stripe trial period.                  |
| `stripe_trial_days`    | `INT`             | `0`     | Number of days the trial remains active before recurring billing begins.           |
| `stripe_trial_price`   | `DECIMAL(10,2)`   | `0.00`  | Upfront charge due today for the trial period (`0.00` for free trials).            |
| `stripe_trial_label`   | `VARCHAR(255)`    | `NULL`  | Optional text label displayed in place of the numeric price across the storefront. |

***

## 3. Admin Configuration Guide

To enable and configure a Stripe trial for a product variant:

1. Navigate to **Admin → Products → Edit Product**.
2. Select or create a **Product Variant**.
3. Under the **Payment Processor IDs → Stripe** panel:
   * Ensure the variant is configured as a subscription (e.g., by selecting a **Billing Interval** such as Monthly or specifying a Stripe Price ID).
   * Toggle **Trial Period & Pricing** to **On**.
   * Set the following fields:
     * **Days**: Number of trial days (e.g., `14`).
     * **Trial Price**: Amount charged today (e.g., `0.00` for free trial, or `1.00` for a \$1 trial).
     * **Display Label**: Optional custom label (e.g., `Free Trial` or `Special $1 Trial`).
4. Click **Update Variant** or **Save Product**.

### Configuration Examples

* **Standard Free Trial**:
  * *Days*: `14`
  * *Trial Price*: `0.00`
  * *Display Label*: `Free Trial`
  * *Customer sees*: `Free Trial` (with notes indicating 14 days, followed by `$29.99/month`).

* **Introductory Paid Trial**:
  * *Days*: `7`
  * *Trial Price*: `1.00`
  * *Display Label*: `$1 Trial`
  * *Customer sees*: `$1 Trial` (charged `$1.00` today; bills full subscription price after 7 days).

* **Numeric-Only Display (No Custom Label)**:
  * *Days*: `30`
  * *Trial Price*: `0.00`
  * *Display Label*: *(leave blank)*
  * *Customer sees*: `$0.00` (with notes indicating 30 Day Trial, then recurring price).

***

## 4. Customer-Facing Display Behavior

When `stripe_trial_enabled` is active on a variant:

| Storefront Area                  | Behavior with Display Label (e.g. "Free Trial")                                          | Behavior without Label (Blank)                                                      |
| -------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| **Product Page / Buy Box**       | Displays `Free Trial` in place of the price, plus duration & post-trial recurring terms. | Displays `$0.00` (or trial price) with trial duration & post-trial recurring terms. |
| **Catalog (Grid & List)**        | Displays `Free Trial` in primary price position.                                         | Displays `$0.00` (or trial price).                                                  |
| **Shopping Cart Page**           | Shows `Free Trial` in the unit price column with duration and recurring breakdown.       | Shows `$0.00` (or trial price) with duration and recurring breakdown.               |
| **Slide-Out Cart Drawer**        | Displays `Free Trial` in the item row.                                                   | Displays `$0.00` (or trial price) in the item row.                                  |
| **Order Review Breakdown**       | Displays `Free Trial` on the item line; calculates order subtotal using trial price.     | Displays `$0.00` on the item line; calculates subtotal using trial price.           |
| **Featured Items & Cross-Sells** | Displays `Free Trial` across all widget types (Grid, List, Slider).                      | Displays `$0.00` across all widget types (Grid, List, Slider).                      |

***

## 5. Checkout & Stripe Payment Processing Workflow

```
Customer Adds Subscription to Cart
               │
               ▼
   Initial Price Calculated:
   item_price = stripe_trial_price ($0.00 or custom)
               │
               ▼
         Order Review
   (Total due today = $0.00 + tax/shipping if any)
               │
               ▼
   Customer Enters Payment Details
   (Stripe Elements: mode='setup' or 'payment' with manual tokenization)
               │
               ▼
   Frontend calls: stripe.createPaymentMethod({ elements })
               │
               ▼
   Backend calls: StripeProcessor::createSubscription()
               │
   ┌───────────┴───────────────────────────────────────────┐
   │                                                       │
   ▼                                                       ▼
Free Trial ($0.00):                              Paid Trial ($X.XX > 0):
- No upfront fee invoice.                        - Creates upfront InvoiceItem for $X.XX.
- Attaches PaymentMethod to Customer.            - Attaches PaymentMethod to Customer.
- Creates Subscription with:                     - Creates Subscription with:
  • items: [price => $public_price]                • items: [price => $public_price]
  • trial_period_days => $trial_days               • trial_period_days => $trial_days
  • default_payment_method => $pm_id               • default_payment_method => $pm_id
- Initial charge: $0.00.                         - Stripe charges $X.XX upfront invoice.
- Status: 'active' / 'trialing'.                 - Status: 'active' / 'trialing'.
   │                                                       │
   └───────────────────────────┬───────────────────────────┘
                               ▼
            Order Placed & Persisted in Database
                               │
                               ▼
        After Trial Expires (Stripe Webhooks / Engine):
        Stripe automatically bills regular Public Price on interval.
```

***

## 6. Key Code Reference

* **\[`app/Models/ProductVariant.php`]**:
  * `hasStripeTrial()`: Checks if the variant is a subscription with `stripe_trial_enabled` and `stripe_trial_days > 0`.
  * `getTrialPrice()`: Returns `(float) $this->stripe_trial_price`.
  * `hasTrialLabel()`: Returns `true` if a non-empty `stripe_trial_label` exists.
  * `getTrialLabel()`: Returns the string label or `null`.
  * `getSubscriptionRecurringPrice($user)`: Returns the post-trial recurring price (wholesale, sale, or public price).
* **\[`app/Services/DiscountService.php`]**:
  * In `applyDiscountsToCart()` and `getDiscountedPriceForVariant()`: Resolves current trial price for the active cart.
* **\[`app/Livewire/OrderReview.php`]**:
  * `preparePayment()`: Forwards `$subRecurringPrice`, `$trialPrice`, `$trialDays`, and `$trialLabel` to the payment driver.
* **\[`app/Services/Payments/Processors/StripeProcessor.php`]**:
  * `createSubscription()`: Attaches the payment method, creates an upfront `InvoiceItem` if `trial_price > 0`, and creates the subscription with `trial_period_days`.

## Stripe Payments Plugin Extension Override

To customize Stripe behavior without editing the built-in class, create an extension file. The platform auto-detects it — no changes to `config/payment_processors.php` are needed.

**File location:**

```text theme={null}
payment-processors/stripe/StripeProcessorExtension.php
```

```php theme={null}
<?php
namespace PaymentProcessors\Stripe;

use App\Services\Payments\Processors\StripeProcessor as Base;

class StripeProcessorExtension extends Base
{
    // Override only the methods you need — everything else is inherited.

    public function createPaymentIntent(float $amount, string $currency = 'usd'): array
    {
        $result = parent::createPaymentIntent($amount, $currency);
        // Add custom logging, metadata, etc.
        return $result;
    }
}
```

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

***

## Webhook Registration

<Steps>
  <Step title="Register the endpoint in Stripe Dashboard">
    Go to **Stripe Dashboard → Developers → Webhooks → Add endpoint** and enter:

    ```text theme={null}
    https://yourdomain.com/webhooks/stripe
    ```
  </Step>

  <Step title="Set the webhook secret in .env">
    ```ini theme={null}
    STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxx
    ```
  </Step>

  <Step title="Verify events are received">
    Use the Stripe Dashboard's "Send test webhook" feature to confirm your endpoint is reachable and the signature is verified correctly.
  </Step>
</Steps>

Signature verification uses `Stripe\Webhook::constructEvent()` with the `Stripe-Signature` header. All webhook routes are CSRF-exempt via the `webhooks/*` wildcard in `bootstrap/app.php`.

### Handled Events

| Event                           | Action                                                         |
| ------------------------------- | -------------------------------------------------------------- |
| `payment_intent.succeeded`      | Finds order by `authorization_code`, ensures status ≥ 1 (Open) |
| `payment_intent.payment_failed` | Logs the failure                                               |
| `charge.refunded`               | Sets order status to 3 (Refunded)                              |
| `customer.created`              | Stores `stripe_customer_id` on matching user                   |
| `customer.subscription.created` | Extend for subscription entitlement grants                     |
| `customer.subscription.updated` | Extend for plan changes                                        |
| `customer.subscription.deleted` | Extend for access revocation                                   |
| `invoice.payment_succeeded`     | Extend for recurring renewals                                  |
| `invoice.payment_failed`        | Extend for dunning/retry logic                                 |

<Info>
  Subscription lifecycle events (`customer.subscription.*`, `invoice.*`) are currently **logged**. To act on these events — for example, granting or revoking subscription access — use the [Extension Override](#extension-override) pattern to add your business logic.
</Info>

***

## Stripe Customer ID Persistence

When a Stripe Subscription is created, the Stripe Customer ID is saved to `users.stripe_customer_id`. This ID is reused for:

* Future subscription renewals (avoids duplicate customer records)
* Webhook linkage (maps incoming events back to a Site Store Pro user)

***
