Интеграция с CoinPayments
CoinPayments — один из старейших криптоплатёжных процессоров с поддержкой 2000+ монет. Для большинства проектов актуальны два сценария: приём платежей через IPN (Instant Payment Notification) и создание транзакций через API.
Аутентификация и базовый запрос
CoinPayments использует HMAC-SHA512 для подписи запросов:
import crypto from "crypto";
import { URLSearchParams } from "url";
const COINPAYMENTS_API = "https://www.coinpayments.net/api.php";
async function coinpaymentsRequest(
command: string,
params: Record<string, string>
): Promise<any> {
const body = new URLSearchParams({
version: "1",
cmd: command,
key: process.env.CP_PUBLIC_KEY!,
format: "json",
...params,
});
const signature = crypto
.createHmac("sha512", process.env.CP_PRIVATE_KEY!)
.update(body.toString())
.digest("hex");
const response = await fetch(COINPAYMENTS_API, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
HMAC: signature,
},
body: body.toString(),
});
const data = await response.json();
if (data.error !== "ok") throw new Error(data.error);
return data.result;
}
Создание транзакции для приёма платежа
async function createTransaction(
amount: string,
currency1: string, // валюта инвойса (USD, EUR)
currency2: string, // крипта для оплаты (BTC, ETH, USDT.ERC20)
orderId: string
) {
return coinpaymentsRequest("create_transaction", {
amount,
currency1,
currency2,
buyer_email: "[email protected]",
item_name: `Order ${orderId}`,
custom: orderId, // вернётся в IPN
ipn_url: `${process.env.BASE_URL}/webhooks/coinpayments`,
});
// Возвращает: { txn_id, address, amount, confirms_needed, timeout, status_url, qrcode_url }
}
Обработка IPN (Instant Payment Notification)
IPN — POST-запрос от CoinPayments на ваш endpoint при изменении статуса платежа. Верификация обязательна:
import express from "express";
const router = express.Router();
router.post("/webhooks/coinpayments", express.urlencoded({ extended: true }), (req, res) => {
// Верифицируем подпись
const hmac = crypto
.createHmac("sha512", process.env.CP_IPN_SECRET!)
.update(new URLSearchParams(req.body).toString())
.digest("hex");
if (hmac !== req.headers["hmac"]) {
return res.status(400).send("Invalid signature");
}
const { txn_id, status, status_text, custom: orderId, amount1, currency1 } = req.body;
// status >= 100 или status == 2 — полное подтверждение
// status >= 0 — в обработке
// status < 0 — ошибка/отмена
if (parseInt(status) >= 100 || parseInt(status) === 2) {
// Кредитовать заказ orderId
processConfirmedPayment(orderId, txn_id, amount1, currency1);
}
res.send("IPN OK"); // CoinPayments ожидает этот ответ
});
Важно: IPN endpoint должен отвечать строкой IPN OK (или любым 200 ответом). Если ответа нет — CoinPayments повторит запрос. Идемпотентность обработки обязательна: сохраняйте txn_id и проверяйте на дублирование.
Статусы платежей
| Статус | Значение |
|---|---|
| -2 | Refund / Dispute |
| -1 | Отменён / Таймаут |
| 0 | Ожидание монет |
| 1 | Получен, но мало подтверждений |
| 2 | Завершён (только для некоторых монет) |
| 3 | Queued for nightly payout |
| 100 | Полностью подтверждён |
Типичные проблемы интеграции
Таймаут транзакции: по умолчанию 2 часа. Пользователь может не успеть. Настраивается параметром hour, максимум 24 часа. При таймауте монеты, если пришли позже, всё равно принимаются как overpaid — обрабатывать отдельно.
IPN не доходит: CoinPayments требует публично доступный URL. Для разработки — ngrok или аналог. В production убедитесь, что firewall не блокирует входящие запросы с IP CoinPayments.
Курсовые разницы: amount1 в IPN — сумма в исходной валюте (USD), amount2 — в крипте. Не ориентируйтесь только на крипто-сумму — курс мог измениться.
Интеграция занимает 2–3 дня с учётом тестирования IPN через тестовые транзакции и обработки edge cases.







