Parcourir la source

refactor: muda service de zip code coordinates para utilizar api do google

Gustavo Mantovani il y a 1 semaine
Parent
commit
75dbb0084b
2 fichiers modifiés avec 112 ajouts et 83 suppressions
  1. 106 77
      app/Services/ZipCodeCoordinatesService.php
  2. 6 6
      config/services.php

+ 106 - 77
app/Services/ZipCodeCoordinatesService.php

@@ -105,7 +105,13 @@ class ZipCodeCoordinatesService
             return $this->resolvedZipCodes[$zipCode];
         }
 
-        Log::info('ZipCodeCoordinates Brasil API lookup required', [
+        if (! $this->googleGeocodingIsConfigured()) {
+            Log::warning('ZipCodeCoordinates Google Geocoding skipped: API key is not configured');
+
+            return $this->resolvedZipCodes[$zipCode] = null;
+        }
+
+        Log::info('ZipCodeCoordinates Google Geocoding lookup required', [
             'zip_code' => $zipCode,
             'mode'     => 'single',
         ]);
@@ -141,32 +147,43 @@ class ZipCodeCoordinatesService
             return;
         }
 
-        Log::info('ZipCodeCoordinates Brasil API lookup required', [
+        if (! $this->googleGeocodingIsConfigured()) {
+            Log::warning('ZipCodeCoordinates Google Geocoding preload skipped: API key is not configured', [
+                'pending_count' => count($pending),
+            ]);
+
+            foreach ($pending as $zipCode) {
+                $this->resolvedZipCodes[$zipCode] = null;
+            }
+
+            return;
+        }
+
+        Log::info('ZipCodeCoordinates Google Geocoding lookup required', [
             'mode'             => 'preload',
             'pending_count'    => count($pending),
             'zip_codes_sample' => array_slice(array_values($pending), 0, 20),
-            'connect_timeout'  => (int) config('services.brasil_api.connect_timeout', 2),
-            'timeout'          => (int) config('services.brasil_api.timeout', 3),
+            'connect_timeout'  => (int) config('services.google_geocoding.connect_timeout', 2),
+            'timeout'          => (int) config('services.google_geocoding.timeout', 5),
             'ip_resolve'       => 'ipv4',
         ]);
 
         try {
-            $baseUrl = rtrim((string) config('services.brasil_api.base_url'), '/');
+            $baseUrl = rtrim((string) config('services.google_geocoding.base_url'), '/');
             $startedAt = microtime(true);
 
             $responses = Http::pool(fn (Pool $pool) => array_map(
                 fn (string $zipCode) => $pool
                     ->as($zipCode)
                     ->acceptJson()
-                    ->withUserAgent($this->brasilApiUserAgent())
-                    ->connectTimeout((int) config('services.brasil_api.connect_timeout', 2))
-                    ->timeout((int) config('services.brasil_api.timeout', 3))
+                    ->connectTimeout((int) config('services.google_geocoding.connect_timeout', 2))
+                    ->timeout((int) config('services.google_geocoding.timeout', 5))
                     ->withOptions($this->curlForceIpv4Options())
-                    ->get("{$baseUrl}/api/cep/v2/{$zipCode}"),
+                    ->get("{$baseUrl}/maps/api/geocode/json", $this->googleQuery($zipCode)),
                 $pending,
             ));
         } catch (Throwable $exception) {
-            Log::warning('ZipCodeCoordinates Brasil API preload failed', [
+            Log::warning('ZipCodeCoordinates Google Geocoding preload failed', [
                 'pending_count' => count($pending),
                 'elapsed_ms'    => isset($startedAt) ? round((microtime(true) - $startedAt) * 1000, 2) : null,
                 'error'         => $exception->getMessage(),
@@ -182,7 +199,7 @@ class ZipCodeCoordinatesService
                 ? $this->coordinatesFromResponse($response)
                 : null;
 
-            Log::info('ZipCodeCoordinates Brasil API preload response', [
+            Log::info('ZipCodeCoordinates Google Geocoding preload response', [
                 'zip_code'     => $zipCode,
                 'has_response' => $response instanceof Response,
                 'status'       => $response instanceof Response ? $response->status() : null,
@@ -198,39 +215,68 @@ class ZipCodeCoordinatesService
         }
     }
 
-    private function normalize(?string $zipCode): ?string
-    {
-        $zipCode = preg_replace('/\D/', '', $zipCode ?? '');
+    //
 
-        return strlen($zipCode) === 8 ? $zipCode : null;
-    }
-
-    private function restoreFromCache(string $zipCode): bool
+    private function coordinatesFromResponse(Response $response): ?array
     {
-        $cacheKey = "zip-code-coordinates:{$zipCode}";
+        if (! $response->successful()) {
+            return null;
+        }
 
-        $cached = Cache::get($cacheKey);
+        if ($response->json('status') !== 'OK') {
+            return null;
+        }
 
-        if (! is_array($cached) || ! array_key_exists('found', $cached)) {
-            return false;
+        $latitude  = $response->json('results.0.geometry.location.lat');
+        $longitude = $response->json('results.0.geometry.location.lng');
+
+        if (! is_numeric($latitude) || ! is_numeric($longitude)) {
+            return null;
         }
 
-        if (! $cached['found']) {
-            Cache::forget($cacheKey);
+        $latitude  = (float) $latitude;
+        $longitude = (float) $longitude;
 
-            Log::info('ZipCodeCoordinates negative cache ignored', [
-                'zip_code' => $zipCode,
-                'reason'   => 'retry_lookup_after_previous_failure',
-            ]);
+        if ($latitude < -90 || $latitude > 90 || $longitude < -180 || $longitude > 180) {
+            return null;
+        }
 
-            return false;
+        return compact('latitude', 'longitude');
+    }
+
+    private function curlForceIpv4Options(): array
+    {
+        if (! defined('CURLOPT_IPRESOLVE') || ! defined('CURL_IPRESOLVE_V4')) {
+            return [];
         }
 
-        $this->resolvedZipCodes[$zipCode] = $cached['found']
-            ? $cached['coordinates']
-            : null;
+        return [
+            'curl' => [
+                CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
+            ],
+        ];
+    }
 
-        return true;
+    private function googleGeocodingIsConfigured(): bool
+    {
+        return trim((string) config('services.google_geocoding.api_key')) !== '';
+    }
+
+    private function googleQuery(string $zipCode): array
+    {
+        return [
+            'components' => "postal_code:{$zipCode}|country:BR",
+            'language'   => 'pt-BR',
+            'region'     => 'br',
+            'key'        => (string) config('services.google_geocoding.api_key'),
+        ];
+    }
+
+    private function normalize(?string $zipCode): ?string
+    {
+        $zipCode = preg_replace('/\D/', '', $zipCode ?? '');
+
+        return strlen($zipCode) === 8 ? $zipCode : null;
     }
 
     private function remember(string $zipCode, ?array $coordinates): void
@@ -252,7 +298,7 @@ class ZipCodeCoordinatesService
                 'coordinates' => $coordinates,
             ],
             now()->addSeconds(
-                (int) config('services.brasil_api.cep_cache_ttl', 2592000)
+                (int) config('services.google_geocoding.cache_ttl', 2592000)
             )
         );
     }
@@ -262,27 +308,25 @@ class ZipCodeCoordinatesService
         $startedAt = microtime(true);
 
         try {
-            Log::info('ZipCodeCoordinates calling Brasil API', [
+            Log::info('ZipCodeCoordinates calling Google Geocoding', [
                 'zip_code'        => $zipCode,
-                'base_url'        => rtrim((string) config('services.brasil_api.base_url'), '/'),
-                'user_agent'      => $this->brasilApiUserAgent(),
-                'connect_timeout' => (int) config('services.brasil_api.connect_timeout', 2),
-                'timeout'         => (int) config('services.brasil_api.timeout', 3),
+                'base_url'        => rtrim((string) config('services.google_geocoding.base_url'), '/'),
+                'connect_timeout' => (int) config('services.google_geocoding.connect_timeout', 2),
+                'timeout'         => (int) config('services.google_geocoding.timeout', 5),
                 'ip_resolve'      => 'ipv4',
             ]);
 
-            $baseUrl = rtrim((string) config('services.brasil_api.base_url'), '/');
+            $baseUrl = rtrim((string) config('services.google_geocoding.base_url'), '/');
 
             $response = Http::acceptJson()
-                ->withUserAgent($this->brasilApiUserAgent())
                 ->withOptions($this->curlForceIpv4Options())
-                ->connectTimeout((int) config('services.brasil_api.connect_timeout', 2))
-                ->timeout((int) config('services.brasil_api.timeout', 3))
-                ->get("{$baseUrl}/api/cep/v2/{$zipCode}");
+                ->connectTimeout((int) config('services.google_geocoding.connect_timeout', 2))
+                ->timeout((int) config('services.google_geocoding.timeout', 5))
+                ->get("{$baseUrl}/maps/api/geocode/json", $this->googleQuery($zipCode));
 
             $coordinates = $this->coordinatesFromResponse($response);
 
-            Log::info('ZipCodeCoordinates Brasil API response', [
+            Log::info('ZipCodeCoordinates Google Geocoding response', [
                 'zip_code'    => $zipCode,
                 'status'      => $response->status(),
                 'elapsed_ms'  => round((microtime(true) - $startedAt) * 1000, 2),
@@ -293,7 +337,7 @@ class ZipCodeCoordinatesService
 
             return $coordinates;
         } catch (Throwable $exception) {
-            Log::warning('ZipCodeCoordinates Brasil API request failed', [
+            Log::warning('ZipCodeCoordinates Google Geocoding request failed', [
                 'zip_code'   => $zipCode,
                 'elapsed_ms' => round((microtime(true) - $startedAt) * 1000, 2),
                 'error'      => $exception->getMessage(),
@@ -303,46 +347,31 @@ class ZipCodeCoordinatesService
         }
     }
 
-    private function curlForceIpv4Options(): array
+    private function restoreFromCache(string $zipCode): bool
     {
-        if (! defined('CURLOPT_IPRESOLVE') || ! defined('CURL_IPRESOLVE_V4')) {
-            return [];
-        }
-
-        return [
-            'curl' => [
-                CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
-            ],
-        ];
-    }
+        $cacheKey = "zip-code-coordinates:{$zipCode}";
 
-    private function brasilApiUserAgent(): string
-    {
-        return 'insomnia/11.3.0';
-    }
+        $cached = Cache::get($cacheKey);
 
-    private function coordinatesFromResponse(Response $response): ?array
-    {
-        if (! $response->successful()) {
-            return null;
+        if (! is_array($cached) || ! array_key_exists('found', $cached)) {
+            return false;
         }
 
-        $coordinates = $response->json('location.coordinates');
+        if (! $cached['found']) {
+            Cache::forget($cacheKey);
 
-        $latitude  = is_array($coordinates) ? ($coordinates['latitude'] ?? $coordinates[1] ?? null) : null;
-        $longitude = is_array($coordinates) ? ($coordinates['longitude'] ?? $coordinates[0] ?? null) : null;
+            Log::info('ZipCodeCoordinates negative cache ignored', [
+                'zip_code' => $zipCode,
+                'reason'   => 'retry_lookup_after_previous_failure',
+            ]);
 
-        if (! is_numeric($latitude) || ! is_numeric($longitude)) {
-            return null;
+            return false;
         }
 
-        $latitude  = (float) $latitude;
-        $longitude = (float) $longitude;
-
-        if ($latitude < -90 || $latitude > 90 || $longitude < -180 || $longitude > 180) {
-            return null;
-        }
+        $this->resolvedZipCodes[$zipCode] = $cached['found']
+            ? $cached['coordinates']
+            : null;
 
-        return compact('latitude', 'longitude');
+        return true;
     }
 }

+ 6 - 6
config/services.php

@@ -40,12 +40,12 @@ return [
         'model'   => env('GEMINI_MODEL'),
     ],
 
-    'brasil_api' => [
-        'base_url'              => env('BRASIL_API_BASE_URL', 'https://brasilapi.com.br'),
-        'connect_timeout'       => env('BRASIL_API_CONNECT_TIMEOUT', 2),
-        'timeout'               => env('BRASIL_API_TIMEOUT', 3),
-        'cep_cache_ttl'         => env('BRASIL_API_CEP_CACHE_TTL', 2592000),
-        'cep_failure_cache_ttl' => env('BRASIL_API_CEP_FAILURE_CACHE_TTL', 600),
+    'google_geocoding' => [
+        'base_url'        => env('GOOGLE_GEOCODING_BASE_URL', 'https://maps.googleapis.com'),
+        'api_key'         => env('GOOGLE_GEOCODING_API_KEY'),
+        'connect_timeout' => env('GOOGLE_GEOCODING_CONNECT_TIMEOUT', 2),
+        'timeout'         => env('GOOGLE_GEOCODING_TIMEOUT', 5),
+        'cache_ttl'       => env('GOOGLE_GEOCODING_CACHE_TTL', 2592000),
     ],
 
     'support' => [