/* ============================================================ routes/shop.route.js Stripe Shop – Gems kaufen .env benötigt: STRIPE_SECRET_KEY=sk_live_... STRIPE_WEBHOOK_SECRET=whsec_... APP_URL=https://spiel.dynastyofknights.com ============================================================ */ const express = require("express"); const router = express.Router(); const db = require("../database/database"); const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); function requireLogin(req, res, next) { if (!req.session?.user) return res.status(401).json({ error: "Nicht eingeloggt" }); next(); } /* ════════════════════════════════════════════ Shop-Pakete (Preis in Cent!) ════════════════════════════════════════════ */ const PACKAGES = [ { id: "starter", name: "Starter", gems: 100, price: 199, bonus: 0 }, { id: "abenteurer", name: "Abenteurer", gems: 500, price: 799, bonus: 50 }, { id: "ritter", name: "Ritter", gems: 1000, price: 1499, bonus: 150 }, { id: "fuerst", name: "Fürst", gems: 2500, price: 3499, bonus: 500 }, { id: "koenig", name: "König", gems: 5000, price: 5999, bonus: 1500 }, ]; /* ════════════════════════════════════════════ GET /api/shop/packages Pakete für Frontend laden ════════════════════════════════════════════ */ router.get("/shop/packages", requireLogin, (req, res) => { res.json(PACKAGES); }); /* ════════════════════════════════════════════ POST /api/shop/checkout Stripe Checkout Session erstellen Body: { packageId: "ritter" } ════════════════════════════════════════════ */ router.post("/shop/checkout", requireLogin, async (req, res) => { const userId = req.session.user.id; const { packageId } = req.body; const pkg = PACKAGES.find(p => p.id === packageId); if (!pkg) return res.status(400).json({ error: "Paket nicht gefunden." }); try { const session = await stripe.checkout.sessions.create({ payment_method_types: ["card", "paypal"], line_items: [{ price_data: { currency: "eur", product_data: { name: `${pkg.name} Paket – ${pkg.gems + pkg.bonus} 💠 Gems`, description: pkg.bonus > 0 ? `${pkg.gems} Gems + ${pkg.bonus} Bonus-Gems` : `${pkg.gems} Gems`, images: [`${process.env.APP_URL}/images/items/blauer-cristal.png`], }, unit_amount: pkg.price, }, quantity: 1, }], mode: "payment", success_url: `${process.env.APP_URL}/launcher?payment=success`, cancel_url: `${process.env.APP_URL}/launcher?payment=cancel`, metadata: { userId: String(userId), packageId: pkg.id, gems: String(pkg.gems + pkg.bonus), }, }); res.json({ url: session.url }); } catch (err) { console.error("Stripe Fehler:", err); res.status(500).json({ error: "Zahlung konnte nicht gestartet werden." }); } }); /* ════════════════════════════════════════════ POST /api/shop/webhook Stripe Webhook – Zahlung bestätigt WICHTIG: Muss VOR express.json() registriert werden → raw body nötig! ════════════════════════════════════════════ */ router.post( "/shop/webhook", express.raw({ type: "application/json" }), async (req, res) => { const sig = req.headers["stripe-signature"]; let event; try { event = stripe.webhooks.constructEvent( req.body, sig, process.env.STRIPE_WEBHOOK_SECRET ); } catch (err) { console.error("Webhook Signatur-Fehler:", err.message); return res.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === "checkout.session.completed") { const session = event.data.object; const userId = parseInt(session.metadata.userId); const gems = parseInt(session.metadata.gems); const packageId = session.metadata.packageId; try { /* ── Idempotenz: bereits verarbeitet? ── */ const [[existing]] = await db.query( "SELECT id FROM shop_purchases WHERE stripe_session_id = ?", [session.id] ); if (existing) { console.log(`⚠️ Webhook bereits verarbeitet (ignoriert): ${session.id}`); return res.json({ received: true }); } /* ── Gems gutschreiben ── */ await db.query( "UPDATE account_currency SET gems = gems + ? WHERE account_id = ?", [gems, userId] ); /* ── Kauf protokollieren ── */ await db.query( `INSERT INTO shop_purchases (user_id, package_id, gems, stripe_session_id, created_at) VALUES (?, ?, ?, ?, NOW())`, [userId, packageId, gems, session.id] ); console.log(`✅ Shop: User ${userId} erhält ${gems} Gems (${packageId})`); } catch (err) { console.error("Gems gutschreiben Fehler:", err); return res.status(500).end(); } } res.json({ received: true }); } ); module.exports = router;