import os, sqlite3, secrets, smtplib, hashlib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from flask import Flask, request, jsonify import stripe app = Flask(__name__) STRIPE_SECRET = os.environ.get("STRIPE_SECRET_KEY", "") STRIPE_WEBHOOK = os.environ.get("STRIPE_WEBHOOK_SECRET", "") GMAIL_USER = os.environ.get("GMAIL_USER", "dayron100813@gmail.com") GMAIL_PASS = os.environ.get("GMAIL_PASS", "") DB_PATH = "/data/usuarios.db" AUTH_SECRET = os.environ.get("AUTH_SECRET", "fenix-secret-interno") stripe.api_key = STRIPE_SECRET PLANES = { "hobby": {"apps_dia": 3, "nombre": "Fénix Hobby"}, "pro": {"apps_dia": 8, "nombre": "Fénix Pro"}, "agencia": {"apps_dia": 15, "nombre": "Fénix Agencia"}, } def get_db(): os.makedirs("/data", exist_ok=True) conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row conn.execute(""" CREATE TABLE IF NOT EXISTS usuarios ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, plan TEXT NOT NULL, stripe_customer_id TEXT, activo INTEGER DEFAULT 1, apps_hoy INTEGER DEFAULT 0, fecha_reset TEXT DEFAULT '', creado_en TEXT DEFAULT (datetime('now')) ) """) conn.commit() return conn def hash_pass(pw): return hashlib.sha256(pw.encode()).hexdigest() def enviar_email(dest, asunto, cuerpo_html): try: msg = MIMEMultipart("alternative") msg["Subject"] = asunto msg["From"] = GMAIL_USER msg["To"] = dest msg.attach(MIMEText(cuerpo_html, "html")) with smtplib.SMTP_SSL("smtp.gmail.com", 465) as s: s.login(GMAIL_USER, GMAIL_PASS) s.sendmail(GMAIL_USER, dest, msg.as_string()) print(f"[EMAIL] Enviado a {dest}") except Exception as e: print(f"[EMAIL] Error: {e}") def crear_usuario(email, plan, stripe_customer_id=""): password = secrets.token_urlsafe(10) db = get_db() try: db.execute( "INSERT INTO usuarios (email, password_hash, plan, stripe_customer_id) VALUES (?,?,?,?)", (email, hash_pass(password), plan, stripe_customer_id) ) db.commit() except sqlite3.IntegrityError: # Usuario ya existe — actualizar plan db.execute("UPDATE usuarios SET plan=?, activo=1 WHERE email=?", (plan, email)) db.commit() password = None # no mandamos nueva contraseña si ya existe db.close() return password @app.route("/webhook", methods=["POST"]) def webhook(): payload = request.data sig = request.headers.get("Stripe-Signature", "") try: event = stripe.Webhook.construct_event(payload, sig, STRIPE_WEBHOOK) except Exception as e: return jsonify({"error": str(e)}), 400 if event["type"] == "checkout.session.completed": session = event["data"]["object"] email = session.get("customer_details", {}).get("email", "") customer = session.get("customer", "") amount = session.get("amount_total", 0) # Detectar plan por precio if amount <= 1900: plan = "hobby" elif amount <= 7900: plan = "pro" else: plan = "agencia" if email: password = crear_usuario(email, plan, customer) nombre_plan = PLANES[plan]["nombre"] if password: cuerpo = f"""

🔥 Bienvenido a Fénix-Forja

Tu cuenta ha sido creada con el plan {nombre_plan}.

Email: {email}
Contraseña: {password}

Accede aquí: https://cristobal299-fenix-fabfica.hf.space

Límite: {PLANES[plan]['apps_dia']} apps por día.


Fénix-Forja — Fábrica autónoma de apps

""" enviar_email(email, f"🔥 Tus credenciales de Fénix-Forja ({nombre_plan})", cuerpo) print(f"[WEBHOOK] Usuario {email} → plan {plan}") return jsonify({"ok": True}) @app.route("/verificar", methods=["POST"]) def verificar(): """Fénix llama aquí para comprobar login. Requiere AUTH_SECRET.""" data = request.json or {} secret = data.get("secret", "") if secret != AUTH_SECRET: return jsonify({"ok": False, "error": "No autorizado"}), 403 email = data.get("email", "").strip().lower() password = data.get("password", "") if not email or not password: return jsonify({"ok": False, "error": "Faltan datos"}) db = get_db() user = db.execute( "SELECT * FROM usuarios WHERE email=? AND password_hash=? AND activo=1", (email, hash_pass(password)) ).fetchone() db.close() if not user: return jsonify({"ok": False, "error": "Credenciales incorrectas"}) return jsonify({ "ok": True, "plan": user["plan"], "apps_dia": PLANES.get(user["plan"], {}).get("apps_dia", 3), "email": user["email"], }) @app.route("/contador", methods=["POST"]) def contador(): """Incrementa el contador de apps del día y comprueba el límite.""" data = request.json or {} secret = data.get("secret", "") if secret != AUTH_SECRET: return jsonify({"ok": False}), 403 email = data.get("email", "").strip().lower() from datetime import date hoy = str(date.today()) db = get_db() user = db.execute("SELECT * FROM usuarios WHERE email=?", (email,)).fetchone() if not user: db.close() return jsonify({"ok": False, "error": "Usuario no encontrado"}) apps_hoy = user["apps_hoy"] if user["fecha_reset"] == hoy else 0 limite = PLANES.get(user["plan"], {}).get("apps_dia", 3) if apps_hoy >= limite: db.close() return jsonify({"ok": False, "error": f"Límite diario alcanzado ({limite} apps/día)", "limite": limite}) db.execute( "UPDATE usuarios SET apps_hoy=?, fecha_reset=? WHERE email=?", (apps_hoy + 1, hoy, email) ) db.commit() db.close() return jsonify({"ok": True, "apps_hoy": apps_hoy + 1, "limite": limite}) @app.route("/health") def health(): return jsonify({"status": "ok", "service": "fenix-auth"}) if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)