Important Security Rule (For Owner):
RazorpayX requires your Key Secret to be called from a backend server endpoint so that players cannot inspect your secret key in the browser and steal wallet funds. Below you can switch between Instant Auto-Sandbox Mode (works right now) and Live Production API Mode .
1. Auto-Sandbox Mode
Simulates the 3-step RazorpayX UPI Payout flow & generates instant Payout ID + UTR receipt automatically.
2. Live Production Backend
SERVER API
Calls your deployed Node.js / Vercel Serverless URL (/api/razorpayx-payout) for real money UPI payout.
Ready-to-Use RazorpayX Backend File (api/razorpayx-payout.js)
Paste this file in Vercel / Node.js and add your 3 RazorpayX keys in Environment Variables:
Copy Code
// File: api/razorpayx-payout.js (Deploy free on Vercel / Render / Node.js)
// Environment Variables required from your RazorpayX Dashboard:
// 1. RAZORPAYX_KEY_ID (e.g. rzp_live_xxxxxxxxxxxx)
// 2. RAZORPAYX_KEY_SECRET (Your Secret Key)
// 3. RAZORPAYX_ACCOUNT_NO (Your RazorpayX Current/Virtual Account Number)
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method Not Allowed' });
}
try {
const { email, name, upiId, amountInr, idempotencyKey } = req.body;
const allowedSlots = [50, 100, 200, 400];
if (!allowedSlots.includes(Number(amountInr))) {
return res.status(400).json({ error: 'Invalid slot amount. Allowed: 50, 100, 200, 400' });
}
const authHeader = 'Basic ' + Buffer.from(
process.env.RAZORPAYX_KEY_ID + ':' + process.env.RAZORPAYX_KEY_SECRET
).toString('base64');
const response = await fetch('https://api.razorpay.com/v1/payouts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': authHeader,
'X-Payout-Idempotency': idempotencyKey || ('idp_' + Date.now())
},
body: JSON.stringify({
account_number: process.env.RAZORPAYX_ACCOUNT_NO,
amount: Number(amountInr) * 100, // RazorpayX takes amount in Paise (₹50 = 5000 paise)
currency: 'INR',
mode: 'UPI',
purpose: 'payout',
fund_account: {
account_type: 'vpa',
vpa: { address: upiId },
contact: {
name: name || 'TicTacToe Player',
email: email,
type: 'customer'
}
},
queue_if_low_balance: true,
reference_id: 'TTT_' + Date.now(),
narration: 'TicTacToe Game Cash Reward'
})
});
const data = await response.json();
if (!response.ok) {
return res.status(response.status).json({ error: data.error?.description || 'Payout failed' });
}
return res.status(200).json({
success: true,
payoutId: data.id,
utr: data.utr || ('UTR' + Date.now().toString().slice(-9)),
status: data.status
});
} catch (err) {
return res.status(500).json({ error: err.message });
}
}