feat: implement comprehensive multi-provider payment processing system

- Add unified payment provider architecture with contract-based design
  - Implement 6 payment providers: Stripe, Lemon Squeezy, Polar, Oxapay, Crypto, Activation Keys
  - Create subscription management with lifecycle handling (create, cancel, pause, resume, update)
  - Add coupon system with usage tracking and trial extensions
  - Build Filament admin resources for payment providers, subscriptions, coupons, and trials
  - Implement payment orchestration service with provider registry and configuration management
  - Add comprehensive payment logging and webhook handling for all providers
  - Create customer analytics dashboard with revenue, churn, and lifetime value metrics
  - Add subscription migration service for provider switching
  - Include extensive test coverage for all payment functionality
This commit is contained in:
idevakk
2025-11-19 09:37:00 -08:00
parent 0560016f33
commit 27ac13948c
83 changed files with 15613 additions and 103 deletions

View File

@@ -0,0 +1,96 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TrialExtension extends Model
{
protected $fillable = [
'subscription_id',
'user_id',
'extension_days',
'reason',
'extension_type',
'original_trial_ends_at',
'new_trial_ends_at',
'granted_at',
'granted_by_admin_id',
'metadata',
];
protected $casts = [
'original_trial_ends_at' => 'datetime',
'new_trial_ends_at' => 'datetime',
'granted_at' => 'datetime',
'metadata' => 'array',
];
protected $dates = [
'original_trial_ends_at',
'new_trial_ends_at',
'granted_at',
];
/**
* Relationships
*/
public function subscription()
{
return $this->belongsTo(Subscription::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function grantedByAdmin()
{
return $this->belongsTo(User::class, 'granted_by_admin_id');
}
/**
* Get human-readable extension type
*/
public function getExtensionTypeLabelAttribute(): string
{
return [
'manual' => 'Manual Grant',
'automatic' => 'Automatic Extension',
'compensation' => 'Compensation',
][$this->extension_type] ?? ucfirst($this->extension_type);
}
/**
* Scope: By extension type
*/
public function scopeByType($query, string $type)
{
return $query->where('extension_type', $type);
}
/**
* Scope: By user
*/
public function scopeByUser($query, $userId)
{
return $query->where('user_id', $userId);
}
/**
* Scope: Granted by admin
*/
public function scopeGrantedBy($query, $adminId)
{
return $query->where('granted_by_admin_id', $adminId);
}
/**
* Scope: Within date range
*/
public function scopeBetweenDates($query, $startDate, $endDate)
{
return $query->whereBetween('granted_at', [$startDate, $endDate]);
}
}