toDateString(); return CurrencyRate::where('currency_code', $currency) ->where('date', '<=', $date) ->orderByDesc('date') ->first() ?->exchange_rate; } /** * Actualiza las tasas de cambio de las 10 divisas. */ public function updateExchangeRates() { foreach ($this->providers as $provider) { $this->fetchAndStoreRates($provider); } } /** * Obtiene tasas de un proveedor y las guarda. */ protected function fetchAndStoreRates(string $provider) { $rates = match ($provider) { 'banxico' => $this->fetchBanxicoRates(), 'fixer' => $this->fetchFixerRates(), default => [] }; foreach ($rates as $currency => $rate) { CurrencyRate::updateOrCreate( ['currency_code' => $currency, 'date' => Carbon::now()->toDateString(), 'source' => $provider], ['exchange_rate' => $rate] ); } } /** * Obtiene tasas de Banxico (solo las divisas disponibles en su API). */ protected function fetchBanxicoRates(): array { $apiKey = Setting::getValue('banxico.api_key'); $url = "https://www.banxico.org.mx/SieAPIRest/service/v1/series/SF43718​,SF46410​,SF46407​,SF46406​,SF60632​/datos/oportuno/?token={$apiKey}"; $response = Http::get($url); if ($response->successful()) { $data = $response->json(); return [ 'USD' => (float) ($data['bmx']['series'][0]['datos'][0]['dato'] ?? null), 'EUR' => (float) ($data['bmx']['series'][1]['datos'][0]['dato'] ?? null), 'GBP' => (float) ($data['bmx']['series'][2]['datos'][0]['dato'] ?? null), 'JPY' => (float) ($data['bmx']['series'][3]['datos'][0]['dato'] ?? null), 'CAD' => (float) ($data['bmx']['series'][4]['datos'][0]['dato'] ?? null), ]; } return []; } /** * Obtiene tasas de Fixer.io. */ protected function fetchFixerRates(): array { $apiKey = Setting::getValue('fixer.api_key'); $url = "http://data.fixer.io/api/latest?access_key={$apiKey}&symbols=USD,EUR,GBP,JPY,CAD,AUD,CHF,CNY,GTQ,MXN"; $response = Http::get($url); return $response->successful() ? $response->json()['rates'] ?? [] : []; } }