mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-20 07:38:34 +02:00
fix credits logic
This commit is contained in:
@@ -870,18 +870,34 @@ const SocketHandlers = {
|
||||
// Hide the QR code now that payment is confirmed
|
||||
SocketHandlers.hidePaymentQR();
|
||||
|
||||
if (typeof Game !== 'undefined' && Game.drawWaitingScreen) {
|
||||
Game.drawWaitingScreen();
|
||||
// Credits purchase: return to home screen (no game queue)
|
||||
if (data.creditsAdded || data.newBalance !== undefined) {
|
||||
if (typeof Game !== 'undefined') {
|
||||
Game._pendingPaymentConfirmed();
|
||||
}
|
||||
// Return to welcome/home screen so user can start a game
|
||||
if (typeof ScreenManager !== 'undefined' && ScreenManager.drawWelcomeScreen) {
|
||||
ScreenManager.drawWelcomeScreen();
|
||||
}
|
||||
$('#messages').append($('<li class="payment-success" style="color:#0f0;">').html(
|
||||
'✅ <strong>Credits purchased!</strong> Type \'enter\' or click START GAME to play.'
|
||||
));
|
||||
UI.scrollChat();
|
||||
SocketHandlers._setBannerStatus('Credits Added', '#0f0');
|
||||
} else {
|
||||
// Single game payment: show waiting screen (player is in queue)
|
||||
if (typeof Game !== 'undefined' && Game.drawWaitingScreen) {
|
||||
Game.drawWaitingScreen();
|
||||
}
|
||||
if (typeof Game !== 'undefined') {
|
||||
Game._pendingPaymentConfirmed();
|
||||
}
|
||||
$('#messages').append($('<li class="payment-success" style="color:#0f0;">').html(
|
||||
'✅ <strong>Payment confirmed in block.</strong> You are in the game queue.'
|
||||
));
|
||||
UI.scrollChat();
|
||||
SocketHandlers._setBannerStatus('Confirmed', '#0f0');
|
||||
}
|
||||
if (typeof Game !== 'undefined') {
|
||||
Game._pendingPaymentConfirmed();
|
||||
}
|
||||
|
||||
$('#messages').append($('<li class="payment-success" style="color:#0f0;">').html(
|
||||
'✅ <strong>Payment confirmed in block.</strong> You are in the game queue.'
|
||||
));
|
||||
UI.scrollChat();
|
||||
SocketHandlers._setBannerStatus('Confirmed', '#0f0');
|
||||
// Sound handled by AudioAlerts._patchSocketHandlers() - don't duplicate
|
||||
},
|
||||
|
||||
|
||||
+15
-6
@@ -638,15 +638,24 @@ const adminAuth = (req, res, next) => {
|
||||
}
|
||||
|
||||
// Origin check — reject cross-origin requests to admin endpoints
|
||||
// Same-origin requests (Origin matches Host) are always allowed
|
||||
const origin = req.headers.origin || req.headers.referer;
|
||||
if (origin) {
|
||||
try {
|
||||
const allowedOrigins = process.env.ALLOWED_ORIGINS
|
||||
? process.env.ALLOWED_ORIGINS.split(',').map(o => o.trim())
|
||||
: [`http://localhost:${process.env.PORT || 3000}`, `http://127.0.0.1:${process.env.PORT || 3000}`];
|
||||
const requestOrigin = new URL(origin).origin;
|
||||
if (!allowedOrigins.includes(requestOrigin)) {
|
||||
return res.status(403).json({ error: 'Forbidden', message: 'Origin not allowed.' });
|
||||
const host = req.headers.host;
|
||||
const protocol = req.secure || req.headers['x-forwarded-proto'] === 'https' ? 'https' : 'http';
|
||||
const selfOrigin = `${protocol}://${host}`;
|
||||
|
||||
// Allow same-origin requests (admin.html served from same server)
|
||||
if (requestOrigin !== selfOrigin) {
|
||||
// Check explicit allowlist for cross-origin requests
|
||||
const allowedOrigins = process.env.ALLOWED_ORIGINS
|
||||
? process.env.ALLOWED_ORIGINS.split(',').map(o => o.trim())
|
||||
: [`http://localhost:${process.env.PORT || 3000}`, `http://127.0.0.1:${process.env.PORT || 3000}`];
|
||||
if (!allowedOrigins.includes(requestOrigin)) {
|
||||
return res.status(403).json({ error: 'Forbidden', message: 'Origin not allowed.' });
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
return res.status(403).json({ error: 'Forbidden', message: 'Invalid origin.' });
|
||||
@@ -1804,7 +1813,7 @@ async function startServer() {
|
||||
const payoutIntervalMs = payoutIntervalSeconds * 1000;
|
||||
batchPayoutInterval = setInterval(async () => {
|
||||
try {
|
||||
await walletRPCService.processBatchPayouts();
|
||||
await gameModeManager._processPendingPayouts();
|
||||
} catch (error) {
|
||||
console.error('Error in batch payout processing:', error);
|
||||
}
|
||||
|
||||
@@ -279,25 +279,37 @@ class PaymentHandlers {
|
||||
if (status.in_mempool && !status.confirmed) {
|
||||
if (this.mempoolNotified.has(paymentRequest.address)) return;
|
||||
this.mempoolNotified.add(paymentRequest.address);
|
||||
socket.emit('payment_detected', { paymentId: paymentRequest.id, message: 'Payment detected in mempool! Adding you to the game queue...', amount: status.amount, confirmations: 0 });
|
||||
const existingIdx = this.queueManager.getPlayerIndex(socket.id);
|
||||
if (existingIdx === -1) {
|
||||
// Try to get DB userId from session
|
||||
let userId = null;
|
||||
if (this.sessionManager?.sessions?.has(socket.id)) {
|
||||
userId = this.sessionManager.sessions.get(socket.id).id;
|
||||
}
|
||||
|
||||
this.queueManager.addPlayer({
|
||||
serverId: socket.id,
|
||||
clientId: currentUser ? currentUser.clientId : null,
|
||||
userId: userId,
|
||||
paymentId: paymentRequest.id,
|
||||
requiresConfirmation: true,
|
||||
confirmed: false
|
||||
});
|
||||
// Check payment type — credits_package should NOT queue for a game
|
||||
const mapping = this.socketPaymentMap.get(socket.id);
|
||||
const isCredits = mapping && mapping.paymentType === 'credits_package';
|
||||
|
||||
const detectMessage = isCredits
|
||||
? 'Payment detected in mempool! Awaiting block confirmation to add credits...'
|
||||
: 'Payment detected in mempool! Adding you to the game queue...';
|
||||
socket.emit('payment_detected', { paymentId: paymentRequest.id, message: detectMessage, amount: status.amount, confirmations: 0 });
|
||||
|
||||
// Only queue for single_game payments (credits just add balance, no game queue)
|
||||
if (!isCredits) {
|
||||
const existingIdx = this.queueManager.getPlayerIndex(socket.id);
|
||||
if (existingIdx === -1) {
|
||||
// Try to get DB userId from session
|
||||
let userId = null;
|
||||
if (this.sessionManager?.sessions?.has(socket.id)) {
|
||||
userId = this.sessionManager.sessions.get(socket.id).id;
|
||||
}
|
||||
|
||||
this.queueManager.addPlayer({
|
||||
serverId: socket.id,
|
||||
clientId: currentUser ? currentUser.clientId : null,
|
||||
userId: userId,
|
||||
paymentId: paymentRequest.id,
|
||||
requiresConfirmation: true,
|
||||
confirmed: false
|
||||
});
|
||||
}
|
||||
socket.emit('queue_joined', { position: (existingIdx === -1 ? this.queueManager.getQueueLength() : existingIdx + 1), message: 'Payment received! Waiting for next block to start game...', currentBlock: this.debugManager.getCurrentBlockHeight ? this.debugManager.getCurrentBlockHeight() : null, nextBlock: this.debugManager.getCurrentBlockHeight ? this.debugManager.getCurrentBlockHeight() + 1 : null });
|
||||
}
|
||||
socket.emit('queue_joined', { position: (existingIdx === -1 ? this.queueManager.getQueueLength() : existingIdx + 1), message: 'Payment received! Waiting for next block to start game...', currentBlock: this.debugManager.getCurrentBlockHeight ? this.debugManager.getCurrentBlockHeight() : null, nextBlock: this.debugManager.getCurrentBlockHeight ? this.debugManager.getCurrentBlockHeight() + 1 : null });
|
||||
} else if (status.confirmed) {
|
||||
// SECURITY: Use in-memory Set as fast-path, but DB is source of truth
|
||||
// This prevents double-processing on server restart
|
||||
@@ -344,6 +356,8 @@ class PaymentHandlers {
|
||||
console.error('Error processing credits package confirmation:', e.message);
|
||||
socket.emit('payment_confirmed', { paymentId: paymentRequest.id, message: 'Payment confirmed in block!', confirmations: status.confirmations });
|
||||
}
|
||||
// Defensively remove from queue — credits purchases should never be queued
|
||||
this.queueManager.removePlayer(socket.id);
|
||||
} else {
|
||||
// single_game payment - standard flow
|
||||
// CRITICAL: Atomically update payment status and check if we actually updated it
|
||||
|
||||
@@ -537,7 +537,7 @@ class SocketHandlers {
|
||||
// Create game immediately
|
||||
const blockHeight = this.debugManager.getCurrentBlockHeight ? this.debugManager.getCurrentBlockHeight() : null;
|
||||
memUser.blockRec = blockHeight; // keep legacy timeout logic consistent
|
||||
const game = this.gameManager.createGameForUser(memUser, 'standard');
|
||||
const game = await this.gameManager.createGameForUser(memUser, 'standard');
|
||||
const state = game.getState();
|
||||
state.blockHeight = blockHeight;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user