177 lines
5.9 KiB
JavaScript
177 lines
5.9 KiB
JavaScript
import { Router } from 'express';
|
|
import Stripe from 'stripe';
|
|
import { authMiddleware } from '../auth.js';
|
|
import { query } from '../db.js';
|
|
|
|
const router = Router();
|
|
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || '', {
|
|
apiVersion: '2024-06-20'
|
|
});
|
|
const STRIPE_MIN_HUF = 175;
|
|
const MIN_DEPOSIT = Math.max(Number(process.env.MIN_DEPOSIT || STRIPE_MIN_HUF), STRIPE_MIN_HUF);
|
|
const MAX_DEPOSIT = Number(process.env.MAX_DEPOSIT || 1000);
|
|
|
|
function ensureStripeConfigured(res) {
|
|
if (!process.env.STRIPE_SECRET_KEY) {
|
|
res.status(500).json({ error: 'Stripe nincs beallitva.' });
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
async function getPromoCode(code) {
|
|
const rows = await query(
|
|
'SELECT id, code, bonus_type, bonus_value, max_uses, expires_at, active FROM promo_codes WHERE code = ? AND active = 1 AND (expires_at IS NULL OR expires_at > NOW())',
|
|
[code]
|
|
);
|
|
return rows[0];
|
|
}
|
|
|
|
function calcBonusAmount(amount, promo) {
|
|
if (!promo) {
|
|
return 0;
|
|
}
|
|
if (promo.bonus_type === 'percent') {
|
|
return Math.max(0, Math.floor(amount * Number(promo.bonus_value) / 100));
|
|
}
|
|
if (promo.bonus_type === 'fixed') {
|
|
return Math.max(0, Number(promo.bonus_value));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
router.post('/api/wallet/deposit-intent', authMiddleware, async (req, res) => {
|
|
try {
|
|
if (!ensureStripeConfigured(res)) {
|
|
return;
|
|
}
|
|
|
|
const rawAmount = req.body.amount;
|
|
const amount = Math.round(Number(rawAmount));
|
|
const stripeAmount = Math.round(amount * 100);
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
console.log('Stripe deposit request:', { rawAmount, amount, stripeAmount, min: MIN_DEPOSIT, max: MAX_DEPOSIT });
|
|
}
|
|
|
|
if (!Number.isFinite(amount) || amount < MIN_DEPOSIT || amount > MAX_DEPOSIT) {
|
|
return res.status(400).json({ error: `A feltoltes ${MIN_DEPOSIT} es ${MAX_DEPOSIT} Ft kozott lehet.` });
|
|
}
|
|
|
|
const promoInput = req.body.promoCode?.toString().trim().toUpperCase();
|
|
let promo = null;
|
|
let bonusAmount = 0;
|
|
let promoCodeId = null;
|
|
|
|
if (promoInput) {
|
|
promo = await getPromoCode(promoInput);
|
|
if (!promo) {
|
|
return res.status(400).json({ error: 'Ervenytelen promo kod.' });
|
|
}
|
|
|
|
const redeemed = await query(
|
|
'SELECT id FROM promo_redemptions WHERE user_id = ? AND promo_code_id = ? LIMIT 1',
|
|
[req.userId, promo.id]
|
|
);
|
|
if (redeemed.length > 0) {
|
|
return res.status(400).json({ error: 'A promo kod mar felhasznalva.' });
|
|
}
|
|
|
|
if (promo.max_uses) {
|
|
const usage = await query(
|
|
'SELECT COUNT(*) AS count FROM promo_redemptions WHERE promo_code_id = ?',
|
|
[promo.id]
|
|
);
|
|
if ((usage[0]?.count ?? 0) >= promo.max_uses) {
|
|
return res.status(400).json({ error: 'A promo kod mar elfogyott.' });
|
|
}
|
|
}
|
|
|
|
bonusAmount = calcBonusAmount(amount, promo);
|
|
promoCodeId = promo.id;
|
|
}
|
|
|
|
const paymentIntent = await stripe.paymentIntents.create({
|
|
amount: stripeAmount,
|
|
currency: 'huf',
|
|
automatic_payment_methods: { enabled: true },
|
|
metadata: {
|
|
userId: String(req.userId)
|
|
}
|
|
});
|
|
|
|
await query(
|
|
'INSERT INTO deposits (user_id, amount, bonus_amount, promo_code_id, stripe_payment_intent_id, status) VALUES (?, ?, ?, ?, ?, ?)',
|
|
[req.userId, amount, bonusAmount, promoCodeId, paymentIntent.id, 'created']
|
|
);
|
|
|
|
return res.json({ clientSecret: paymentIntent.client_secret, paymentIntentId: paymentIntent.id });
|
|
} catch (err) {
|
|
console.error('Stripe fizetes hiba:', err);
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
return res.status(500).json({ error: err.message || 'Nem sikerult letrehozni a fizetest.' });
|
|
}
|
|
return res.status(500).json({ error: 'Nem sikerult letrehozni a fizetest.' });
|
|
}
|
|
});
|
|
|
|
router.post('/api/wallet/confirm', authMiddleware, async (req, res) => {
|
|
try {
|
|
if (!ensureStripeConfigured(res)) {
|
|
return;
|
|
}
|
|
|
|
const paymentIntentId = req.body.paymentIntentId?.toString();
|
|
if (!paymentIntentId) {
|
|
return res.status(400).json({ error: 'Hianyzo paymentIntentId.' });
|
|
}
|
|
|
|
const rows = await query(
|
|
'SELECT id, status, amount, bonus_amount, promo_code_id FROM deposits WHERE user_id = ? AND stripe_payment_intent_id = ?',
|
|
[req.userId, paymentIntentId]
|
|
);
|
|
const deposit = rows[0];
|
|
if (!deposit) {
|
|
return res.status(404).json({ error: 'Ismeretlen befizetes.' });
|
|
}
|
|
|
|
const intent = await stripe.paymentIntents.retrieve(paymentIntentId);
|
|
if (intent.status !== 'succeeded') {
|
|
return res.json({ status: intent.status });
|
|
}
|
|
|
|
if (deposit.status !== 'succeeded') {
|
|
await query(
|
|
'UPDATE deposits SET status = ? WHERE id = ?',
|
|
['succeeded', deposit.id]
|
|
);
|
|
const totalCredit = Number(deposit.amount) + Number(deposit.bonus_amount || 0);
|
|
await query('UPDATE users SET balance = balance + ? WHERE id = ?', [totalCredit, req.userId]);
|
|
|
|
if (deposit.promo_code_id) {
|
|
const already = await query(
|
|
'SELECT id FROM promo_redemptions WHERE user_id = ? AND promo_code_id = ? LIMIT 1',
|
|
[req.userId, deposit.promo_code_id]
|
|
);
|
|
if (already.length === 0) {
|
|
await query(
|
|
'INSERT INTO promo_redemptions (user_id, promo_code_id, deposit_id) VALUES (?, ?, ?)',
|
|
[req.userId, deposit.promo_code_id, deposit.id]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
const balanceRows = await query('SELECT balance FROM users WHERE id = ?', [req.userId]);
|
|
const balance = balanceRows[0]?.balance ?? 0;
|
|
return res.json({ status: 'succeeded', balance });
|
|
} catch (err) {
|
|
console.error('Stripe confirm hiba:', err);
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
return res.status(500).json({ error: err.message || 'Nem sikerult a befizetes ellenorzese.' });
|
|
}
|
|
return res.status(500).json({ error: 'Nem sikerult a befizetes ellenorzese.' });
|
|
}
|
|
});
|
|
|
|
export default router;
|