You want to accept USDT on your website, SaaS app, or Telegram bot. You don't want to deal with blockchain nodes, wallet management, or building a checkout page from scratch.
This tutorial gets you from zero to a working USDT checkout in under 5 minutes, using IronixPay — a payment gateway for USDT on TRON.
What you'll build: A payment flow where your customer clicks "Pay", sees a checkout page with a TRON address + QR code, sends USDT, and your server gets a webhook when the payment confirms on-chain.
What You Need
- Node.js v18+
- An IronixPay account → Sign up free
That's it. No blockchain node. No wallet. No smart contract.
Step 1: Get Your API Key
- Log in to the IronixPay Dashboard
- Go to API Keys in the sidebar
- Click Create Key → copy it (starts with
sk_test_)
💡 Use
sk_test_keys for development (TRON Nile testnet, free test USDT). Switch tosk_live_for real payments.
Step 2: Create a Checkout Session (Backend)
Your backend creates a session, which generates a unique payment address and checkout URL.
// server.js
const express = require('express');
const app = express();
app.use(express.json());
const IRONIXPAY_SECRET = process.env.IRONIXPAY_SECRET_KEY; // sk_test_...
app.post('/create-checkout', async (req, res) => {
const response = await fetch(
'https://sandbox.ironixpay.com/v1/checkout/sessions',
{
method: 'POST',
headers: {
Authorization: `Bearer ${IRONIXPAY_SECRET}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 10000000, // 10.00 USDT (micro-units: 1 USDT = 1,000,000)
currency: 'USDT',
network: 'TRON',
success_url: 'https://yoursite.com/success',
cancel_url: 'https://yoursite.com/cancel',
client_reference_id: req.body.orderId,
}),
}
);
const session = await response.json();
res.json({ id: session.id, url: session.url });
});
app.listen(3000, () => console.log('Server running on :3000'));
The response gives you:
-
url— hosted checkout page with QR code and payment address -
id— session ID (e.g.cs_abc123...) for tracking
⚠️ Never expose
sk_test_orsk_live_keys in frontend code. Always create sessions from your backend.
Step 3: Send Your Customer to Checkout
document.getElementById('pay-btn').addEventListener('click', async () => {
const res = await fetch('/create-checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ orderId: 'order_001' }),
});
const { url } = await res.json();
window.location.href = url; // → IronixPay checkout page
});
<button id="pay-btn">Pay 10 USDT</button>
💡 Want to embed the checkout inside your own page? Use the
@ironix-pay/sdk— see the Embed Mode guide.
Step 4: Receive the Webhook
When your customer pays, IronixPay sends a session.completed webhook:
const crypto = require('crypto');
const WEBHOOK_SECRET = process.env.IRONIXPAY_WEBHOOK_SECRET; // whsec_...
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-signature'];
const timestamp = req.headers['x-timestamp'];
const payload = req.body.toString();
// 1. Verify signature
const message = `${timestamp}.${payload}`;
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(message)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
// 2. Check timestamp (5-min window)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > 300) {
return res.status(401).send('Timestamp expired');
}
// 3. Process the event
const event = JSON.parse(payload);
if (event.event_type === 'session.completed') {
const { session_id, amount_received } = event.data;
console.log(`✅ Payment received! Session: ${session_id}, Amount: ${amount_received / 1_000_000} USDT`);
// TODO: Mark order as paid in your database
}
res.status(200).send('OK');
});
💡 Go to Dashboard → Developer → Webhooks to set your endpoint URL and copy the signing secret.
Complete Working Example
Copy-paste this server.js:
require('dotenv').config();
const express = require('express');
const crypto = require('crypto');
const app = express();
const SECRET_KEY = process.env.IRONIXPAY_SECRET_KEY;
const WEBHOOK_SECRET = process.env.IRONIXPAY_WEBHOOK_SECRET;
const API_BASE = 'https://sandbox.ironixpay.com';
app.use('/public', express.static('public'));
app.use(express.json());
app.post('/create-checkout', async (req, res) => {
const response = await fetch(`${API_BASE}/v1/checkout/sessions`, {
method: 'POST',
headers: {
Authorization: `Bearer ${SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: req.body.amount || 10000000,
currency: 'USDT',
network: 'TRON',
success_url: `http://localhost:3000/public/success.html`,
cancel_url: `http://localhost:3000/public/cancel.html`,
client_reference_id: req.body.orderId,
}),
});
const session = await response.json();
res.json({ id: session.id, url: session.url });
});
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-signature'];
const ts = req.headers['x-timestamp'];
const body = req.body.toString();
const expected = crypto.createHmac('sha256', WEBHOOK_SECRET)
.update(`${ts}.${body}`).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).send('Bad signature');
}
const event = JSON.parse(body);
console.log(`[Webhook] ${event.event_type}:`, JSON.stringify(event.data, null, 2));
if (event.event_type === 'session.completed') {
console.log(`💰 Order paid: ${event.data.amount_received / 1e6} USDT`);
}
res.sendStatus(200);
});
app.listen(3000, () => console.log('🚀 http://localhost:3000'));
# .env
IRONIXPAY_SECRET_KEY=sk_test_your_key_here
IRONIXPAY_WEBHOOK_SECRET=whsec_your_secret_here
npm install express dotenv
node server.js
Telegram Bot? Same API.
bot.onText(/\/pay/, async (msg) => {
const res = await fetch(`${API_BASE}/v1/checkout/sessions`, {
method: 'POST',
headers: {
Authorization: `Bearer ${SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 5000000,
currency: 'USDT',
network: 'TRON',
success_url: 'https://t.me/your_bot',
cancel_url: 'https://t.me/your_bot',
}),
});
const session = await res.json();
bot.sendMessage(msg.chat.id, `💳 Pay 5 USDT to complete your order:`, {
reply_markup: {
inline_keyboard: [[{ text: '🔗 Pay Now', url: session.url }]],
},
});
});
What Happens Behind the Scenes
Your app creates session → IronixPay generates unique TRON address
↓
Customer sends USDT → on-chain transaction detected
↓
IronixPay confirms → webhook fired to your server
↓
USDT auto-swept to your treasury wallet 💰
You never touch a private key. You never run a blockchain node. IronixPay handles HD wallet derivation, transaction monitoring, and fund sweeping.
Learn More
- 📖 Full API Reference
- 🧪 Testing Guide — sandbox environment
- 🎨 Embed Mode (SDK) — embed checkout in your page
- 🕹️ Live Demo — try the checkout experience
Built with ❤️ by IronixPay — USDT payment gateway for developers.
Top comments (0)