Files
sirpremiumv2/app/Services/PagoValidadorService.php
T
LizandroandClaude Sonnet 4.6 536377363c feat: web chat con IA, validación de pagos y OTP por correo
- Chat público en /chat con flujos de compra, recarga y credenciales
- Verificación de identidad por código OTP enviado al correo registrado
- Botones enriquecidos: cards, links, credenciales, validación de comprobante
- Gemini IA para detección de intención en texto libre
- Gemini Vision para extraer datos de foto de comprobante
- Validador de pagos cruzando IA con correos IMAP (Bancolombia)
- MercadoPago como pasarela de pago (reemplaza Wompi en el chat)
- Migraciones: payload en chat_messages, user_id en chat_contacts
- Config admin: API key Gemini, toggles IA y validación de foto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-14 00:09:31 +00:00

84 lines
3.1 KiB
PHP

<?php
namespace App\Services;
use App\Models\ChatConfig;
use App\Models\WhatsappSystemConfig;
use Illuminate\Support\Facades\Log;
class PagoValidadorService
{
/**
* Cruza los datos extraídos por IA con los correos IMAP recientes.
*
* @param array $datosPago ['banco', 'valor', 'referencia', 'fecha', 'hora', 'remitente']
* @return array ['estado' => confirmado|no_encontrado|monto_incorrecto, 'correo' => array|null]
*/
public function validar(array $datosPago): array
{
if (WhatsappSystemConfig::get('correo_imap_enabled', '0') !== '1') {
return ['estado' => 'no_encontrado', 'correo' => null, 'motivo' => 'correo_deshabilitado'];
}
try {
$correos = $this->fetchCorreos();
} catch (\Throwable $e) {
Log::warning('[PagoValidador] Error leyendo correos: ' . $e->getMessage());
return ['estado' => 'no_encontrado', 'correo' => null, 'motivo' => 'error_imap'];
}
if (empty($correos)) {
return ['estado' => 'no_encontrado', 'correo' => null, 'motivo' => 'sin_correos'];
}
$valorIA = (int) ($datosPago['valor'] ?? 0);
foreach ($correos as $correo) {
$datosCorreo = BancolombiaParser::parse($correo['body'] ?? '');
if (! $datosCorreo) {
continue;
}
$valorCorreo = (int) ($datosCorreo['valor'] ?? 0);
// Verificar referencia si ambas están disponibles
if (! empty($datosPago['referencia']) && ! empty($datosCorreo['referencia'])) {
if ($datosPago['referencia'] === $datosCorreo['referencia']) {
return ['estado' => 'confirmado', 'correo' => $datosCorreo];
}
}
// Verificar valor
if ($valorIA > 0 && $valorCorreo > 0) {
$tolerancia = (int) ChatConfig::get('validacion_monto_tolerancia', '0');
if (abs($valorIA - $valorCorreo) <= $tolerancia) {
return ['estado' => 'confirmado', 'correo' => $datosCorreo];
} else {
return ['estado' => 'monto_incorrecto', 'correo' => $datosCorreo,
'esperado' => $valorCorreo, 'recibido' => $valorIA];
}
}
}
return ['estado' => 'no_encontrado', 'correo' => null, 'motivo' => 'sin_coincidencia'];
}
private function fetchCorreos(): array
{
$minutos = (int) WhatsappSystemConfig::get('correo_imap_minutos', '5');
$service = new CorreoImapService(
host: WhatsappSystemConfig::get('correo_imap_host', ''),
port: (int) WhatsappSystemConfig::get('correo_imap_port', '993'),
useSsl: WhatsappSystemConfig::get('correo_imap_ssl', '1') === '1',
user: WhatsappSystemConfig::get('correo_imap_user', ''),
password: WhatsappSystemConfig::get('correo_imap_password', ''),
folder: WhatsappSystemConfig::get('correo_imap_folder', 'INBOX'),
);
return $service->fetchLatest(limit: 10, minutesBack: $minutos);
}
}