crystalpayio-sdk
v1.0.1
Published
TypeScript SDK for CrystalPay.io payment system — invoices, payoffs, swaps, transfers, and more
Maintainers
Readme
crystalpayio-sdk
Типизированный TypeScript/Node.js SDK для CrystalPay.io — платёжной системы с поддержкой криптовалют и карт.
Покрывает весь API v3: инвойсы, выводы, обмены, переводы, балансы, методы, курсы валют, историю и callback.
Установка
npm install crystalpayio-sdk
# или
bun add crystalpayio-sdk
# или
yarn add crystalpayio-sdk
# или
pnpm add crystalpayio-sdkБыстрый старт
import { CrystalPayClient } from 'crystalpayio-sdk';
const client = new CrystalPayClient({
login: 'your_login',
secret: 'your_secret',
salt: 'your_salt',
});
// Создать инвойс
const invoice = await client.invoice.create({
amount: 500,
type: 'purchase',
lifetime: 30,
description: 'Оплата заказа #42',
});
console.log(invoice.url); // ссылка на страницу оплатыКонфигурация
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
| login | string | Да | Логин кассы (auth_login) |
| secret | string | Да | Секретный ключ (auth_secret) |
| salt | string | Да | Соль для генерации подписей операций |
| baseUrl | string | Нет | Базовый URL API. По умолчанию https://api.crystalpay.io/v3/ |
Где взять ключи: зарегистрируйтесь в @CrystalPAY_bot и создайте кассу.
Модули
client.me — Информация о кассе
const info = await client.me.info();
// { id, name, status_level, created_at }client.balance — Балансы
// Все методы (hideEmpty — скрыть нулевые)
const { items } = await client.balance.list(true);
// Один метод
const btc = await client.balance.get('BITCOIN');
console.log(btc.amount, btc.currency); // "0.0012" "BTC"client.method — Методы оплаты
// Полный список с комиссиями и лимитами
const { items } = await client.method.list();
// Компактный список
const { items: compact } = await client.method.list({ compact: true });
// Один метод
const method = await client.method.get('USDTTRC');
console.log(method.out.limits.min, method.out.limits.max);
// Изменить настройки (включение / доп. комиссия)
await client.method.edit({
method: 'USDTTRC',
enabled: true,
extra_commission_percent: 2,
});client.invoice — Инвойсы (входящие платежи)
Создание
// Фиксированный платёж (покупатель платит точную сумму)
const invoice = await client.invoice.create({
amount: 500,
type: 'purchase',
lifetime: 30, // минут
currency: 'RUB', // по умолчанию RUB
subtract_from: 'amount', // 'amount' | 'balance'
required_method: 'USDTTRC', // предустановить метод (опционально)
description: 'Заказ #42',
extra: 'order_42', // вернётся в callback
redirect_url: 'https://yourshop.com/success',
callback_url: 'https://yourshop.com/webhooks/crystalpay',
});
console.log(invoice.id);
console.log(invoice.url);
// Пополнение баланса (покупатель может заплатить любую сумму, инвойс пересчитается)
// amount задаёт начальную сумму — должна быть > 0
const topup = await client.invoice.create({
amount: 100,
type: 'topup',
lifetime: 60,
callback_url: 'https://yourshop.com/webhooks/crystalpay',
});Проверка статуса
const info = await client.invoice.info('123456789_abcdefghij');
console.log(info.state); // 'created' | 'notpayed' | 'payed' | ...
console.log(info.balance_amount); // сколько будет зачислено на баланс
console.log(info.remaining_amount); // сколько ещё нужно оплатитьВозможные статусы: created, notpayed, processing, wrongamount, failed, payed✓, unavailable✓
client.payoff — Выводы средств
Подписи SHA1 вычисляются автоматически из salt.
// 1. Создать заявку
const payoff = await client.payoff.create({
method: 'USDTTRC',
wallet: 'TYourWalletAddress',
amount: 50,
subtract_from: 'balance', // комиссия поверх суммы
callback_url: 'https://yoursite.com/webhooks/crystalpay',
extra: 'withdrawal_99',
});
console.log(payoff.id);
console.log(payoff.receive_amount); // получит адресат
console.log(payoff.deduction_amount); // спишется с баланса
// 2. Подтвердить
const result = await client.payoff.submit(payoff.id);
console.log(result.state); // 'processing'
// 3. Статус
const info = await client.payoff.info(payoff.id);
console.log(info.state); // 'payed' | 'failed' | 'canceled'
console.log(info.message); // TX-хэш при успехе
// Отменить (если ещё не обработан)
await client.payoff.cancel(payoff.id);Возможные статусы: created, processing, failed✓, payed✓, canceled✓
client.swap — Обмен между счетами
Подписи SHA1 вычисляются автоматически из salt.
// Список пар обмена
const { items } = await client.swap.pairList({
page: 1,
items: 20,
source: 'CARDRUBP2P', // фильтр (опционально)
target: 'USDTTRC',
});
// Конкретная пара
const pair = await client.swap.pairGet(1);
console.log(pair.price); // курс
// Создать заявку
const swap = await client.swap.create({
pair_id: 1,
amount: 1000,
amount_type: 'source', // 'source' — сколько отдаём, 'target' — сколько получаем
});
console.log(swap.source.amount, swap.source.currency); // отдаём
console.log(swap.target.amount, swap.target.currency); // получаем
// Подтвердить
const result = await client.swap.submit(swap.id);
// Отменить / статус
await client.swap.cancel(swap.id);
const info = await client.swap.info(swap.id);Возможные статусы: created, processing, failed✓, success✓, canceled✓
client.transfer — Переводы между кассами
Подписи SHA1 вычисляются автоматически из salt.
// Создать перевод
const transfer = await client.transfer.create({
method: 'USDTTRC',
amount: 25,
receiver: 'partner_login',
description: 'Партнёрская выплата',
});
// Подтвердить
await client.transfer.submit(transfer.id);
// Статус / отмена
const info = await client.transfer.info(transfer.id);
await client.transfer.cancel(transfer.id);client.ticker — Курсы валют
// Список поддерживаемых тикеров
const { tickers } = await client.ticker.list();
// ['BTC', 'ETH', 'USDT', 'TON', 'RUB', ...]
// Курсы к базовой валюте (по умолчанию RUB)
const rates = await client.ticker.get({
tickers: ['BTC', 'ETH', 'USDT', 'TON'],
base_currency: 'RUB',
});
for (const [ticker, { price }] of Object.entries(rates.currencies)) {
console.log(`1 ${ticker} = ${price.toLocaleString()} RUB`);
}client.report — История и статистика
// История инвойсов за 7 дней
const { items, has_next_page } = await client.report.invoiceHistory({
page: 1,
items: 50,
period: 7,
});
// Статистика за 30 дней
const summary = await client.report.invoiceSummary({ period: 30 });
console.log(summary.payed_count, summary.conversion_percent + '%');
// Аналогично для выводов, обменов и переводов:
await client.report.payoffHistory({ page: 1, items: 20, period: 30 });
await client.report.payoffSummary({ period: 30 });
await client.report.swapHistory({ page: 1, items: 20, period: 30 });
await client.report.transferHistory({ page: 1, items: 20, period: 30 });client.callback — Callback-уведомления
// Список попыток доставки callback для инвойса
const { items } = await client.callback.invoiceList('123456789_abcdefghij');
for (const cb of items) {
console.log(cb.state, cb.attempts, cb.last_response);
}
// Принудительно переотправить
await client.callback.invoiceResend('123456789_abcdefghij');
// То же для выводов
await client.callback.payoffList('123456789_dpWminAiaqwTcBOJVlFk');
await client.callback.payoffResend('123456789_dpWminAiaqwTcBOJVlFk');Обработка ошибок
import { CrystalPayClient, CrystalPayError, CrystalPayNetworkError } from 'crystalpayio-sdk';
try {
await client.invoice.create({ ... });
} catch (err) {
if (err instanceof CrystalPayError) {
// Ошибка от API (неверные параметры, недостаточно прав и т.д.)
console.error(err.errors); // string[]
} else if (err instanceof CrystalPayNetworkError) {
// Сетевая ошибка (нет соединения, таймаут)
console.error(err.message, err.cause);
} else {
throw err;
}
}Верификация callback-уведомлений
CrystalPay отправляет POST-запрос на callback_url после завершения операции. Проверяйте подпись перед обработкой:
import { verifyCallbackSignature } from 'crystalpayio-sdk';
import type { InvoiceCallbackPayload } from 'crystalpayio-sdk';
// В вашем HTTP-обработчике (Express, Fastify, Hono и т.д.)
app.post('/webhooks/crystalpay', (req, res) => {
const body = req.body as InvoiceCallbackPayload;
// Проверяем SHA1({id}:{salt})
if (!verifyCallbackSignature(body.id, 'your_salt', body.signature)) {
return res.status(403).send('Invalid signature');
}
if (body.state === 'payed') {
console.log('Оплачен инвойс:', body.id);
console.log('extra (ваш ID заказа):', body.extra);
console.log('Зачислено:', body.balance_amount, body.amount_currency);
// ... начислить баланс, обновить заказ
}
res.status(200).send('OK');
});IP-адреса CrystalPay для белого списка:
193.141.53.171 193.141.53.176
191.101.112.123 191.101.112.154
185.168.250.38 163.198.213.130Подписи операций
SDK автоматически генерирует подписи при создании и подтверждении secure-операций. Соль (salt) задаётся один раз в конфиге клиента.
| Операция | Формат |
|---|---|
| Создание вывода | SHA1({amount}:{method}:{wallet}:{salt}) |
| Подтверждение / отмена вывода | SHA1({id}:{salt}) |
| Создание обмена | SHA1({amount}:{pair_id}:{salt}) |
| Подтверждение / отмена обмена | SHA1({id}:{salt}) |
| Создание перевода | SHA1({amount}:{method}:{receiver}:{salt}) |
| Подтверждение / отмена перевода | SHA1({id}:{salt}) |
Если нужна ручная генерация:
import { sha1, signPayoffCreate, signById } from 'crystalpayio-sdk';
const sig = signPayoffCreate(50, 'USDTTRC', 'TYourWallet', 'your_salt');
const submitSig = signById('123456789_dpWminAiaqwTcBOJVlFk', 'your_salt');Лимиты API
| Лимит | Значение | |---|---| | Запросов в секунду | 5 | | Запросов за 10 секунд | 50 |
При превышении API возвращает 429 Too Many Requests.
