apiKey = ChatConfig::get('gemini_api_key', ''); } /** * Extrae datos de pago de una imagen de comprobante. * * @param string $base64 Imagen en base64 * @param string $mimeType MIME type (image/jpeg, image/png, etc.) * @return array|null ['banco', 'valor', 'referencia', 'fecha', 'hora', 'remitente'] o null */ public function extraerPago(string $base64, string $mimeType): ?array { if (! $this->apiKey) { Log::warning('[Gemini Vision] No hay API key configurada.'); return null; } $prompt = $this->buildPrompt(); try { $response = Http::withHeaders(['Content-Type' => 'application/json']) ->timeout(15) ->post("{$this->apiUrl}?key={$this->apiKey}", [ 'contents' => [[ 'parts' => [ ['text' => $prompt], ['inline_data' => ['mime_type' => $mimeType, 'data' => $base64]], ], ]], 'generationConfig' => [ 'temperature' => 0.1, 'maxOutputTokens' => 200, ], ]); if (! $response->successful()) { Log::warning('[Gemini Vision] API error: ' . $response->body()); return null; } $text = $response->json('candidates.0.content.parts.0.text', ''); return $this->parseRespuesta($text); } catch (\Throwable $e) { Log::error('[Gemini Vision] Excepcion: ' . $e->getMessage()); return null; } } private function buildPrompt(): string { return << $json['banco'] ?? null, 'valor' => $json['valor'] ?? null, 'referencia' => $json['referencia'] ?? null, 'fecha' => $json['fecha'] ?? null, 'hora' => $json['hora'] ?? null, 'remitente' => $json['remitente'] ?? null, ]; } }