Actualizar server.js
This commit is contained in:
124
server.js
124
server.js
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user