Пути использования и примеры
API CoinVertus на практике: приём оплат, кошелёк в своём сервисе, аналитика сети и клиент на PHP.
Содержание
Адрес API: https://api.coinvertus.net/v1
Пути использования
Три типичных сценария: приём оплат своими силами, кошелёк в собственном сервисе и аналитика по сети. Примеры показывают порядок вызовов; полные поля — в разделах выше.
Как SCI: приём оплат
На каждый заказ — свой адрес через getnewaddress с label = номер заказа. Поступление приходит вебхуком tx.new, подтверждение — tx.confirmed; заказ закрывается по confirmed. Без вебхука сверяйте txinfo. Готовая страница оплаты со счётом и статусами — в интерфейсе SCI.
# Order created: a dedicated address (right: addresses)
POST /v1/getnewaddress/DOGE {"network": "dogecoin-mainnet", "label": "order-1042"}
-> {"coin": "DOGE", "network": "dogecoin-mainnet", "address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD", ...}
# The buyer pays: webhook tx.new, then tx.confirmed
{"event": "tx.confirmed", "transaction": {"txid": "c0c0…", "direction": "in", "status": "confirmed",
"transfers": [{"address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD", "amount": "250"}]}}
# No webhook received: reconcile (right: read)
POST /v1/txinfo/DOGE {"network": "dogecoin-mainnet", "txid": "c0c0…"}Как кошелёк: балансы и отправка
Балансы — getbalance, история — transactions. Перевод: оценка getfee, план preparetx, подтверждение posttx с confirm, затем состояние задачи — task или вебхук task.done. Деньги ушли, только когда задача confirmed.
# Balances and history (right: read)
POST /v1/getbalance/DOGE {"network": "dogecoin-mainnet"}
POST /v1/transactions/DOGE {"network": "dogecoin-mainnet", "page": 1}
# Transfer (right: send)
POST /v1/getfee/DOGE {"network": "dogecoin-mainnet", "to": [{"address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD", "amount": "100"}]}
POST /v1/preparetx/DOGE {"network": "dogecoin-mainnet", "to": [{"address": "D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD", "amount": "100"}], "fee": "normal"}
-> {"prepare_id": "prep_…", "prepare_confirm": "…", "prepare_time": 1789647000, "fingerprint": "…", ...}
POST /v1/posttx {"prepare_id": "prep_…", "confirm": "hex(HMAC-SHA256(secret, key_id.fingerprint.prepare_confirm.prepare_time))"}
-> {"task_id": "task_…", "task_info": "queue", ...}
POST /v1/task/task_… {}
-> {"task_info": "confirmed", "txid": "b7b7…", ...} (or the task.done webhook)Как аналитика: сеть, блоки, адреса
Состояние сети и индекса — chains, lastblock и info; данные — blocks, block, tx и address страницами по 100, курсы — rates. Ключ для этих вызовов не обязателен, если они открыты гостям; с ключом действуют лимиты тарифа.
# Network and index state (key optional when open to guests)
GET /v1/chains
GET /v1/chains/dash/lastblock
GET /v1/chains/dash/info
# Blocks, transactions, addresses: pages of 100
GET /v1/chains/dash/blocks?page=1
GET /v1/chains/dash/block/2371204
GET /v1/chains/dash/tx/e7e7…
GET /v1/chains/dash/address/XcF5mKwWsiv3k394GBQNpYAuk3CVJ48Xnp?direction=in&page=2
# Rates
POST /v1/rates {"coins": ["DASH", "LTC"]}Пример на PHP
Подписанный вызов, план отправки и его подтверждение:
<?php
const CVC_API = 'https://api.coinvertus.net/v1';
function cvcCall(string $method, array $params = []): array
{
$keyId = getenv('CVC_API_KEY_ID');
$secret = getenv('CVC_API_SECRET');
$path = '/v1/' . $method;
$body = $params === [] ? '' : json_encode($params, JSON_UNESCAPED_SLASHES);
$t = time();
$v1 = hash_hmac('sha256', $t . '.POST.' . $path . '.' . $body, $secret);
$curl = curl_init(CVC_API . '/' . $method);
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-CVC-Key: ' . $keyId,
'X-CVC-Signature: t=' . $t . ',v1=' . $v1,
],
]);
$response = json_decode((string) curl_exec($curl), true);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
throw new RuntimeException($status . ' ' . ($response['error']['code'] ?? '') . ' ' . ($response['error']['message'] ?? ''));
}
return $response;
}
$balances = cvcCall('getbalance/DOGE');
$plan = cvcCall('preparetx/DOGE', [
'to' => [['address' => 'D8vFz4p1L37jdg47HXKtSHA5uYLYxbGgPD', 'amount' => '100']],
]);
// Проверьте план: получатели, network_fee, service_fee_usd — и подтвердите его.
$confirm = hash_hmac('sha256', getenv('CVC_API_KEY_ID') . '.' . $plan['fingerprint'] . '.'
. $plan['prepare_confirm'] . '.' . $plan['prepare_time'], getenv('CVC_API_SECRET'));
$task = cvcCall('posttx', ['prepare_id' => $plan['prepare_id'], 'confirm' => $confirm]);
// Итог — вебхук task.done или опрос task/{TASK_ID}.
$task = cvcCall('task/' . $task['task_id']);Приём вебхука:
<?php
$secret = getenv('CVC_API_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$t = null;
$signatures = [];
foreach (explode(',', $_SERVER['HTTP_X_CVC_SIGNATURE'] ?? '') as $pair) {
[$name, $value] = array_pad(explode('=', trim($pair), 2), 2, '');
if ($name === 't') {
$t = $value;
} elseif ($name === 'v1') {
$signatures[] = strtolower($value);
}
}
$expected = hash_hmac('sha256', $t . '.' . $body, $secret);
$valid = $t !== null && ctype_digit($t) && abs(time() - (int) $t) <= 300
&& array_filter($signatures, fn (string $v1): bool => hash_equals($expected, $v1)) !== [];
if (!$valid) {
http_response_code(400);
exit;
}
$hook = json_decode($body, true);
if (!$events->remember($hook['event_id'])) {
http_response_code(200);
exit;
}
switch ($hook['event']) {
case 'tx.new':
case 'tx.confirmed':
case 'tx.dropped':
$ledger->apply($hook['transaction']);
break;
case 'task.done':
$payouts->finish($hook['task']['task_id'], $hook['task']['task_info'], $hook['task']['txid']);
break;
case 'paybalance.low':
$alerts->notify($hook['reason'], $hook['paybalance']['usd']);
break;
}
http_response_code(200);Расшифровка privkey из getnewaddress:
<?php
$raw = base64_decode($response['privkey']);
$key = hash_hmac('sha256', 'privkey', getenv('CVC_API_SECRET'), true);
$privkey = openssl_decrypt(substr($raw, 12, -16), 'aes-256-gcm', $key, OPENSSL_RAW_DATA,
substr($raw, 0, 12), substr($raw, -16));Пример упрощён: при 429 и 503 повторяйте запрос с паузой, ошибки разбирайте по коду.