Пошаговое руководство по настройке приёма USDT от пользователей вашей платформы.
Вы — обменник или биржа. Ваши пользователи хотят пополнить баланс в USDT:
- Пользователь запрашивает адрес для пополнения
- Ваша система создаёт уникальный кошелёк
- Пользователь отправляет USDT
- Lumo проводит AML-проверку
- Вы получаете webhook о зачислении
- Без блокчейн-кода — не нужно работать с TRON напрямую
- AML из коробки — автоматическая проверка входящих транзакций
- Автопересылка — средства собираются на вашем treasury
- Webhooks — real-time уведомления
Сначала настройте endpoint для получения уведомлений:
const crypto = require('crypto');
app.post('/webhooks/lumo', (req, res) => {
// Верификация подписи
const signature = req.headers['x-lumo-signature'];
const expected = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
if (signature !== expected) {
return res.status(401).send('Invalid signature');
}
// Обработка события
handleWebhook(req.body);
res.status(200).send('OK');
});
function handleWebhook(payload) {
const { event, externalId, amount, status } = payload;
switch (event) {
case 'deposit.completed':
creditUserBalance(externalId, amount);
break;
case 'deposit.aml_failed':
notifySupport(payload);
break;
}
}Обновите профиль компании:
curl -X PATCH 'https://b2b.lumowallet.io/auth/company/profile' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"webhookUrl": "https://your-server.com/webhooks/lumo"
}'Когда пользователь запрашивает адрес для пополнения:
async function getDepositAddress(userId) {
const response = await fetch('https://b2b.lumowallet.io/user-wallets', {
method: 'POST',
headers: {
'X-API-Key': process.env.LUMO_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
externalId: userId // Ваш внутренний ID пользователя
})
});
const wallet = await response.json();
return wallet.address;
}Ответ:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"companyId": "660e8400-e29b-41d4-a716-446655440001",
"externalId": "user-12345",
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"isBlocked": false,
"lastUsdtBalance": 0,
"createdAt": "2026-03-10T12:00:00Z"
}💡 Идемпотентность: Повторный запрос с тем же
externalIdвернёт существующий кошелёк.
function DepositPage({ userId }) {
const [address, setAddress] = useState(null);
useEffect(() => {
getDepositAddress(userId).then(setAddress);
}, [userId]);
return (
<div>
<h2>Пополнение баланса</h2>
<p>Отправьте USDT (TRC-20) на адрес:</p>
<AddressBox>{address}</AddressBox>
<QRCode value={address} />
<Warning>
⚠️ Отправляйте только USDT в сети TRON (TRC-20)
</Warning>
</div>
);
}Когда пользователь отправляет USDT, вы получаете webhooks:
{
"event": "deposit.created",
"depositId": "770e8400-e29b-41d4-a716-446655440002",
"externalId": "user-12345",
"txHash": "abc123...",
"walletAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"amount": 100.00,
"status": "new"
}Действие: Показать пользователю "Депозит обнаружен, ожидает подтверждения"
{
"event": "deposit.aml_pending",
"depositId": "770e8400-e29b-41d4-a716-446655440002",
"externalId": "user-12345",
"status": "aml_pending"
}Действие: Показать "Проверка безопасности..."
{
"event": "deposit.completed",
"depositId": "770e8400-e29b-41d4-a716-446655440002",
"externalId": "user-12345",
"amount": 100.00,
"status": "completed"
}Действие: Зачислить средства на баланс пользователя
async function creditUserBalance(externalId, amount) {
await db.users.update({
where: { id: externalId },
data: {
balance: { increment: amount },
lastDepositAt: new Date()
}
});
// Уведомить пользователя
await notifyUser(externalId, {
type: 'deposit_success',
amount: amount
});
}При aml_failed:
function handleAmlFailed(payload) {
const { externalId, amount, depositId } = payload;
// Уведомить пользователя
notifyUser(externalId, {
type: 'deposit_blocked',
message: 'Депозит заблокирован для проверки'
});
// Создать тикет для поддержки
createSupportTicket({
type: 'aml_review',
userId: externalId,
depositId: depositId,
amount: amount
});
}async function getUserDeposits(userId) {
const response = await fetch(
`https://b2b.lumowallet.io/user-wallets/deposits?externalId=${userId}`,
{ headers: { 'X-API-Key': process.env.LUMO_API_KEY } }
);
return response.json();
}При подозрительной активности заблокируйте кошелёк:
async function blockUserWallet(walletId, reason) {
await fetch(`https://b2b.lumowallet.io/user-wallets/${walletId}/block`, {
method: 'POST',
headers: {
'X-API-Key': process.env.LUMO_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ reason })
});
}Если пользователь просит новый адрес:
async function replaceUserWallet(walletId) {
const response = await fetch(
`https://b2b.lumowallet.io/user-wallets/${walletId}/replace`,
{
method: 'POST',
headers: {
'X-API-Key': process.env.LUMO_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ reason: 'User requested new address' })
}
);
const newWallet = await response.json();
return newWallet.address; // Новый адрес
}class DepositService {
constructor(apiKey, webhookSecret) {
this.apiKey = apiKey;
this.webhookSecret = webhookSecret;
this.baseUrl = 'https://b2b.lumowallet.io';
}
async getOrCreateWallet(userId) {
const response = await fetch(`${this.baseUrl}/user-wallets`, {
method: 'POST',
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({ externalId: userId })
});
return response.json();
}
verifyWebhook(body, signature) {
const expected = crypto
.createHmac('sha256', this.webhookSecret)
.update(JSON.stringify(body))
.digest('hex');
return signature === expected;
}
async handleWebhook(payload) {
switch (payload.event) {
case 'deposit.completed':
await this.onDepositCompleted(payload);
break;
case 'deposit.aml_failed':
await this.onAmlFailed(payload);
break;
}
}
async onDepositCompleted({ externalId, amount }) {
// Зачисляем баланс
await db.users.increment(externalId, 'balance', amount);
// Уведомляем пользователя
await notifications.send(externalId, {
title: 'Депозит зачислен',
body: `+${amount} USDT`
});
}
async onAmlFailed({ externalId, depositId }) {
await notifications.send(externalId, {
title: 'Депозит на проверке',
body: 'Свяжитесь с поддержкой'
});
}
}- Настроен webhook endpoint
- Webhook URL обновлён в профиле
- Верификация подписи webhook
- Создание кошельков для пользователей
- UI для показа адреса + QR-код
- Обработка
deposit.completed - Обработка
deposit.aml_failed - Зачисление баланса пользователю
- Уведомления пользователю
- Логирование всех событий