Files
zemailnator/routes/web.php
idevakk 5ee5c5b8dc feat(billing): implement Polar customer portal integration
- Add comprehensive billing page with current subscription display and transaction history
   - Integrate Polar.sh customer portal for subscription management
   - Fix Polar API endpoint from /customer-portal to /customer-sessions
   - Use Polar's direct customer_portal_url response for seamless redirect
   - Add responsive button layout with cursor-pointer styling
   - Implement human-readable timestamps using diffForHumans()
   - Add subscription sync functionality with 30-minute recheck window
   - Include subscription cancellation with modal confirmation
   - Support activation key provider with pending activation display
   - Add proper error handling and user feedback messages
2025-12-06 02:03:56 -08:00

191 lines
7.4 KiB
PHP

<?php
use App\Http\Controllers\AppController;
// DEBUG: Test route to check PolarProvider
Route::get('/debug-polar', function () {
try {
$provider = new \App\Services\Payments\Providers\PolarProvider;
return response()->json([
'status' => 'success',
'provider_class' => get_class($provider),
'is_active' => $provider->isActive(),
'config' => $provider->getConfiguration(),
'sandbox' => $provider->config['sandbox'] ?? 'unknown',
'timestamp' => '2025-12-04-17-15-00',
]);
} catch (\Exception $e) {
return response()->json([
'status' => 'error',
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
}
});
use App\Http\Controllers\ImpersonationController;
use App\Http\Controllers\WebhookController;
use App\Http\Middleware\CheckPageSlug;
use App\Http\Middleware\CheckUserBanned;
use App\Livewire\AddOn;
use App\Livewire\Blog;
use App\Livewire\Dashboard\Bulk;
use App\Livewire\Dashboard\BulkGmail;
use App\Livewire\Dashboard\Dashboard;
use App\Livewire\Dashboard\Mailbox\Inbox;
use App\Livewire\Dashboard\Support;
use App\Livewire\Frontend\Mailbox;
use App\Livewire\Home;
use App\Livewire\ListBlog;
use App\Livewire\Page;
use App\Livewire\Settings\Appearance;
use App\Livewire\Settings\Billing;
use App\Livewire\Settings\Password;
use App\Livewire\Settings\Profile;
use App\Models\Email;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
Route::get('/', Home::class)->name('home');
Route::get('/mailbox', Mailbox::class)->name('mailbox');
Route::get('/mailbox/{email?}', [AppController::class, 'mailbox'])->name('mailboxFromURL');
Route::get('/switch/{email}', [AppController::class, 'switch'])->name('switch');
Route::get('/switchP/{email}', [AppController::class, 'switchP'])->name('switchP');
Route::get('/delete/{email?}', [AppController::class, 'delete'])->name('delete');
Route::get('/deleteP/{email?}', [AppController::class, 'deleteP'])->name('deleteP');
Route::get('locale/{locale}', [AppController::class, 'locale'])->name('locale');
Route::get('/blog', ListBlog::class)->name('list-blog');
Route::get('/blog/{slug}', Blog::class)->name('blog');
Route::post('/sync', function (Request $request) {
try {
if (config('app.auto_fetch_mail')) {
Email::fetchProcessStoreEmail();
}
} catch (Exception $e) {
Log::error($e->getMessage());
}
return response()->noContent();
});
Route::get('disposable-email', AddOn::class)->name('disposable-email');
Route::get('disposable-gmail', AddOn::class)->name('disposable-gmail');
Route::get('disposable-outlook', AddOn::class)->name('disposable-outlook');
Route::get('disposable-yahoo', AddOn::class)->name('disposable-yahoo');
Route::get('gmailnator', AddOn::class)->name('gmailnator');
Route::get('emailnator', AddOn::class)->name('emailnator');
Route::get('temp-gmail', AddOn::class)->name('temp-gmail');
Route::middleware(['auth', 'verified', CheckUserBanned::class])->group(function (): void {
Route::get('dashboard', Dashboard::class)->name('dashboard');
Route::get('dashboard/generate-premium-email', Inbox::class)->name('dashboard.premium');
Route::get('dashboard/generate-10minute-email', Dashboard::class)->name('dashboard.10minute');
Route::get('dashboard/bulk-email-generator', Bulk::class)->name('dashboard.bulk');
Route::get('dashboard/bulk-gmail-generator', BulkGmail::class)->name('dashboard.bulkGmail');
Route::get('dashboard/compose-email', Dashboard::class)->name('dashboard.compose');
Route::get('dashboard/support', Support::class)->name('dashboard.support');
// LEGACY: Old Stripe Cashier checkout route (deprecated - use unified payment system)
Route::get('checkout/{plan}', function ($pricing_id) {
$plans = config('app.plans');
$pricingData = [];
foreach ($plans as $plan) {
$pricingData[] = $plan['pricing_id'];
}
if (in_array($pricing_id, $pricingData)) {
return auth()->user()
->newSubscription('default', $pricing_id)
->allowPromotionCodes()
->checkout([
'billing_address_collection' => 'required',
'success_url' => route('checkout.success'),
'cancel_url' => route('checkout.cancel'),
]);
}
abort(404);
})->name('checkout');
// LEGACY: Payment status routes (used by both legacy and unified systems)
Route::get('dashboard/success', [Dashboard::class, 'paymentStatus'])->name('checkout.success')->defaults('status', 'success');
Route::get('dashboard/cancel', [Dashboard::class, 'paymentStatus'])->name('checkout.cancel')->defaults('status', 'cancel');
Route::get('dashboard/billing', fn () => auth()->user()->redirectToBillingPortal(route('dashboard')))->name('billing');
Route::get('0xdash/slink', function (Request $request) {
$validUser = 'admin';
$validPass = 'admin@9608'; // 🔐 Change this to something secure
if (! isset($_SERVER['PHP_AUTH_USER']) ||
Request::server('PHP_AUTH_USER') !== $validUser ||
Request::server('PHP_AUTH_PW') !== $validPass) {
header('WWW-Authenticate: Basic realm="Restricted Area"');
header('HTTP/1.0 401 Unauthorized');
echo 'Unauthorized';
exit;
}
Artisan::call('storage:link');
$output = Artisan::output();
return response()->json([
'message' => trim($output),
]);
})->name('storageLink');
Route::get('0xdash/scache', function (Request $request) {
$validUser = 'admin';
$validPass = 'admin@9608'; // 🔐 Change this to something secure
if (! isset($_SERVER['PHP_AUTH_USER']) ||
Request::server('PHP_AUTH_USER') !== $validUser ||
Request::server('PHP_AUTH_PW') !== $validPass) {
header('WWW-Authenticate: Basic realm="Restricted Area"');
header('HTTP/1.0 401 Unauthorized');
echo 'Unauthorized';
exit;
}
Artisan::call('cache:clear');
$output = Artisan::output();
return response()->json([
'message' => trim($output),
]);
})->name('cacheClear');
// Impersonation Routes
Route::prefix('impersonation')->name('impersonation.')->group(function (): void {
Route::post('/stop', [ImpersonationController::class, 'stop'])->name('stop');
Route::get('/status', [ImpersonationController::class, 'status'])->name('status');
Route::get('/start/{user}', [ImpersonationController::class, 'start'])->name('start');
});
});
Route::middleware(['auth'])->group(function (): void {
Route::redirect('settings', 'settings/profile');
Route::get('settings/profile', Profile::class)->name('settings.profile');
Route::get('settings/billing', Billing::class)->name('settings.billing');
Route::get('settings/password', Password::class)->name('settings.password');
Route::get('settings/appearance', Appearance::class)->name('settings.appearance');
});
Route::post('/webhook/oxapay', [WebhookController::class, 'oxapay'])->name('webhook.oxapay');
// Unified Payment System Routes
require __DIR__.'/payment.php';
require __DIR__.'/auth.php';
Route::get('{slug}', Page::class)->where('slug', '.*')->name('page')->middleware(CheckPageSlug::class);