đī¸ CreatorContent.net
U
User
!
-
!
-
Manage Subscription
Manage Tokens
Storage
Media Library â
Documentation
User Dashboard
Podcasts
Podcasts
Episodes
Transcriptions
Contributors
Studio
Public Profile
Public Profiles
Blog
Event Lists
Surveys
Contact Forms
Subscribers
Notifications & Shoutouts
Development
React Test
Media Library
Help Center
Admin Dashboard
Logout
Back to Documentation
Subscription Token System
Subscription Token System
File: subscription_token_system.md
Documentation Index
Loading documentation...
# Subscription & Token System Documentation This document provides a comprehensive overview of the subscription and token system, including Laravel Cashier integration, Stripe webhooks, and token package management. ## Table of Contents 1. [Database Schema](#database-schema) 2. [Laravel Cashier Integration](#laravel-cashier-integration) 3. [Subscription System](#subscription-system) 4. [Token Package System](#token-package-system) 5. [Webhook System](#webhook-system) 6. [Usage Tracking](#usage-tracking) 7. [Admin Management](#admin-management) 8. [Frontend Integration](#frontend-integration) ## Database Schema ### Core Tables #### `plans` Table ```sql - id (Primary Key) - name (e.g., "Basic", "Pro", "Enterprise") - slug (unique identifier) - price (decimal, e.g., 9.99) - interval (month/year) - interval_count (1 for 1 month, 12 for 1 year) - stripe_plan_id (Stripe plan ID) - description (text) - is_active (boolean) - is_featured (boolean) - sort_order (integer) - timestamps ``` #### `plan_features` Table ```sql - id (Primary Key) - plan_id (Foreign Key to plans) - name (e.g., "Unlimited Projects") - value (e.g., "true", "100", "unlimited") - type (feature, limit, boolean) - icon (check, x, star) - is_highlighted (boolean) - sort_order (integer) - timestamps ``` #### `subscriptions` Table (Laravel Cashier) ```sql - id (Primary Key) - user_id (Foreign Key to users) - type (subscription type, e.g., "default") - stripe_id (unique Stripe subscription ID) - stripe_status (active, canceled, past_due, etc.) - stripe_price (Stripe price ID) - quantity (subscription quantity) - trial_ends_at (timestamp) - ends_at (timestamp) - current_period_start (timestamp) - current_period_end (timestamp) - canceled_at (timestamp) - timestamps ``` #### `subscription_items` Table (Laravel Cashier) ```sql - id (Primary Key) - subscription_id (Foreign Key to subscriptions) - stripe_id (Stripe subscription item ID) - stripe_product (Stripe product ID) - stripe_price (Stripe price ID) - quantity (integer) - timestamps ``` #### `subscription_payments` Table ```sql - id (Primary Key) - subscription_id (Foreign Key to subscriptions) - amount (decimal) - currency (3-letter code) - status (paid, failed, refunded) - stripe_charge_id (Stripe charge ID) - stripe_invoice_id (Stripe invoice ID) - paid_at (timestamp) - timestamps ``` ### Token System Tables #### `token_packages` Table ```sql - id (Primary Key) - feature_type (sms_tokens, email_tokens, transcribe_tokens) - name (e.g., "100 SMS Tokens") - amount (number of tokens) - price (decimal) - description (text) - is_active (boolean) - stripe_price_id (Stripe price ID) - timestamps ``` #### `token_purchases` Table ```sql - id (Primary Key) - user_id (Foreign Key to users) - feature_type (sms_tokens, email_tokens, transcribe_tokens) - amount_purchased (integer) - amount_used (integer, default 0) - amount_remaining (integer, calculated) - purchase_price (decimal) - currency (3-letter code) - payment_method (stripe, paypal, manual) - transaction_id (external transaction ID) - status (active, expired, refunded, canceled) - purchased_at (timestamp) - expires_at (timestamp, nullable) - notes (text) - metadata (JSON) - timestamps ``` #### `token_usage_logs` Table ```sql - id (Primary Key) - user_id (Foreign Key to users) - feature_type (sms_tokens, email_tokens, transcribe_tokens) - amount_used (integer) - description (text) - context (JSON, additional data) - timestamps ``` #### `user_usage` Table ```sql - id (Primary Key) - user_id (Foreign Key to users) - feature_type (sms_tokens, email_tokens, transcribe_tokens) - current_usage (integer) - limit (integer) - reset_date (timestamp) - timestamps ``` ## Laravel Cashier Integration ### User Model Setup The `User` model uses Laravel Cashier's `Billable` trait: ```php use Laravel\Cashier\Billable; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable, Billable; // ... other code } ``` This trait adds the following methods to the User model: - `newSubscription($name, $stripePlanId)` - Create new subscription - `subscription($name)` - Get existing subscription - `subscriptions()` - Get all subscriptions - `hasDefaultPaymentMethod()` - Check if user has payment method - `defaultPaymentMethod()` - Get default payment method - `addPaymentMethod($paymentMethod)` - Add payment method - `updateDefaultPaymentMethod($paymentMethod)` - Update default payment method ### Stripe Configuration The system uses Laravel Cashier's built-in Stripe integration: ```php // config/cashier.php return [ 'key' => env('STRIPE_KEY'), 'secret' => env('STRIPE_SECRET'), 'webhook' => [ 'secret' => env('STRIPE_WEBHOOK_SECRET'), 'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300), ], ]; ``` ## Subscription System ### Plan Management #### Creating Plans Plans are created through the admin interface and stored in the `plans` table. Each plan has: - Basic information (name, price, interval) - Stripe integration (stripe_plan_id) - Features (stored in plan_features table) #### Plan Features Features are flexible and can be: - **Boolean features**: Unlimited access (true/false) - **Limit features**: Specific amounts (e.g., "100 SMS tokens") - **Text features**: Descriptive features ### Subscription Flow #### 1. Plan Selection (`/subscription/plans`) - Users view available plans with features - Current plan is highlighted - Upgrade/downgrade options available #### 2. Subscription Creation ```php // SubscriptionController.php public function subscribe(Request $request) { $user = $request->user(); $plan = Plan::findOrFail($request->plan_id); $subscription = $user->newSubscription('default', $plan->stripe_plan_id) ->create($request->payment_method); // Update billing period $subscription->update([ 'current_period_start' => now(), 'current_period_end' => $this->calculatePeriodEnd($plan->interval, $plan->interval_count), 'stripe_status' => 'active', ]); } ``` #### 3. Subscription Management - **Cancel**: Cancel at period end or immediately - **Resume**: Reactivate canceled subscription - **Change**: Upgrade/downgrade between plans - **Payment History**: View all payments ### Usage Tracking The system tracks usage based on the user's current plan: ```php // UsageService.php public function canUseFeature(User $user, string $featureName, int $amount = 1): bool { $usage = $user->usage()->where('feature_type', $featureName)->first(); $plan = $user->getCurrentPlan(); if (!$usage || !$plan) { return false; } $feature = $plan->features()->where('name', $featureName)->first(); if (!$feature) { return false; } // Check if user has remaining usage return ($usage->current_usage + $amount) <= $usage->limit; } ``` ## Token Package System ### Token Package Types The system supports three types of token packages: 1. **SMS Tokens** (`sms_tokens`) - Used for sending SMS notifications - Tracked per message sent 2. **Email Tokens** (`email_tokens`) - Used for sending email notifications - Tracked per email sent 3. **Transcription Minutes** (`transcribe_tokens`) - Used for audio transcription - Tracked per minute of audio ### Token Purchase Flow #### 1. Package Selection Users can purchase token packages through: - Admin interface (for testing) - API endpoints (for frontend integration) - Stripe Checkout (for direct purchases) #### 2. Purchase Creation ```php // TokenPurchaseController.php public function purchase(Request $request) { $user = $request->user(); $package = TokenPackage::findOrFail($request->package_id); $purchase = TokenPurchase::create([ 'user_id' => $user->id, 'feature_type' => $package->feature_type, 'amount_purchased' => $package->amount, 'amount_remaining' => $package->amount, 'purchase_price' => $package->price, 'payment_method' => 'stripe', 'transaction_id' => $request->transaction_id, 'status' => 'active', 'purchased_at' => now(), ]); // Update user usage limits $this->updateUserUsageForPurchase($user, $package); } ``` #### 3. Token Usage ```php // UsageService.php public function useFeature(User $user, string $featureName, int $amount = 1): bool { if (!$this->canUseFeature($user, $featureName, $amount)) { return false; } // Find available token purchase $purchase = $user->tokenPurchases() ->where('feature_type', $featureName) ->where('status', 'active') ->where('amount_remaining', '>=', $amount) ->orderBy('purchased_at') ->first(); if (!$purchase) { return false; } // Update purchase $purchase->update([ 'amount_used' => $purchase->amount_used + $amount, 'amount_remaining' => $purchase->amount_remaining - $amount, ]); // Log usage TokenUsageLog::create([ 'user_id' => $user->id, 'feature_type' => $featureName, 'amount_used' => $amount, 'description' => 'Feature usage', ]); return true; } ``` ## Webhook System ### Stripe Webhook Integration The system uses Laravel Cashier's webhook controller with custom handlers: ```php // WebhookController.php class WebhookController extends CashierWebhookController { public function handleCustomerSubscriptionCreated($payload) { $subscription = \Laravel\Cashier\Subscription::where('stripe_id', $payload['data']['object']['id'])->first(); if ($subscription) { $subscription->update([ 'stripe_status' => $payload['data']['object']['status'], 'current_period_start' => date('Y-m-d H:i:s', $payload['data']['object']['current_period_start']), 'current_period_end' => date('Y-m-d H:i:s', $payload['data']['object']['current_period_end']), ]); // Update user usage for new plan $user = $subscription->owner; $usageService = app(\App\Services\UsageService::class); $usageService->updateUserUsageForPlanChange($user); } } } ``` ### Webhook Events Handled 1. **Customer Subscription Created** - Updates subscription status - Initializes user usage limits 2. **Customer Subscription Updated** - Updates subscription details - Handles plan changes 3. **Customer Subscription Deleted** - Marks subscription as canceled - Updates user access 4. **Invoice Payment Succeeded** - Records successful payment - Updates subscription status 5. **Invoice Payment Failed** - Records failed payment - Updates subscription status 6. **Charge Refunded** - Marks payment as refunded - Handles token refunds if applicable ### Webhook Configuration ```php // routes/api.php Route::post('stripe/webhook', [WebhookController::class, 'handleWebhook']) ->name('cashier.webhook'); ``` ## Admin Management ### Plan Management (`/admin/plans`) #### Features - Create, edit, and delete plans - Manage plan features - Set Stripe plan IDs - Configure pricing and intervals - Set featured and default plans #### Plan Creation Process 1. Create plan in admin interface 2. Set basic information (name, price, interval) 3. Add features (unlimited, limits, boolean) 4. Create corresponding Stripe product/price 5. Link Stripe plan ID to local plan ### Token Package Management (`/admin/token-packages`) #### Features - Create and manage token packages - Set pricing and token amounts - Link to Stripe prices - Validate Stripe integration - View package statistics #### Package Creation Process 1. Select feature type (SMS, Email, Transcription) 2. Set package name and token amount 3. Set price 4. Create Stripe price (optional) 5. Activate package #### Stripe Integration ```javascript // Admin interface includes Stripe validation async function validateAllPackages() { const response = await fetch('/api/admin/token-packages/validate-stripe', { headers: { 'Authorization': `Bearer ${appState.apiToken}`, } }); const data = await response.json(); stripeValidation = data.validation; displayTokenPackages(); // Refresh display with validation results } ``` ## Frontend Integration ### Subscription Pages #### Plans Page (`/subscription/plans`) ```javascript // Load plans and current subscription async function loadPlans() { const response = await fetch('/api/subscriptions', { headers: { 'Authorization': `Bearer ${appState.apiToken}`, } }); const data = await response.json(); displayPlans(data.plans, data.current_subscription, data.current_plan); } ``` #### Plan Display - Shows all available plans - Highlights current plan - Displays plan features - Provides upgrade/downgrade options ### Checkout Integration #### Stripe Elements Integration ```javascript // Initialize Stripe const stripe = Stripe(STRIPE_PUBLIC_KEY); const elements = stripe.elements(); // Create payment method const { paymentMethod, error } = await stripe.createPaymentMethod({ type: 'card', card: cardElement, }); // Submit subscription const response = await fetch('/api/subscriptions/subscribe', { method: 'POST', headers: { 'Authorization': `Bearer ${appState.apiToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ plan_id: selectedPlanId, payment_method: paymentMethod.id, }), }); ``` ### Usage Display #### Dashboard Integration ```javascript // Load usage data async function loadUsageData() { const response = await fetch('/api/usage', { headers: { 'Authorization': `Bearer ${appState.apiToken}`, } }); const data = await response.json(); displayUsage(data.usage); } ``` #### Usage Display - Shows current usage vs. limits - Displays token balances - Provides purchase options - Shows usage history ## Usage Tracking System ### Feature Usage The system tracks usage for various features: ```php // UsageService.php public function useFeature(User $user, string $featureName, int $amount = 1): bool { // Check if user can use feature if (!$this->canUseFeature($user, $featureName, $amount)) { return false; } // Use tokens from purchases $purchase = $this->findAvailableTokenPurchase($user, $featureName, $amount); if ($purchase) { $this->useTokensFromPurchase($purchase, $amount); } // Log usage $this->logUsage($user, $featureName, $amount); return true; } ``` ### Usage Limits Usage limits are determined by: 1. **Plan Features**: Base limits from subscription plan 2. **Token Purchases**: Additional tokens purchased separately 3. **Usage Period**: Monthly/yearly reset cycles ### Usage Calculation ```php public function getUserUsageSummary(User $user): array { $summary = []; foreach (['sms_tokens', 'email_tokens', 'transcribe_tokens'] as $feature) { $usage = $user->usage()->where('feature_type', $feature)->first(); $purchases = $user->tokenPurchases() ->where('feature_type', $feature) ->where('status', 'active') ->get(); $totalLimit = $usage ? $usage->limit : 0; $totalUsed = $usage ? $usage->current_usage : 0; $purchasedTokens = $purchases->sum('amount_remaining'); $summary[$feature] = [ 'limit' => $totalLimit, 'used' => $totalUsed, 'purchased' => $purchasedTokens, 'available' => $totalLimit + $purchasedTokens - $totalUsed, ]; } return $summary; } ``` ## Security & Validation ### Webhook Security - Stripe signature verification - Webhook tolerance settings - Secure endpoint configuration ### Payment Security - PCI compliance through Stripe - Secure payment method storage - Token-based authentication ### Usage Validation - Server-side usage checks - Rate limiting - Fraud detection ## Monitoring & Analytics ### Subscription Metrics - Active subscriptions - Revenue tracking - Churn analysis - Plan popularity ### Usage Analytics - Feature usage patterns - Token consumption rates - User behavior analysis - Performance metrics --- *This documentation covers the complete subscription and token system. For implementation details, refer to the specific controller and service files.*
0
đ Page Notes
+ Add New
Add New Note
Type
âšī¸ Info
đ Bug
⨠Feature Request
đĄ Improvement
â Missing Feature
đ¨ Design Changes
Title (optional)
Note Content
đ Add Note