true, 'customdomain.server_ip' => $this->serverIp, 'customdomain.ssl_api_url' => 'https://domains.ladill.com/api', 'customdomain.ssl_api_key' => 'merchant-ssl-key', 'customdomain.callback_secret' => 'shared-secret', ]); } private function storefront(?User $owner = null): QrCode { $owner ??= User::factory()->create(['public_id' => 'usr_'.uniqid()]); return QrCode::create([ 'user_id' => $owner->id, 'short_code' => 'sc'.uniqid(), 'type' => QrCode::TYPE_SHOP, 'label' => 'My Shop', 'is_active' => true, ]); } private function fakeDns(array $ips): void { $this->app->bind(DnsResolver::class, fn () => new class($ips) extends DnsResolver { public function __construct(private array $ips) {} public function aRecords(string $host): array { return $this->ips; } }); } public function test_verify_requests_certificate_when_dns_points_to_app(): void { Http::fake(['*/ssl/certificates' => Http::response(['status' => 'pending'], 202)]); $this->fakeDns([$this->serverIp]); $store = $this->storefront(); $service = app(CustomDomainService::class); $domain = $service->attach($store, 'brand.com', true); [$ok] = $service->verifyAndProvision($domain->fresh()); $this->assertTrue($ok); $this->assertNotNull($domain->fresh()->dns_verified_at); Http::assertSent(fn ($r) => str_contains($r->url(), '/ssl/certificates') && $r['host'] === 'brand.com' && $r['target'] === 'app'); } public function test_verify_fails_when_dns_not_pointing(): void { $this->fakeDns(['1.2.3.4']); $store = $this->storefront(); $service = app(CustomDomainService::class); $domain = $service->attach($store, 'brand.com', true); [$ok, $msg] = $service->verifyAndProvision($domain->fresh()); $this->assertFalse($ok); $this->assertStringContainsString('DNS', $msg); $this->assertNull($domain->fresh()->dns_verified_at); } public function test_signed_callback_marks_domain_live_and_resolves(): void { $store = $this->storefront(); $domain = app(CustomDomainService::class)->attach($store, 'brand.com', true); $payload = json_encode(['event' => 'ssl.active', 'data' => [ 'host' => 'brand.com', 'status' => 'active', 'expires_at' => now()->addDays(89)->toIso8601String(), ]], JSON_UNESCAPED_SLASHES); $sig = hash_hmac('sha256', $payload, 'shared-secret'); $this->call('POST', '/api/ssl-callback', [], [], [], [ 'HTTP_X-Ladill-Signature' => $sig, 'CONTENT_TYPE' => 'application/json', ], $payload)->assertOk(); $domain->refresh(); $this->assertTrue($domain->isLive()); $resolved = app(CustomDomainService::class)->resolveStorefront('www.brand.com'); $this->assertSame($store->id, $resolved?->id); } public function test_callback_rejects_bad_signature(): void { app(CustomDomainService::class)->attach($this->storefront(), 'brand.com', true); $payload = json_encode(['data' => ['host' => 'brand.com', 'status' => 'active']]); $this->call('POST', '/api/ssl-callback', [], [], [], [ 'HTTP_X-Ladill-Signature' => 'wrong', 'CONTENT_TYPE' => 'application/json', ], $payload)->assertStatus(401); } public function test_store_requires_storefront_ownership(): void { $store = $this->storefront(); $intruder = User::factory()->create(['public_id' => 'usr_'.uniqid()]); $this->withoutMiddleware(\App\Http\Middleware\EnsurePlatformSession::class); $this->actingAs($intruder) ->post(route('merchant.custom-domain.store', $store), ['host' => 'brand.com']) ->assertForbidden(); } }