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

# Stripe

> Payment processing, subscriptions, Connect payouts, and webhooks

## Overview

Stripe handles all payment processing. The integration uses **Stripe Connect** for marketplace-style payments: students pay the platform, the platform pays tutors.

**File:** `app/Models/Services/Payments/StripeService.php`

**SDK:** `stripe/stripe-php` v7.2

## Configuration

```
STRIPE_SECRET              — Stripe secret API key
STRIPE_SIGNING_SECRET      — Webhook signing secret (payment events)
STRIPE_SUBSCRIPTION_SIGNING_SECRET — Webhook signing secret (subscription events)
STRIPE_VERSION             — Stripe API version
BUSINESS_PROFILE_MCC_CODE  — Merchant category code
```

Config file: `config/services.php` under `stripe` key.

## Account types

Two types of Stripe accounts are used:

| Type     | Prefix   | Owner          | Purpose                              |
| -------- | -------- | -------------- | ------------------------------------ |
| Customer | `cus_*`  | Student/Parent | Holds payment methods, makes charges |
| Connect  | `acct_*` | Tutor          | Receives payouts                     |

Both stored in `payment_accounts` table, linked to `payment_gateways`.

## Key operations

### Customer management

```php theme={null}
StripeService::createCustomer($user)
```

Creates a Stripe Customer, stores the ID in `PaymentAccount`. Called during registration or first payment.

### Card management

```php theme={null}
StripeService::createCard($user, $data)
// Validates card, creates PaymentMethod, attaches to customer, sets as default

StripeService::validateCard($data)
// Validates card without saving — used for pre-validation
```

Cards stored in the `cards` table with `card_id`, `brand`, `last_4`, `exp_month`, `exp_year`, `is_default`. Soft-deleted when removed.

### Charging & payment flow

The full charge → capture → receipt → payout flow is documented in [Booking & Payments](/workflows/booking-and-payments). Key `StripeService` methods:

| Method            | Purpose                                                      |
| ----------------- | ------------------------------------------------------------ |
| `createCharge()`  | Creates PaymentIntent with manual capture, handles 3D Secure |
| `capture()`       | Captures a pre-authorized payment                            |
| `createReceipt()` | Creates `PaymentReceipt` with commission breakdown           |
| `createPayout()`  | Transfers funds to tutor's Connect account                   |
| `refund()`        | Full or partial refund                                       |

## Subscriptions

Tutors pay a subscription fee to use the platform.

```php theme={null}
StripeService::createSubscription($user, $product)
StripeService::createSubscriptionWithTrial($user, $product, $trialEndDate)
```

Subscription products are defined in the `subscription_products` table with `product_id`, `price_id`, and `trial_period`.

### Billing portal

```php theme={null}
StripeService::getCancelSubscriptionCustomerPortalURL($paymentAccount)
StripeService::getUpdatePaymentMethodSubscriptionCustomerPortalURL($paymentAccount)
```

Generates Stripe Customer Portal URLs for self-service subscription management.

### Subscription statuses

Tracked in the `subscriptions` table:

| Status               | Meaning                            |
| -------------------- | ---------------------------------- |
| `trialing`           | In trial period                    |
| `active`             | Active and paying                  |
| `canceled`           | Cancelled                          |
| `incomplete`         | Payment failed, awaiting retry     |
| `incomplete_expired` | Payment failed, subscription ended |

## Webhooks

### Payment webhooks

**Endpoint:** `POST /api/v1/payments/webhooks/accounts`

Validates webhook signature using `STRIPE_SIGNING_SECRET`.

### Subscription webhooks

**Endpoint:** `POST /api/subscriptions/webhooks`

```php theme={null}
StripeService::handleSubscriptionWebhook($request)
```

Validates signature using `STRIPE_SUBSCRIPTION_SIGNING_SECRET`. Updates subscription status in the database based on Stripe events.

<Warning>
  Both webhook endpoints are **public** (no auth middleware). Security relies entirely on Stripe's webhook signature verification.
</Warning>

## Payment status flow

See [Booking & Payments — Step 3](/workflows/booking-and-payments#step-3-make-payment) for the full payment flow with booking state transitions.

```
PaymentIntent created (manual capture)
├── requires_action → Client handles 3D Secure → succeeds/fails
├── requires_capture → Booking state: REQUIRES_CAPTURE (5)
│   └── capture() → Booking state: PAYED (1)
│       └── createPayout() → Transfer to tutor Connect account
├── succeeded → Booking state: PAYED (1)
└── canceled/failed → Payment failed
```
