fix payment UI

This commit is contained in:
jwinterm
2025-12-24 17:24:04 -05:00
parent 3589406bac
commit e218fbf67b
4 changed files with 268 additions and 75 deletions
+41 -6
View File
@@ -824,6 +824,7 @@ class GameModeManager {
try {
const user = await this.getOrCreateUser(socketId);
const reuseExisting = options.reuseExisting !== false;
const requestedPackageId = options.packageId;
let amount;
let description;
@@ -836,12 +837,26 @@ class GameModeManager {
break;
}
case 'credits_package': {
const primaryPackage = this.getPrimaryCreditPackage();
const packagePrice = primaryPackage?.price ?? this.creditsPackagePrice;
amount = Number(packagePrice);
packageInfo = primaryPackage;
const creditCount = primaryPackage?.credits ?? 10;
description = `Wowngeon ${creditCount} credits package (${this.cryptoType})`;
// Find the requested package, or fall back to primary
const packages = this.configSnapshot?.modes?.credits?.packages || [];
let selectedPackage = null;
if (requestedPackageId && packages.length > 0) {
selectedPackage = packages.find(p => p.id === requestedPackageId);
}
// Fall back to first package if not found
if (!selectedPackage) {
selectedPackage = this.getPrimaryCreditPackage();
}
const packagePrice = selectedPackage?.price ?? this.creditsPackagePrice;
amount = typeof packagePrice === 'bigint' ? Number(packagePrice) : Number(packagePrice);
packageInfo = selectedPackage;
const creditCount = selectedPackage?.credits ?? 10;
const bonusCredits = selectedPackage?.bonus ?? 0;
const bonusText = bonusCredits > 0 ? ` (+${bonusCredits} bonus)` : '';
description = `Wowngeon ${creditCount}${bonusText} credits package (${this.cryptoType})`;
break;
}
default:
@@ -1003,6 +1018,19 @@ class GameModeManager {
? `⚠️ STAGENET MODE: This server is using ${this.network} XMR. Do NOT send real mainnet XMR! Only ${this.network} XMR will be accepted.`
: null;
// Serialize all credit packages (convert BigInt prices to Number)
const packages = this.configSnapshot?.modes?.credits?.packages || [];
const creditPackages = packages.map(pkg => ({
id: pkg.id,
credits: pkg.credits,
price: typeof pkg.price === 'bigint' ? Number(pkg.price) : pkg.price,
bonus: pkg.bonus || 0,
priceFormatted: this.formatAtomicHuman(
typeof pkg.price === 'bigint' ? Number(pkg.price) : pkg.price,
2
)
}));
return {
mode: this.gameMode,
cryptoType: this.cryptoType,
@@ -1010,13 +1038,20 @@ class GameModeManager {
isTestNetwork: this.isTestNetwork,
testnetWarning: testnetWarning,
singleGamePrice: this.singleGamePrice,
singleGamePriceFormatted: this.formatAtomicHuman(this.singleGamePrice, 2),
creditsPackagePrice: this.creditsPackagePrice,
creditsPerGame: this.creditsPerGameCost,
creditPackages: creditPackages,
creditsPayoutBaseValue: this.creditsPayoutBaseValue,
paymentsEnabled: this.paymentsEnabled,
directModeEnabled: this.directModeEnabled,
creditsModeEnabled: this.creditsModeEnabled,
directPayoutsEnabled: this.directPayoutMultipliers.escape > 0,
creditsPayoutsEnabled: this.creditsPayoutEnabled,
payoutMultipliers: {
direct: this.directPayoutMultipliers,
credits: this.creditPayoutMultipliers
},
features: {
paymentRequired: this.paymentsEnabled,
creditsSystem: this.creditsModeEnabled,
+36 -10
View File
@@ -47,8 +47,10 @@ class PaymentHandlers {
return;
}
try {
const { gameMode } = data;
const paymentRequest = await this.gameModeManager.createPaymentRequest(socket.id, gameMode);
const { type, packageId } = data;
const paymentType = type || data.gameMode || 'single_game';
const options = { packageId };
const paymentRequest = await this.gameModeManager.createPaymentRequest(socket.id, paymentType, options);
this.io.to(socket.id).emit('payment_created', {
paymentId: paymentRequest.id,
address: paymentRequest.address,
@@ -56,7 +58,7 @@ class PaymentHandlers {
amountFormatted: paymentRequest.amountFormatted,
currency: this.gameModeManager.cryptoType,
package: paymentRequest.package,
gameMode: gameMode
paymentType: paymentType
});
if (this.debugManager.CONSOLE_LOGGING) console.log(`💳 Payment request created for ${socket.id}: ${paymentRequest.amount}`);
} catch (e) {
@@ -66,8 +68,22 @@ class PaymentHandlers {
}
}
async createAndShowPaymentRequest(socket) {
async createAndShowPaymentRequest(socket, options = {}) {
if (!this.gameModeManager) return;
// If both direct and credits modes are enabled, let the user choose
const bothModesEnabled = this.gameModeManager.directModeEnabled && this.gameModeManager.creditsModeEnabled;
const forceShowOptions = options.showOptions === true;
if (bothModesEnabled && !options.paymentType) {
// Send event to show payment options modal on client
this.io.to(socket.id).emit('show_payment_options', {
reason: 'choose_payment_method',
message: 'Choose how you want to play'
});
return;
}
try {
// Ensure payout address exists for modes that may payout (PAID_SINGLE or PAID_CREDITS with payouts)
const mode = this.gameModeManager.gameMode;
@@ -89,16 +105,23 @@ class PaymentHandlers {
// caller (SocketHandlers) will handle user existence; keep method generic
const gameMode = this.gameModeManager.gameMode;
const cryptoType = this.gameModeManager.cryptoType;
let paymentType;
let paymentType = options.paymentType;
let amount;
let description;
if (gameMode === 'PAID_SINGLE') {
paymentType = 'single_game';
// Determine payment type if not specified
if (!paymentType) {
if (gameMode === 'PAID_SINGLE' || this.gameModeManager.directModeEnabled) {
paymentType = 'single_game';
} else if (gameMode === 'PAID_CREDITS') {
paymentType = 'credits_package';
}
}
if (paymentType === 'single_game') {
amount = this.gameModeManager.singleGamePrice;
description = 'Single game entry';
} else if (gameMode === 'PAID_CREDITS') {
paymentType = 'credits_package';
} else if (paymentType === 'credits_package') {
const primaryPackage = this.gameModeManager.getPrimaryCreditPackage();
amount = Number(primaryPackage?.price ?? this.gameModeManager.creditsPackagePrice);
const credits = primaryPackage?.credits ?? this.gameModeManager.creditsPerGameCost * 10;
@@ -108,7 +131,10 @@ class PaymentHandlers {
return;
}
const paymentRequest = await this.gameModeManager.createPaymentRequest(socket.id, paymentType, { reuseExisting: true });
const paymentRequest = await this.gameModeManager.createPaymentRequest(socket.id, paymentType, {
reuseExisting: true,
packageId: options.packageId
});
const reused = !!paymentRequest.reused;
const formattedAmount = paymentRequest.amountFormatted ?? this.gameModeManager.formatAtomicHuman(amount, 3);
let qrDataUrl = null;