Actualizar server.js

This commit is contained in:
2026-04-03 21:23:52 +00:00
parent c8312f0aae
commit 9c538f7a7a

124
server.js
View File

@@ -5086,63 +5086,125 @@ app.get("/public/portal/:token/protection", async (req, res) => {
}
});
// 2. Firmar contrato, generar suscripción y redirigir a Stripe
app.post("/public/portal/:token/protection/subscribe", async (req, res) => {
try {
const { token } = req.params;
const { plan_id, signature, pdf_document, dni } = req.body;
// 1. Validar cliente
const clientQ = await pool.query("SELECT * FROM clients WHERE portal_token = $1", [token]);
if (clientQ.rowCount === 0) return res.status(404).json({ ok: false, error: "Token inválido" });
const clientQ = await pool.query(
"SELECT * FROM clients WHERE portal_token = $1",
[token]
);
if (clientQ.rowCount === 0) {
return res.status(404).json({ ok: false, error: "Token inválido" });
}
const client = clientQ.rows[0];
const ownerId = client.owner_id;
// 2. Validar Plan
const planQ = await pool.query("SELECT * FROM protection_plans WHERE id = $1 AND company_id = $2", [plan_id, ownerId]);
if (planQ.rowCount === 0) return res.status(404).json({ ok: false, error: "El plan seleccionado no existe" });
const planQ = await pool.query(
"SELECT * FROM protection_plans WHERE id = $1 AND company_id = $2",
[plan_id, ownerId]
);
if (planQ.rowCount === 0) {
return res.status(404).json({ ok: false, error: "El plan seleccionado no existe" });
}
const plan = planQ.rows[0];
// 3. Crear suscripción en la BD (Estado: Impagado hasta que Stripe confirme)
const subInsert = await pool.query(`
INSERT INTO protection_subscriptions (company_id, plan_id, client_name, client_dni, client_phone, payment_status, status)
VALUES ($1, $2, $3, $4, $5, 'impagado', 'suspendido')
RETURNING id
`, [ownerId, plan.id, client.full_name, dni || null, client.phone]);
const subscriptionId = subInsert.rows[0].id;
const ownerConfigQ = await pool.query(
"SELECT billing_settings FROM users WHERE id = $1",
[ownerId]
);
let billingSettings = ownerConfigQ.rows[0]?.billing_settings || {};
if (typeof billingSettings === "string") {
try { billingSettings = JSON.parse(billingSettings); } catch (_) { billingSettings = {}; }
}
// 4. Guardamos la firma REAL y el registro
await pool.query("UPDATE protection_subscriptions SET contract_pdf_url = $1 WHERE id = $2", [pdf_document, subscriptionId]);
await pool.query("INSERT INTO protection_activity (company_id, type, description) VALUES ($1, 'alta', $2)", [ownerId, `Suscripción iniciada vía Web: ${client.full_name} (${plan.name})`]);
// 5. Integración con Stripe
const ownerConfigQ = await pool.query("SELECT billing_settings FROM users WHERE id = $1", [ownerId]);
const billingSettings = ownerConfigQ.rows[0]?.billing_settings || {};
if (!billingSettings.stripe_enabled || !billingSettings.stripe_sk) {
return res.status(400).json({ ok: false, error: "La empresa no tiene habilitados los pagos con tarjeta." });
}
const stripe = new Stripe(billingSettings.stripe_sk, { apiVersion: "2023-10-16" });
const interval =
String(plan.billing_interval || "").toLowerCase() === "year" ||
String(plan.type || "").toLowerCase().includes("anual")
? "year"
: "month";
const intervalCount = Number(plan.billing_interval_count || 1);
const subInsert = await pool.query(`
INSERT INTO protection_subscriptions (
company_id,
plan_id,
client_name,
client_dni,
client_phone,
payment_status,
status,
contract_pdf_url
)
VALUES ($1, $2, $3, $4, $5, 'impagado', 'pendiente_pago', $6)
RETURNING id
`, [
ownerId,
plan.id,
client.full_name,
dni || null,
client.phone,
pdf_document || null
]);
const subscriptionId = subInsert.rows[0].id;
await pool.query(
"INSERT INTO protection_activity (company_id, type, description) VALUES ($1, 'alta', $2)",
[ownerId, `Suscripción iniciada vía Web: ${client.full_name} (${plan.name})`]
);
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
payment_method_types: ["card"],
mode: "subscription",
line_items: [{
price_data: {
currency: 'eur',
product_data: { name: `Plan de Protección: ${plan.name}`, description: `Suscripción ${plan.type}` },
unit_amount: Math.round(plan.price * 100),
currency: "eur",
product_data: {
name: `Plan de Protección: ${plan.name}`,
description: `Suscripción ${plan.type || interval}`
},
unit_amount: Math.round(Number(plan.price || 0) * 100),
recurring: {
interval,
interval_count: intervalCount
}
},
quantity: 1,
quantity: 1
}],
mode: 'payment',
metadata: { subscription_id: subscriptionId, owner_id: ownerId, type: 'protection_plan' },
metadata: {
subscription_id: String(subscriptionId),
owner_id: String(ownerId),
plan_id: String(plan.id),
type: "protection_plan"
},
customer_email: client.email || undefined,
success_url: `https://portal.integrarepara.es/pago_exito.html?sub_id=${subscriptionId}`,
cancel_url: `https://portal.integrarepara.es/plan-tranquilidad.html?token=${token}`,
});
await pool.query(`
UPDATE protection_subscriptions
SET stripe_session_id = $1,
stripe_price_id = $2,
updated_at = NOW()
WHERE id = $3
`, [
session.id,
null,
subscriptionId
]);
res.json({ ok: true, checkout_url: session.url });
} catch (e) {