'whsec_test_secret']); } public function test_handle_payment_intent_succeeded_creates_event_package(): void { $tenant = \App\Models\Tenant::factory()->create(); $event = \App\Models\Event::factory()->create(['tenant_id' => $tenant->id]); $package = Package::factory()->create(['type' => 'endcustomer']); $payload = [ 'id' => 'evt_test', 'type' => 'payment_intent.succeeded', 'data' => [ 'object' => [ 'id' => 'pi_test', 'metadata' => [ 'type' => 'endcustomer_event', 'tenant_id' => (string) $tenant->id, 'event_id' => (string) $event->id, 'package_id' => (string) $package->id, ], ], ], ]; $sigHeader = 't=12345,v1=' . base64_encode(hash_hmac('sha256', json_encode($payload), 'whsec_test_secret', true)); $response = $this->postJson('/api/v1/stripe/webhook', $payload, [ 'Stripe-Signature' => $sigHeader, ]); $response->assertStatus(200); $this->assertDatabaseHas('package_purchases', [ 'package_id' => $package->id, 'tenant_id' => $tenant->id, 'event_id' => $event->id, 'type' => 'endcustomer_event', 'provider_id' => 'pi_test', ]); $this->assertDatabaseHas('event_packages', [ 'event_id' => $event->id, 'package_id' => $package->id, ]); } public function test_handle_invoice_paid_renews_tenant_package(): void { $tenant = \App\Models\Tenant::factory()->create(); $package = Package::factory()->create(['type' => 'reseller']); $payload = [ 'id' => 'evt_test', 'type' => 'invoice.paid', 'data' => [ 'object' => [ 'subscription' => 'sub_test', 'metadata' => [ 'type' => 'reseller_subscription', 'tenant_id' => (string) $tenant->id, 'package_id' => (string) $package->id, ], ], ], ]; $sigHeader = 't=12345,v1=' . base64_encode(hash_hmac('sha256', json_encode($payload), 'whsec_test_secret', true)); $response = $this->postJson('/api/v1/stripe/webhook', $payload, [ 'Stripe-Signature' => $sigHeader, ]); $response->assertStatus(200); $this->assertDatabaseHas('package_purchases', [ 'package_id' => $package->id, 'tenant_id' => $tenant->id, 'type' => 'reseller_subscription', ]); $tenantPackage = TenantPackage::where('tenant_id', $tenant->id)->first(); $this->assertNotNull($tenantPackage); $this->assertTrue($tenantPackage->expires_at->isFuture()); } public function test_webhook_rejects_invalid_signature(): void { $payload = ['type' => 'invalid']; $sigHeader = 'invalid'; $response = $this->postJson('/api/v1/stripe/webhook', $payload, [ 'Stripe-Signature' => $sigHeader, ]); $response->assertStatus(400); } }