Actualizar server.js
This commit is contained in:
71
server.js
71
server.js
@@ -905,6 +905,77 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// 🔐 OTP PARA CLIENTES (VERIFICACIÓN WHATSAPP)
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
// 1. Solicitar el código de 4 cifras
|
||||||
|
app.post("/public/auth/request-otp", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { phone, owner_id } = req.body;
|
||||||
|
if (!phone) return res.status(400).json({ ok: false });
|
||||||
|
|
||||||
|
const targetOwnerId = owner_id || 1;
|
||||||
|
const cleanPhone = phone.replace(/\D/g, "");
|
||||||
|
|
||||||
|
// Generar código de 4 cifras (ej: 4829)
|
||||||
|
const code = String(Math.floor(1000 + Math.random() * 9000));
|
||||||
|
const hash = await bcrypt.hash(code, 10);
|
||||||
|
|
||||||
|
// Guardamos el código (dejamos user_id nulo porque es un cliente externo)
|
||||||
|
await pool.query(`
|
||||||
|
INSERT INTO login_codes (phone, code_hash, purpose, expires_at)
|
||||||
|
VALUES ($1, $2, 'client_portal', NOW() + INTERVAL '15 minutes')
|
||||||
|
`, [cleanPhone, hash]);
|
||||||
|
|
||||||
|
// Enviar el WhatsApp
|
||||||
|
const msg = `🔐 Tu código de acceso para solicitar asistencia es: *${code}*\n\nSi no has solicitado este código, ignora este mensaje.`;
|
||||||
|
sendWhatsAppAuto("34" + cleanPhone, msg, `cliente_${targetOwnerId}`, false).catch(console.error);
|
||||||
|
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch(e) {
|
||||||
|
console.error("Error OTP Request:", e);
|
||||||
|
res.status(500).json({ ok: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Verificar el código y comprobar si el cliente existe
|
||||||
|
app.post("/public/auth/verify-otp", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { phone, code, owner_id } = req.body;
|
||||||
|
const cleanPhone = phone.replace(/\D/g, "");
|
||||||
|
const targetOwnerId = owner_id || 1;
|
||||||
|
|
||||||
|
// Buscamos el último código válido
|
||||||
|
const q = await pool.query(`
|
||||||
|
SELECT id, code_hash FROM login_codes
|
||||||
|
WHERE phone = $1 AND purpose = 'client_portal' AND consumed_at IS NULL AND expires_at > NOW()
|
||||||
|
ORDER BY created_at DESC LIMIT 1
|
||||||
|
`, [cleanPhone]);
|
||||||
|
|
||||||
|
if (q.rowCount === 0) return res.status(400).json({ ok: false, error: "Código inválido o caducado" });
|
||||||
|
|
||||||
|
// Comparamos el código que ha puesto el cliente con el de la BBDD
|
||||||
|
const valid = await bcrypt.compare(code, q.rows[0].code_hash);
|
||||||
|
if (!valid) return res.status(400).json({ ok: false, error: "Código incorrecto" });
|
||||||
|
|
||||||
|
// Lo marcamos como usado
|
||||||
|
await pool.query("UPDATE login_codes SET consumed_at = NOW() WHERE id = $1", [q.rows[0].id]);
|
||||||
|
|
||||||
|
// VERIFICAMOS SI EL CLIENTE YA EXISTE EN NUESTRA BASE DE DATOS
|
||||||
|
const qClient = await pool.query("SELECT id, full_name, addresses, portal_token FROM clients WHERE phone LIKE $1 AND owner_id = $2 LIMIT 1", [`%${cleanPhone}%`, targetOwnerId]);
|
||||||
|
|
||||||
|
if (qClient.rowCount > 0) {
|
||||||
|
res.json({ ok: true, exists: true, client: qClient.rows[0] });
|
||||||
|
} else {
|
||||||
|
res.json({ ok: true, exists: false });
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error("Error OTP Verify:", e);
|
||||||
|
res.status(500).json({ ok: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 🌐 EMBUDO PÚBLICO DE ENTRADA DE CLIENTES
|
// 🌐 EMBUDO PÚBLICO DE ENTRADA DE CLIENTES
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|||||||
Reference in New Issue
Block a user