Інтеграція з 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.







