|
|
@@ -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;
|
|
|
}
|
|
|
}
|