Gaming top-up platforms in India (selling Free Fire Diamonds, BGMI UC, Roblox Robux, Steam Wallet codes, and Mobile Legends diamonds) process high-velocity, low-ticket transactions. Traditional payment aggregators like Razorpay, Cashfree, or PayU frequently block gaming top-up merchants due to stringent Merchant Category Codes (MCC 7995/5816), high chargeback rates, and 2-to-3-day escrow holds that disrupt real-time liquidity.
UPIGateway.dev eliminates these barriers through peer-to-peer, direct-to-bank UPI routing. Because payments land directly in your own bank account with 0% platform fee and automated payment verification, you achieve instantaneous diamond delivery without risk of merchant account freezes or escrow clawbacks.
Architecture of an Automated Gaming Top-Up Platform
An automated gaming top-up architecture consists of four streamlined stages designed for sub-minute fulfillment:
- Player Selection: The customer enters their Game Player UID (e.g. Free Fire Player ID) and selects a SKU (e.g. 520 Diamonds).
- Order Generation: Your backend calls /api/create-order on UPIGateway.dev, passing the player UID and SKU in the remarks payload.
- Dynamic QR / Deep Link Checkout: The customer scans the dynamic QR or taps the UPI intent link on mobile to pay the exact amount.
- Instant Webhook & API Credit: Our automated payment verification engine detects the bank credit and dispatches an instant signed Webhook POST to your server, which triggers your game distribution API to credit the diamonds to the player immediately.
Step 1 — Creating the Top-Up Order (Node.js / Express)
When the gamer clicks 'Buy Now', your backend calls the /api/create-order endpoint to generate a unique session:
// Express.js Route: Initiate Gaming Top-Up Order
app.post('/api/topup/initiate', async (req, res) => {
const { playerId, gameSku, amount, customerPhone } = req.body;
if (!playerId || !amount) {
return res.status(400).json({ status: false, message: 'Player ID and amount required' });
}
const orderId = 'TOPUP_' + Date.now() + '_' + Math.floor(Math.random() * 1000);
try {
const upiRes = await fetch('https://upigateway.dev/api/create-order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
user_token: process.env.UPIGATEWAY_USER_TOKEN,
amount: Number(amount),
order_id: orderId,
redirect_url: 'https://gametopup.example.com/status/' + orderId,
remark1: 'UID: ' + playerId,
remark2: 'SKU: ' + gameSku
})
});
const data = await upiRes.json();
if (data.status && data.result) {
// Save pending topup record into your database
await db.collection('orders').insertOne({
orderId,
playerId,
gameSku,
amount,
status: 'PENDING',
createdAt: new Date()
});
return res.json({
status: true,
orderId,
paymentUrl: data.result.payment_url
});
}
return res.status(500).json({ status: false, message: data.message || 'Gateway error' });
} catch (error) {
return res.status(500).json({ status: false, message: error.message });
}
});
Step 2 — Handling the Verification Webhook & Auto-Fulfillment
As soon as the customer authorizes payment in their UPI app, our automated verification engine verifies the transaction with bank records and hits your registered webhook URL. Your server verifies the order status with /api/check-order-status to prevent replay attacks, then triggers game fulfillment:
// Express.js Webhook Receiver: Automated Credit Fulfillment
app.post('/api/topup/webhook', async (req, res) => {
const { order_id, status, utr, amount } = req.body;
// 1. Strict Server-to-Server Verification (Anti-Spoofing Guard)
const verifyRes = await fetch('https://upigateway.dev/api/check-order-status', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
user_token: process.env.UPIGATEWAY_USER_TOKEN,
order_id: order_id
})
});
const verifiedData = await verifyRes.json();
const isVerified = (verifiedData.status === true || verifiedData.status === 'COMPLETED') &&
(verifiedData.result?.status === 'COMPLETED' || verifiedData.result?.status === 'SUCCESS');
if (!isVerified) {
return res.status(400).json({ error: 'Transaction unverified or pending' });
}
// 2. Anti-Replay Check: Ensure order hasn't already been fulfilled
const existingOrder = await db.collection('orders').findOne({ orderId: order_id });
if (!existingOrder || existingOrder.status === 'COMPLETED') {
return res.json({ status: 'ALREADY_PROCESSED' });
}
// 3. Trigger Game Distributor API (Free Fire / BGMI / Steam)
const fulfillmentSuccess = await fulfillGameCredit({
playerId: existingOrder.playerId,
sku: existingOrder.gameSku,
amount: verifiedData.result?.amount || amount
});
if (fulfillmentSuccess) {
await db.collection('orders').updateOne(
{ orderId: order_id },
{ $set: { status: 'COMPLETED', utr: verifiedData.result?.utr || utr, completedAt: new Date() } }
);
return res.json({ status: 'SUCCESS', message: 'Order credited to gamer' });
}
return res.status(500).json({ status: 'FULFILLMENT_FAILED' });
});
Best Practices for Gaming Top-Up Gateways
- Zero-MDR Advantage: Keep 100% of player payments instead of surrendering 2-3% to corporate aggregators.
- Anti-Replay Guards: Always verify the UTR and order status against /api/check-order-status before sending virtual goods.
- Sub-Minute Player Delivery: Keep your webhook handler fast and lightweight so diamonds land in the player's account in under 60 seconds.
- WhatsApp Delivery Notifications: Integrate WAPI to dispatch an automated receipt with player ID and UTR reference number upon successful delivery.