API, совместимый с Coinbase Commerce
Эндпоинты charge, заголовок X-CC-Api-Key, объект charge и вебхуки с подписью X-CC-Webhook-Signature соответствуют документации Coinbase Commerce, поэтому официальные SDK работают после замены одной строки. Coinbase Commerce перестал обслуживать продавцов за пределами США и Сингапура с 2026-03-31. Переходите откуда-то ещё? См. обзор перехода.
Внутри это обычный счёт blockwallets: адреса для приёма ваши, страница оплаты — наша размещённая страница, а платёж засчитывается только после подтверждения в блокчейне и сверки со вторым узлом. Далее: три шага, затем что поддерживает каждый API и чем он отличается от оригинала — параметры, которые мы не реализовали, возвращают ошибку, а не молча игнорируются.
Три шага
- Получите аккаунт продавца (запросите доступ на главной странице) и добавьте свои домены в разделе «Домены сайта» на странице «Разработчикам › Интеграция и ключи» в кабинете. URL уведомлений (
ipn_callback_url) и URL перенаправления (success_url/cancel_url/redirect_url) должны находиться на этих доменах или на домене вашего URL уведомлений — утёкший ключ не сможет направить вебхуки в другое место. - Создайте совместимые учётные данные в кабинете продавца в разделе «Разработчикам › Интеграция и ключи», один набор для live и один для test: для NOWPayments — API key + IPN secret, для Coinbase Commerce — API key + webhook shared secret. Они показываются один раз; мы храним только хеши / шифртекст.
- Направьте код на базовый URL ниже и используйте новые ключи. Сначала запустите его в тестовых сетях с тестовыми учётными данными, затем переключитесь на live.
| До | После | Заголовок авторизации | Подпись вебхука |
|---|---|---|---|
https://api.commerce.coinbase.com | https://blockwallets.io/coinbase/ | X-CC-Api-Key | X-CC-Webhook-Signature (HMAC-SHA256) |
Coinbase Commerce
Все официальные SDK принимают базовый URL — измените одну строку (не забудьте про завершающий /):
// Node(coinbase-commerce-node)
const { Client } = require("coinbase-commerce-node");
- Client.init(process.env.COINBASE_COMMERCE_API_KEY);
+ Client.init(process.env.COINBASE_COMMERCE_API_KEY, "https://blockwallets.io/coinbase/");
# Python(coinbase-commerce)
- client = Client(api_key=API_KEY)
+ client = Client(api_key=API_KEY, base_api_uri="https://blockwallets.io/coinbase/")
// PHP(coinbase/coinbase-commerce)
- ApiClient::init($apiKey);
+ ApiClient::init($apiKey, 'https://blockwallets.io/coinbase/');curl -X POST https://blockwallets.io/coinbase/charges \
-H "X-CC-Api-Key: $COINBASE_COMMERCE_API_KEY" -H "X-CC-Version: 2018-03-22" \
-H "content-type: application/json" \
-d '{"name":"Order #12345","description":"Pro plan","pricing_type":"fixed_price",
"local_price":{"amount":"100.00","currency":"USD"},
"redirect_url":"https://shop.example/success","cancel_url":"https://shop.example/cancel",
"metadata":{"order_id":"12345"}}'
# → 201 {"data": {"id": "…", "code": "7C7V5ECK", "hosted_url": "https://blockwallets.io/pay/inv_…", "timeline": [{"status": "NEW", …}], …}}Поддерживаемые эндпоинты
| Эндпоинт | Примечания |
|---|---|
POST /charges | Создать charge; hosted_url — наша размещённая страница оплаты; действует 1 час |
GET /charges/:code_or_id | Поиск по 8-символьному коду или id |
GET /charges | Список: limit (≤100) / starting_after / ending_before / order, с тем же объектом pagination |
POST /charges/:code_or_id/cancel | Отменить charge, по которому ещё не виден ни один платёж |
Недоступно: /charges/:code/resolve (400 — недоплаченные charge разбирайте в кабинете), /checkouts, /events, /invoices (404).
Вебхуки
Вебхуки Coinbase настраиваются на уровне аккаунта, и наши тоже: они приходят на URL уведомлений, заданный в кабинете (charge, созданные с тестовыми учётными данными, приходят на тестовый URL). Тело — формат Coinbase {id, scheduled_for, attempt_number, event: {id, type, api_version, created_at, data}} с полным charge в data; X-CC-Webhook-Signature = HMAC-SHA256(shared secret, исходное тело), так что Webhook.verifyEventBody из SDK работает без изменений. При повторах event.id остаётся прежним, а attempt_number растёт — убирайте дубликаты по event.id.
import crypto from "node:crypto";
// Same as the SDK's Webhook.verifySigHeader: HMAC-SHA256(shared secret, raw body)
function verifyWebhook(rawBody, sig, sharedSecret) {
const hmac = crypto.createHmac("sha256", sharedSecret).update(rawBody, "utf8").digest("hex");
return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(sig || ""));
}
// verifyWebhook(rawBody, req.headers["x-cc-webhook-signature"], process.env.COINBASE_WEBHOOK_SECRET)
// or with the official SDK:Webhook.verifyEventBody(rawBody, signature, sharedSecret)| Событие | Когда | Последняя запись в timeline |
|---|---|---|
charge:confirmed | Оплачен (подтверждён в блокчейне и сверен; переплата засчитывается) | COMPLETED |
charge:failed | Истёк без оплаты / отменён вами / истёк с недоплатой | EXPIRED / CANCELED / UNRESOLVED (контекст UNDERPAID) |
При запросе вы увидите также NEW (ожидает оплаты) и PENDING (платёж виден в блокчейне, идут подтверждения). Выполняйте заказ по charge:confirmed: события charge:created, charge:pending, charge:delayed и charge:resolved мы не отправляем.
Отличия от Coinbase Commerce
pricing_typeдолжен бытьfixed_price;local_price.currencyдолжна быть USD (USDC / USDT 1:1).no_priceи другие фиатные валюты возвращают 400.- Адрес появляется, когда клиент выбирает монету и сеть на странице оплаты: в
addressesтолько эта сеть, вpricingпосле выбора толькоlocalиsettlement; полейexchange_rates,checkoutи брендинга нет. metadataсохраняется и возвращается как есть (до 4 КБ).- Возвраты в timeline не отображаются; смотрите их в кабинете.
Тестовый режим
Charge и платежи, созданные с тестовыми учётными данными, работают в тестовой сети каждого блокчейна, а их вебхуки подписываются тестовым IPN secret / shared secret — полностью отдельно от live: тестовый ключ не видит live-платежи.
Всё остальное (страница оплаты, подтверждения, сети и минимумы, возвраты) работает так же, как в основной документации.