Розробка White-label платіжного шлюзу
White-label шлюз — це не просто "платіжний шлюз з чужим логотипом". Це повнофункціональна платіжна платформа, яку клієнт продає під своїм брендом своїм клієнтам. Це змінює всю архітектуру: потрібна мультиарендність, ізоляція даних між мерчантами, API для партнерської інтеграції, біллинг по використанню, white-label UI kit.
Архітектурні рівні
┌─────────────────────────────────────────────────────┐
│ White-label клієнт (Tenant) │
│ Власний домен, логотип, кольори │
├─────────────────────────────────────────────────────┤
│ Merchant Layer │
│ Мерчанти створюють платіжні посилання, API ключі│
├─────────────────────────────────────────────────────┤
│ Core Gateway Engine │
│ Мультисеть, мониторинг, підтвердження, webhook │
├─────────────────────────────────────────────────────┤
│ Blockchain Infrastructure │
│ Ноди / RPC провайдери по кожній мережі │
└─────────────────────────────────────────────────────┘
Кожний tenant має: окремий домен (або поддомен), брандований checkout UI, ізольовані HD wallet деривації, окремий біллинг.
Мультиарендність та ізоляція
Стратегія деривації адрес
Кожний tenant отримує власний master xpub, з якого деривуються адреси його мерчантів та їхніх замовлень. Структура шляху деривації:
m / purpose' / coin_type' / tenant_id' / merchant_id / order_index
Приклад для EVM-мереж:
import { HDNodeWallet } from "ethers";
class TenantWalletManager {
private masterNode: HDNodeWallet;
constructor(masterMnemonic: string) {
this.masterNode = HDNodeWallet.fromPhrase(masterMnemonic);
}
getTenantXpub(tenantId: number): string {
// Деривуємо на рівні tenant — отдаємо xpub, не приватний ключ
return this.masterNode
.deriveChild(44 + 0x80000000) // purpose 44'
.deriveChild(60 + 0x80000000) // ETH coin_type 60'
.deriveChild(tenantId + 0x80000000) // tenant (hardened)
.neuter()
.extendedKey; // публічний xpub
}
getDepositAddress(tenantXpub: string, merchantId: number, orderIndex: number): string {
const tenantNode = HDNodeWallet.fromExtendedKey(tenantXpub);
return tenantNode
.deriveChild(merchantId)
.deriveChild(orderIndex)
.address;
}
}
Це дозволяє tenant'ю самостійно верифікувати адреси (у нього є власний xpub), але не отримати контроль над master-ключами.
Ізоляція даних у PostgreSQL
Схема з row-level security замість окремих баз даних (простіше в операціях):
-- RLS політики для ізоляції тенантів
ALTER TABLE payments ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON payments
USING (tenant_id = current_setting('app.tenant_id')::uuid);
-- У кожному запиті виставляємо контекст
SET LOCAL app.tenant_id = '...';
Для високонавантажених платформ (100+ тенантів з великим обсягом) — окрема PostgreSQL схема на tenant через search_path.
API для мерчантів
Мерчанти інтегруються через REST API, аналогічно Stripe/PayPal. Аутентифікація через API ключі (публічний + секретний):
// Створення платіжного інвойсу
// POST /api/v1/invoices
{
"amount": "99.99",
"currency": "USD",
"accepted_coins": ["ETH", "USDT_ERC20", "BTC"],
"order_id": "order_123", // ваш внутрішній ID
"customer_email": "[email protected]",
"success_url": "https://shop.example.com/success",
"cancel_url": "https://shop.example.com/cancel",
"metadata": { "product_id": "456" },
"expires_in": 900 // секунди (15 хвилин)
}
// Відповідь
{
"invoice_id": "inv_abc123",
"checkout_url": "https://pay.whitelabel.com/i/inv_abc123",
"status": "pending",
"expires_at": "2024-01-15T10:45:00Z",
"payment_options": [
{
"coin": "ETH",
"address": "0x...",
"amount": "0.02941",
"rate": "3400.00",
"rate_expires_at": "2024-01-15T10:45:00Z"
}
]
}
Webhook система
Вебхуки повинні бути надійними — retry логіка, підписи, дедупліка:
interface WebhookEvent {
id: string; // унікальний ID подій
type: "payment.confirmed" | "payment.failed" | "payment.expired";
created_at: string;
data: {
invoice_id: string;
amount_paid: string;
currency_paid: string;
txhash: string;
confirmations: number;
};
}
// Підпис: HMAC-SHA256(webhookSecret, `${timestamp}.${JSON.stringify(payload)}`)
// Заголовок: X-Signature: t=1705312200,v1=abcdef...
Retry schedule при неуспішній доставці: 1хв → 5хв → 30хв → 2год → 8год → 24год. Після 6 неудачних спроб — помічаємо як failed, dashboard мерчанта показує failed webhooks з можливістю ручного retry.
Checkout UI як white-label компонент
Фронтенд має підтримувати повну кастомізацію під бренд тенанта:
// Конфігурація тенанта з БД
interface TenantTheme {
primaryColor: string;
logoUrl: string;
fontFamily: string;
borderRadius: "none" | "sm" | "md" | "lg" | "full";
darkMode: boolean;
}
// Next.js додаток з динамічним CSS
// При завантаженні checkout сторінки — запит теми тенанта
// CSS variables інжектуються в <head>
const theme = await getTenantTheme(tenantId);
const css = `
:root {
--color-primary: ${theme.primaryColor};
--border-radius: ${borderRadiusMap[theme.borderRadius]};
--font-family: ${theme.fontFamily};
}
`;
Компоненти: вибір монети → QR-код з адресою → countdown таймер → статус підтверджень → success/fail екран.
Custom domain: кожен tenant може підключити свій домен (pay.theirclient.com). Реалізується через Cloudflare for SaaS або nginx з автоматичним Let's Encrypt через Caddy.
Біллинг тенантів
Моделі монетизації:
| Модель | Реалізація |
|---|---|
| Процент від обсягу | Утримання X% при sweep на hot wallet |
| Фіксована плата за транзакцію | Додавання fee до суми інвойсу або вичитання при sweep |
| Subscription | Щомісячна плата, доступ до API |
| Комбінована | Subscription + reduced transaction fee |
Sweep з вичитанням fee:
async function sweepWithFee(depositAddress: string, amount: bigint, tenantId: string) {
const tenant = await getTenant(tenantId);
const feeRate = tenant.feeRate; // наприклад 0.01 = 1%
const fee = amount * BigInt(Math.floor(feeRate * 10000)) / 10000n;
await sendTransaction(PLATFORM_FEE_WALLET, fee);
await sendTransaction(tenant.hotWallet, amount - fee);
}
Безпека та compliance
API Key management: генерація через crypto.randomBytes(32).toString('hex'), зберігання тільки хешованого значення в БД (sha256), показуємо один раз при створенні.
Rate limiting: окремі ліміти на кожен API ключ, можливість настройки тенантом через dashboard. Redis + sliding window алгоритм.
IP whitelist: мерчанти можуть обмежити API ключ конкретними IP. Обов'язково для production інтеграцій.
Audit log: всі адміністративні дії тенанта (створення/відзив ключів, зміна настроєк, запити на вивід) логуються в immutable таблицю.
AML: опціональна інтеграція з Chainalysis або Elliptic для перевірки адрес відправників по санкційним спискам. Актуально якщо платформа працює в регульованих юрисдикціях.
Інфраструктура
Load Balancer (nginx/Caddy)
├── API Gateway (Node.js/Fastify)
├── Checkout Frontend (Next.js)
└── Admin Dashboard (Next.js)
Background Services
├── Block Monitor Workers (по одному на мережу)
├── Confirmation Tracker
├── Sweep Worker
├── Webhook Delivery Worker
└── Rate Sync Worker (ціни)
Data Layer
├── PostgreSQL (primary + read replicas)
├── Redis (caches, queues, rate limits)
└── S3-compatible (логи, експорти)
Терміни розробки
| Компонент | Термін |
|---|---|
| Core gateway engine (мониторинг, підтвердження, sweep) | 1–2 нед |
| Merchant API + webhook система | 1 нед |
| Checkout UI з white-label темізацією | 1 нед |
| Tenant management + біллинг | 1 нед |
| Admin dashboard для тенантів | 1–2 нед |
| Custom domain + SSL автоматизація | 3–5 днів |
| Тестування, security review, hardening | 1–2 нед |
Мінімальний термін від нуля до production-ready MVP: 6–8 тижнів. З підтримкою 5–6 мереж, брандованим checkout, webhook системою і базовим dashboard. Повнофункціональна платформа з enterprise фічами — 3 місяці.







