Fix tenant event form package selector so it no longer renders empty-value options, handles loading/empty
states, and pulls data from the authenticated /api/v1/tenant/packages endpoint.
(resources/js/admin/pages/EventFormPage.tsx, resources/js/admin/api.ts)
- Harden tenant-admin auth flow: prevent PKCE state loss, scope out StrictMode double-processing, add SPA
routes for /event-admin/login and /event-admin/logout, and tighten token/session clearing semantics (resources/js/admin/auth/{context,tokens}.tsx, resources/js/admin/pages/{AuthCallbackPage,LogoutPage}.tsx,
resources/js/admin/router.tsx, routes/web.php)
This commit is contained in:
@@ -3,10 +3,11 @@
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PackagePurchase;
|
||||
use App\Models\EventPackage;
|
||||
use App\Models\PackagePurchase;
|
||||
use App\Models\TenantPackage;
|
||||
use App\Models\User;
|
||||
use App\Services\Checkout\CheckoutWebhookService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -15,6 +16,10 @@ use Stripe\Webhook;
|
||||
|
||||
class StripeWebhookController extends Controller
|
||||
{
|
||||
public function __construct(private CheckoutWebhookService $checkoutWebhooks)
|
||||
{
|
||||
}
|
||||
|
||||
public function handleWebhook(Request $request)
|
||||
{
|
||||
$payload = $request->getContent();
|
||||
@@ -23,7 +28,9 @@ class StripeWebhookController extends Controller
|
||||
|
||||
try {
|
||||
$event = Webhook::constructEvent(
|
||||
$payload, $sigHeader, $endpointSecret
|
||||
$payload,
|
||||
$sigHeader,
|
||||
$endpointSecret
|
||||
);
|
||||
} catch (SignatureVerificationException $e) {
|
||||
return response()->json(['error' => 'Invalid signature'], 400);
|
||||
@@ -31,54 +38,81 @@ class StripeWebhookController extends Controller
|
||||
return response()->json(['error' => 'Invalid payload'], 400);
|
||||
}
|
||||
|
||||
// Handle the event
|
||||
switch ($event['type']) {
|
||||
$eventArray = method_exists($event, 'toArray') ? $event->toArray() : (array) $event;
|
||||
|
||||
if ($this->checkoutWebhooks->handleStripeEvent($eventArray)) {
|
||||
return response()->json(['status' => 'success'], 200);
|
||||
}
|
||||
|
||||
// Legacy handlers for legacy marketing checkout
|
||||
return $this->handleLegacyEvent($eventArray);
|
||||
}
|
||||
|
||||
private function handleLegacyEvent(array $event)
|
||||
{
|
||||
$type = $event['type'] ?? null;
|
||||
|
||||
switch ($type) {
|
||||
case 'payment_intent.succeeded':
|
||||
$paymentIntent = $event['data']['object'];
|
||||
$paymentIntent = $event['data']['object'] ?? [];
|
||||
$this->handlePaymentIntentSucceeded($paymentIntent);
|
||||
break;
|
||||
|
||||
case 'invoice.paid':
|
||||
$invoice = $event['data']['object'];
|
||||
$invoice = $event['data']['object'] ?? [];
|
||||
$this->handleInvoicePaid($invoice);
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::info('Unhandled Stripe event', ['type' => $event['type']]);
|
||||
Log::info('Unhandled Stripe event', ['type' => $type]);
|
||||
}
|
||||
|
||||
return response()->json(['status' => 'success'], 200);
|
||||
}
|
||||
|
||||
private function handlePaymentIntentSucceeded(array $paymentIntent)
|
||||
private function handlePaymentIntentSucceeded(array $paymentIntent): void
|
||||
{
|
||||
$metadata = $paymentIntent['metadata'];
|
||||
$packageId = $metadata['package_id'];
|
||||
$type = $metadata['type'];
|
||||
$metadata = $paymentIntent['metadata'] ?? [];
|
||||
$packageId = $metadata['package_id'] ?? null;
|
||||
$type = $metadata['type'] ?? null;
|
||||
|
||||
if (! $packageId || ! $type) {
|
||||
Log::warning('Stripe intent missing metadata payload', ['metadata' => $metadata]);
|
||||
return;
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($paymentIntent, $metadata, $packageId, $type) {
|
||||
// Create purchase record
|
||||
$purchase = PackagePurchase::create([
|
||||
'package_id' => $packageId,
|
||||
'type' => $type,
|
||||
'provider_id' => 'stripe',
|
||||
'transaction_id' => $paymentIntent['id'],
|
||||
'price' => $paymentIntent['amount_received'] / 100,
|
||||
'transaction_id' => $paymentIntent['id'] ?? null,
|
||||
'price' => isset($paymentIntent['amount_received'])
|
||||
? $paymentIntent['amount_received'] / 100
|
||||
: 0,
|
||||
'metadata' => $metadata,
|
||||
]);
|
||||
|
||||
if ($type === 'endcustomer_event') {
|
||||
$eventId = $metadata['event_id'];
|
||||
$eventId = $metadata['event_id'] ?? null;
|
||||
if (! $eventId) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventPackage::create([
|
||||
'event_id' => $eventId,
|
||||
'package_id' => $packageId,
|
||||
'package_purchase_id' => $purchase->id,
|
||||
'used_photos' => 0,
|
||||
'used_guests' => 0,
|
||||
'expires_at' => now()->addDays(30), // Default, or from package
|
||||
'expires_at' => now()->addDays(30),
|
||||
]);
|
||||
} elseif ($type === 'reseller_subscription') {
|
||||
$tenantId = $metadata['tenant_id'];
|
||||
$tenantId = $metadata['tenant_id'] ?? null;
|
||||
if (! $tenantId) {
|
||||
return;
|
||||
}
|
||||
|
||||
TenantPackage::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'package_id' => $packageId,
|
||||
@@ -88,59 +122,60 @@ class StripeWebhookController extends Controller
|
||||
'expires_at' => now()->addYear(),
|
||||
]);
|
||||
|
||||
$user = User::find($metadata['user_id']);
|
||||
if ($user) {
|
||||
$user->update(['role' => 'tenant_admin']);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function handleInvoicePaid(array $invoice)
|
||||
{
|
||||
$subscription = $invoice['subscription'];
|
||||
$metadata = $subscription['metadata'] ?? [];
|
||||
|
||||
if (isset($metadata['tenant_id'])) {
|
||||
$tenantId = $metadata['tenant_id'];
|
||||
$packageId = $metadata['package_id'];
|
||||
|
||||
// Renew or create tenant package
|
||||
$tenantPackage = TenantPackage::where('tenant_id', $tenantId)
|
||||
->where('package_id', $packageId)
|
||||
->where('stripe_subscription_id', $subscription)
|
||||
->first();
|
||||
|
||||
if ($tenantPackage) {
|
||||
$tenantPackage->update([
|
||||
'active' => true,
|
||||
'expires_at' => now()->addYear(),
|
||||
]);
|
||||
} else {
|
||||
TenantPackage::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'package_id' => $packageId,
|
||||
'stripe_subscription_id' => $subscription,
|
||||
'used_events' => 0,
|
||||
'active' => true,
|
||||
'expires_at' => now()->addYear(),
|
||||
]);
|
||||
|
||||
$user = User::find($metadata['user_id'] ?? null);
|
||||
if ($user) {
|
||||
$user->update(['role' => 'tenant_admin']);
|
||||
}
|
||||
}
|
||||
|
||||
// Create purchase record
|
||||
PackagePurchase::create([
|
||||
'package_id' => $packageId,
|
||||
'type' => 'reseller_subscription',
|
||||
'provider_id' => 'stripe',
|
||||
'transaction_id' => $invoice['id'],
|
||||
'price' => $invoice['amount_paid'] / 100,
|
||||
'metadata' => $metadata,
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private function handleInvoicePaid(array $invoice): void
|
||||
{
|
||||
$subscription = $invoice['subscription'] ?? null;
|
||||
$metadata = $subscription['metadata'] ?? [];
|
||||
|
||||
if (! isset($metadata['tenant_id'], $metadata['package_id'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tenantId = $metadata['tenant_id'];
|
||||
$packageId = $metadata['package_id'];
|
||||
|
||||
$tenantPackage = TenantPackage::where('tenant_id', $tenantId)
|
||||
->where('package_id', $packageId)
|
||||
->where('stripe_subscription_id', $subscription)
|
||||
->first();
|
||||
|
||||
if ($tenantPackage) {
|
||||
$tenantPackage->update([
|
||||
'active' => true,
|
||||
'expires_at' => now()->addYear(),
|
||||
]);
|
||||
} else {
|
||||
TenantPackage::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'package_id' => $packageId,
|
||||
'stripe_subscription_id' => $subscription,
|
||||
'used_events' => 0,
|
||||
'active' => true,
|
||||
'expires_at' => now()->addYear(),
|
||||
]);
|
||||
|
||||
$user = User::find($metadata['user_id'] ?? null);
|
||||
if ($user) {
|
||||
$user->update(['role' => 'tenant_admin']);
|
||||
}
|
||||
}
|
||||
|
||||
PackagePurchase::create([
|
||||
'package_id' => $packageId,
|
||||
'type' => 'reseller_subscription',
|
||||
'provider_id' => 'stripe',
|
||||
'transaction_id' => $invoice['id'] ?? null,
|
||||
'price' => isset($invoice['amount_paid']) ? $invoice['amount_paid'] / 100 : 0,
|
||||
'metadata' => $metadata,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user