Compare commits
3 Commits
b673f6fcb3
...
f10714b2c8
| Author | SHA1 | Date | |
|---|---|---|---|
| f10714b2c8 | |||
| fcbe008a5c | |||
| 32db9278e4 |
@@ -15,9 +15,8 @@ DISCORD_REDIRECT_URI=http://localhost:4000/auth/discord/callback
|
|||||||
DEFAULT_APP_REDIRECT=blackjack://auth
|
DEFAULT_APP_REDIRECT=blackjack://auth
|
||||||
|
|
||||||
STRIPE_SECRET_KEY=sk_test_...
|
STRIPE_SECRET_KEY=sk_test_...
|
||||||
STRIPE_WEBHOOK_SECRET=whsec_...
|
|
||||||
|
|
||||||
MIN_BET=10
|
MIN_BET=10
|
||||||
MAX_BET=100
|
MAX_BET=500
|
||||||
ROUND_START_DELAY_MS=3000
|
ROUND_START_DELAY_MS=3000
|
||||||
ROUND_RESET_DELAY_MS=5000
|
ROUND_RESET_DELAY_MS=5000
|
||||||
|
|||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.env
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
@@ -158,7 +158,7 @@ class Table {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (this.currentSeatIndex === index) {
|
if (this.currentSeatIndex === index) {
|
||||||
this.advanceTurn();
|
await this.advanceTurn();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.seats.every((seat) => !seat.userId)) {
|
if (this.seats.every((seat) => !seat.userId)) {
|
||||||
@@ -169,7 +169,7 @@ class Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async placeBet(userId, amount) {
|
async placeBet(userId, amount) {
|
||||||
if (this.phase === 'playing') {
|
if (!['waiting', 'betting'].includes(this.phase)) {
|
||||||
throw new Error('A kor mar fut, varj a kovetkezo korig.');
|
throw new Error('A kor mar fut, varj a kovetkezo korig.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +182,11 @@ class Table {
|
|||||||
throw new Error('Nem ulsz az asztalnal.');
|
throw new Error('Nem ulsz az asztalnal.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const seat = this.seats[index];
|
||||||
|
if (seat.bet > 0) {
|
||||||
|
throw new Error('Mar van teted erre a korre.');
|
||||||
|
}
|
||||||
|
|
||||||
const balanceRows = await query('SELECT balance FROM users WHERE id = ?', [userId]);
|
const balanceRows = await query('SELECT balance FROM users WHERE id = ?', [userId]);
|
||||||
const balance = balanceRows[0]?.balance ?? 0;
|
const balance = balanceRows[0]?.balance ?? 0;
|
||||||
if (balance < amount) {
|
if (balance < amount) {
|
||||||
@@ -192,7 +197,6 @@ class Table {
|
|||||||
const updatedBalanceRows = await query('SELECT balance FROM users WHERE id = ?', [userId]);
|
const updatedBalanceRows = await query('SELECT balance FROM users WHERE id = ?', [userId]);
|
||||||
const updatedBalance = updatedBalanceRows[0]?.balance ?? 0;
|
const updatedBalance = updatedBalanceRows[0]?.balance ?? 0;
|
||||||
|
|
||||||
const seat = this.seats[index];
|
|
||||||
seat.bet = amount;
|
seat.bet = amount;
|
||||||
seat.ready = false;
|
seat.ready = false;
|
||||||
seat.status = 'bet';
|
seat.status = 'bet';
|
||||||
@@ -218,6 +222,10 @@ class Table {
|
|||||||
throw new Error('Eloszor tegyel tetet.');
|
throw new Error('Eloszor tegyel tetet.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.phase !== 'betting') {
|
||||||
|
throw new Error('A kor mar elindult.');
|
||||||
|
}
|
||||||
|
|
||||||
seat.ready = true;
|
seat.ready = true;
|
||||||
this.broadcastState();
|
this.broadcastState();
|
||||||
this.scheduleRound();
|
this.scheduleRound();
|
||||||
@@ -298,14 +306,14 @@ class Table {
|
|||||||
const value = handValue(seat.hand).total;
|
const value = handValue(seat.hand).total;
|
||||||
if (value > 21) {
|
if (value > 21) {
|
||||||
seat.status = 'bust';
|
seat.status = 'bust';
|
||||||
this.advanceTurn();
|
await this.advanceTurn();
|
||||||
} else if (value === 21) {
|
} else if (value === 21) {
|
||||||
seat.status = 'stood';
|
seat.status = 'stood';
|
||||||
this.advanceTurn();
|
await this.advanceTurn();
|
||||||
}
|
}
|
||||||
} else if (action === 'stand') {
|
} else if (action === 'stand') {
|
||||||
seat.status = 'stood';
|
seat.status = 'stood';
|
||||||
this.advanceTurn();
|
await this.advanceTurn();
|
||||||
} else if (action === 'double') {
|
} else if (action === 'double') {
|
||||||
if (seat.hand.length !== 2) {
|
if (seat.hand.length !== 2) {
|
||||||
throw new Error('Duplazni csak az elso ket lap utan lehet.');
|
throw new Error('Duplazni csak az elso ket lap utan lehet.');
|
||||||
@@ -323,7 +331,7 @@ class Table {
|
|||||||
seat.bet += seat.bet;
|
seat.bet += seat.bet;
|
||||||
seat.hand.push(draw(this.deck));
|
seat.hand.push(draw(this.deck));
|
||||||
seat.status = 'stood';
|
seat.status = 'stood';
|
||||||
this.advanceTurn();
|
await this.advanceTurn();
|
||||||
this.broadcast({ type: 'balance', balance: updatedBalance }, userId);
|
this.broadcast({ type: 'balance', balance: updatedBalance }, userId);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Ismeretlen akcio.');
|
throw new Error('Ismeretlen akcio.');
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { WebSocketServer } from 'ws';
|
|||||||
import authRoutes from './routes/auth.js';
|
import authRoutes from './routes/auth.js';
|
||||||
import lobbyRoutes from './routes/lobby.js';
|
import lobbyRoutes from './routes/lobby.js';
|
||||||
import walletRoutes from './routes/wallet.js';
|
import walletRoutes from './routes/wallet.js';
|
||||||
import stripeRoutes from './routes/stripe.js';
|
|
||||||
import { setupWebSocket } from './ws.js';
|
import { setupWebSocket } from './ws.js';
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@@ -19,7 +18,6 @@ app.use(helmet());
|
|||||||
app.use(cors({ origin: process.env.CORS_ORIGIN || '*', credentials: true }));
|
app.use(cors({ origin: process.env.CORS_ORIGIN || '*', credentials: true }));
|
||||||
app.use(morgan('dev'));
|
app.use(morgan('dev'));
|
||||||
|
|
||||||
app.use(stripeRoutes);
|
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
app.get('/health', (req, res) => res.json({ ok: true }));
|
app.get('/health', (req, res) => res.json({ ok: true }));
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import express, { Router } from 'express';
|
|
||||||
import Stripe from 'stripe';
|
|
||||||
import { query } from '../db.js';
|
|
||||||
|
|
||||||
const router = Router();
|
|
||||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || '', {
|
|
||||||
apiVersion: '2024-06-20'
|
|
||||||
});
|
|
||||||
|
|
||||||
router.post('/api/stripe/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
|
|
||||||
const signature = req.headers['stripe-signature'];
|
|
||||||
let event;
|
|
||||||
|
|
||||||
try {
|
|
||||||
event = stripe.webhooks.constructEvent(
|
|
||||||
req.body,
|
|
||||||
signature,
|
|
||||||
process.env.STRIPE_WEBHOOK_SECRET || ''
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
return res.status(400).send('Webhook alairas hiba.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.type === 'payment_intent.succeeded') {
|
|
||||||
const intent = event.data.object;
|
|
||||||
const amount = Number(intent.amount || 0);
|
|
||||||
const userId = Number(intent.metadata?.userId || 0);
|
|
||||||
|
|
||||||
if (userId && amount) {
|
|
||||||
const rows = await query(
|
|
||||||
'SELECT status FROM deposits WHERE stripe_payment_intent_id = ?',
|
|
||||||
[intent.id]
|
|
||||||
);
|
|
||||||
const status = rows[0]?.status;
|
|
||||||
|
|
||||||
if (status !== 'succeeded') {
|
|
||||||
await query(
|
|
||||||
'UPDATE deposits SET status = ? WHERE stripe_payment_intent_id = ?',
|
|
||||||
['succeeded', intent.id]
|
|
||||||
);
|
|
||||||
await query('UPDATE users SET balance = balance + ? WHERE id = ?', [amount, userId]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.json({ received: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
@@ -29,10 +29,47 @@ router.post('/api/wallet/deposit-intent', authMiddleware, async (req, res) => {
|
|||||||
[req.userId, amount, paymentIntent.id, 'created']
|
[req.userId, amount, paymentIntent.id, 'created']
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.json({ clientSecret: paymentIntent.client_secret });
|
return res.json({ clientSecret: paymentIntent.client_secret, paymentIntentId: paymentIntent.id });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(500).json({ error: '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 {
|
||||||
|
const paymentIntentId = req.body.paymentIntentId?.toString();
|
||||||
|
if (!paymentIntentId) {
|
||||||
|
return res.status(400).json({ error: 'Hianyzo paymentIntentId.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = await query(
|
||||||
|
'SELECT id, status, amount 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]
|
||||||
|
);
|
||||||
|
await query('UPDATE users SET balance = balance + ? WHERE id = ?', [deposit.amount, req.userId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return res.status(500).json({ error: 'Nem sikerult a befizetes ellenorzese.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
Reference in New Issue
Block a user