web-production-saas-starter/next_b2b_starter/docs/04-payments-and-billing.md
2025-12-16 18:54:41 +04:00

99 lines
2.2 KiB
Markdown

# Payments & Billing
The starter supports Stripe or Polar. Subscription status is managed via Stytch Custom Claims.
## Subscription Status
- **`active` / `trialing`**: User has access.
- **`past_due` / `canceled` / `unpaid`**: Access restricted.
## Checking Payment Status
Use `hasActiveSubscription()` helper function.
**File**: `lib/auth/subscription.ts`
### Server-Side Check
```typescript
import { hasActiveSubscription } from '@/lib/auth/subscription';
export default async function Page() {
const session = await requireMemberSession();
if (!hasActiveSubscription(session)) {
return <div>Upgrade to access</div>;
}
return <PremiumContent />;
}
```
### Client-Side Check
```typescript
'use client';
import { hasActiveSubscription } from '@/lib/auth/subscription';
export function Feature() {
const { session, member } = useStytchMemberSession();
if (!hasActiveSubscription(session, member)) {
return <button>Subscribe</button>;
}
return <FeatureContent />;
}
```
## Payment Flow Architecture
```mermaid
sequenceDiagram
participant User
participant Frontend
participant API
participant Stripe/Polar
User->>Frontend: Click Subscribe
Frontend->>API: POST /api/billing/checkout
API->>Stripe/Polar: Create Session
Stripe/Polar-->>User: Redirect to Checkout
User->>Stripe/Polar: Pay
Stripe/Polar->>API: Webhook (async)
API->>Stytch: Update Custom Claims
```
## Paywalls
We include a pre-built Paywall component.
**File**: `components/billing/subscription-paywall.tsx`
```typescript
import { SubscriptionPaywall } from '@/components/billing/subscription-paywall';
export default function Page() {
return (
<SubscriptionPaywall>
<ProtectedContent />
</SubscriptionPaywall>
);
}
```
## API Route Protection
Always verify logic in your API routes, returning `402 Payment Required` if needed.
```typescript
if (!hasActiveSubscription(session)) {
return NextResponse.json({ error: 'Upgrade required' }, { status: 402 });
}
```
## Webhooks
Webhooks handle status updates asynchronously.
**File**: `app/api/billing/webhook/route.ts`
## Next Steps
👉 **Learn about**: [Making API Requests](./05-making-api-requests.md)