# Приём депозитов для обменников Пошаговое руководство по настройке приёма USDT от пользователей вашей платформы. ## Сценарий Вы — обменник или биржа. Ваши пользователи хотят пополнить баланс в USDT: 1. Пользователь запрашивает адрес для пополнения 2. Ваша система создаёт уникальный кошелёк 3. Пользователь отправляет USDT 4. Lumo проводит AML-проверку 5. Вы получаете webhook о зачислении ## Преимущества - **Без блокчейн-кода** — не нужно работать с TRON напрямую - **AML из коробки** — автоматическая проверка входящих транзакций - **Автопересылка** — средства собираются на вашем treasury - **Webhooks** — real-time уведомления ## Шаг 1: Настройка webhook Сначала настройте endpoint для получения уведомлений: ```javascript 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; } } ``` Обновите профиль компании: ```bash 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" }' ``` ## Шаг 2: Создание кошелька для пользователя Когда пользователь запрашивает адрес для пополнения: ```javascript 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; } ``` Ответ: ```json { "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` вернёт существующий кошелёк. ## Шаг 3: Показ адреса пользователю ```jsx function DepositPage({ userId }) { const [address, setAddress] = useState(null); useEffect(() => { getDepositAddress(userId).then(setAddress); }, [userId]); return (

Пополнение баланса

Отправьте USDT (TRC-20) на адрес:

{address} ⚠️ Отправляйте только USDT в сети TRON (TRC-20)
); } ``` ## Шаг 4: Обработка депозита Когда пользователь отправляет USDT, вы получаете webhooks: ### 4.1 Депозит обнаружен ```json { "event": "deposit.created", "depositId": "770e8400-e29b-41d4-a716-446655440002", "externalId": "user-12345", "txHash": "abc123...", "walletAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", "amount": 100.00, "status": "new" } ``` Действие: Показать пользователю "Депозит обнаружен, ожидает подтверждения" ### 4.2 AML-проверка ```json { "event": "deposit.aml_pending", "depositId": "770e8400-e29b-41d4-a716-446655440002", "externalId": "user-12345", "status": "aml_pending" } ``` Действие: Показать "Проверка безопасности..." ### 4.3 Депозит завершён ```json { "event": "deposit.completed", "depositId": "770e8400-e29b-41d4-a716-446655440002", "externalId": "user-12345", "amount": 100.00, "status": "completed" } ``` Действие: Зачислить средства на баланс пользователя ```javascript 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 }); } ``` ## Шаг 5: Обработка AML-блокировок При `aml_failed`: ```javascript function handleAmlFailed(payload) { const { externalId, amount, depositId } = payload; // Уведомить пользователя notifyUser(externalId, { type: 'deposit_blocked', message: 'Депозит заблокирован для проверки' }); // Создать тикет для поддержки createSupportTicket({ type: 'aml_review', userId: externalId, depositId: depositId, amount: amount }); } ``` ## Шаг 6: Просмотр истории депозитов ```javascript 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(); } ``` ## Блокировка кошелька При подозрительной активности заблокируйте кошелёк: ```javascript 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 }) }); } ``` ## Замена кошелька Если пользователь просит новый адрес: ```javascript 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; // Новый адрес } ``` ## Полный пример ```javascript 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` - [ ] Зачисление баланса пользователю - [ ] Уведомления пользователю - [ ] Логирование всех событий