Приложение на Python принимает криптовалюту через CryptoLike в три шага: подписать каждый запрос к API стандартными модулями hmac и hashlib, создать платёж по заказу и проверить подписанный вебхук, прежде чем отметить заказ оплаченным. В примерах — requests и Flask; та же логика подходит для Django, FastAPI и других фреймворков.
Магазину на WooCommerce, OpenCart, PrestaShop или Magento 2 код не нужен — смотрите интеграции. Это руководство — для собственного бэкенда.
Что понадобится
Аккаунт CryptoLike, Python 3.10 или новее и публичный адрес https:// для вебхуков. Секреты держите в окружении: в примерах это CRYPTOLIKE_API_KEY_ID, CRYPTOLIKE_API_SECRET и CRYPTOLIKE_WEBHOOK_SECRET, а также CRYPTOLIKE_API_URL для тестового адреса API (без него — рабочий). Начинайте с тестовых ключей и тестовых сетей.
1. Создайте тестовый API-ключ
В кабинете откройте Разработчикам → API-ключи → Создать ключ с правами create_invoice и read. Ключ ck_test_ работает с тестовыми сетями, где монеты ничего не стоят. Тестовые ключи выдаёт тестовая среда: поддержка CryptoLike даст доступ к её кабинету, где вы создадите такой же ключ, и адрес её API (CRYPTOLIKE_API_URL в примерах). Рабочий кабинет выпускает только боевые ключи, а в основных сетях тестовый ключ получает 401 auth.test_key. Секрет показывается один раз — сразу положите его в окружение или менеджер секретов.
2. Подписывайте запросы через hmac
Подпись — HMAC-SHA256 от четырёх строк: времени Unix в секундах, метода, пути с query и SHA-256 тела, с ключом — API-секретом:
import hashlib, hmac, json, os, time
import requests
def cryptolike(method: str, path: str, payload: dict | None = None, idempotency_key: str | None = None) -> dict:
body = b"" if payload is None else json.dumps(payload, separators=(",", ":")).encode()
ts = str(int(time.time()))
canonical = "\n".join([ts, method.upper(), path, hashlib.sha256(body).hexdigest()])
headers = {
"X-API-Key": os.environ["CRYPTOLIKE_API_KEY_ID"],
"X-Timestamp": ts,
"X-Signature": hmac.new(os.environ["CRYPTOLIKE_API_SECRET"].encode(), canonical.encode(), hashlib.sha256).hexdigest(),
"Content-Type": "application/json",
}
if idempotency_key:
headers["Idempotency-Key"] = idempotency_key
r = requests.request(method, os.environ.get("CRYPTOLIKE_API_URL", "https://api.cryptolike.net") + path, data=body or None, headers=headers, timeout=30)
data = r.json()
if r.status_code >= 400:
raise RuntimeError(f"{data.get('error', {}).get('code', r.status_code)}: {data.get('error', {}).get('message', '')}")
return dataОтправляйте те же байты, что хешировали: data=body, а не json=payload, который сериализует тело заново. Сверьте функцию с эталонным вектором из раздела аутентификация API.
3. Создайте платёж по заказу
Создавайте платёж на сервере в момент оформления заказа. Укажите цену в USD или EUR и дайте покупателю выбрать монету или передайте coin_id из GET /v1/currencies. Без coin_id страница покажет монеты, доступные для инвойсов, с ориентировочной суммой ≈ у каждой; добавьте allowed_coin_ids (id с invoice_enabled: true из подписанного GET /v1/currencies), чтобы предложить только часть из них. Номер заказа как ключ идемпотентности вернёт тот же платёж при повторе:
invoice = cryptolike("POST", "/v1/invoices", {
"amount": "49.90",
"currency": "USD",
"order_id": order.id,
"idempotency_by_order_id": True,
"return_url": f"https://example.com/orders/{order.id}",
}, idempotency_key=f"order-{order.id}")
order.invoice_id = invoice["id"]Храните суммы строками или Decimal — никогда не float.
4. Отправьте покупателя на страницу оплаты
Перенаправьте на invoice["checkout_url"] (во Flask — redirect(invoice["checkout_url"], code=303)). На странице видны сумма, сеть, адрес с QR-кодом, оставшееся время и статус в реальном времени, а после оплаты покупатель вернётся на return_url. Чтобы он не уходил с сайта, встройте страницу виджетом оплаты.
5. Проверьте вебхук во Flask
Добавьте вебхук-эндпоинт в разделе Разработчикам → Вебхуки с событиями invoice.*. Проверяйте подпись по сырому телу из request.get_data(), отсеивайте повторы по event_id и отвечайте быстро:
from flask import Flask, request
app = Flask(__name__)
@app.post("/webhooks/cryptolike")
def cryptolike_webhook():
raw = request.get_data()
ts = request.headers.get("X-Timestamp", "")
got = request.headers.get("X-Signature", "")
secret = os.environ.get("CRYPTOLIKE_WEBHOOK_SECRET", "")
want = "sha256=" + hmac.new(secret.encode(), ts.encode() + b"." + raw, hashlib.sha256).hexdigest()
if not secret or not ts.isdigit() or abs(time.time() - int(ts)) > 300 or not hmac.compare_digest(got, want):
return "", 401
event = json.loads(raw)
if first_time(event["event_id"]) and event["type"] == "invoice.paid":
mark_order_paid(event["data"]["invoice"]["order_id"])
return "", 200Доставка — «хотя бы один раз», и порядок может нарушаться: опирайтесь на статус внутри data. Полная процедура — в руководстве по проверке подписи вебхуков.
6. Проверьте в тестовой сети и запускайте
Создайте платёж тестовым ключом и оплатите его тестовыми монетами в той сети, что указана на странице: сначала придёт invoice.pending, затем invoice.paid. Обработайте также invoice.underpaid, invoice.expired и invoice.reverted, затем перейдите на рабочий ключ и пройдите чек-лист запуска из руководства разработчика.
Частые ошибки
| Ошибка | Что произошло | Что сделать |
|---|---|---|
401 auth.invalid_signature |
Тело запроса отличается от подписанного | Отправляйте хешированные байты через data=, а не json= |
401 auth.expired_timestamp |
Часы расходятся больше чем на 5 минут | Синхронизируйте часы сервера через NTP |
401 на вашем вебхуке |
Тело разобрано или декодировано до проверки | Проверяйте по request.get_data() |
400 validation_error |
Поле отсутствует или в неверном формате | Посмотрите details.field; суммы передавайте строками |
409 conflict |
У заказа уже есть платёж | Возьмите details.invoice_id вместо создания нового |
422 no_allowed_coins |
Ни одна монета из allowed_coin_ids не доступна для инвойсов в этой валюте |
Передайте другие id или уберите поле, чтобы предложить все монеты |
Удобнее с SDK?
Официальный Python SDK для Python 3.10+ оборачивает эти вызовы: подпись запросов, повторы при 429 и 5xx, Idempotency-Key на каждом POST, постраничные списки и проверку вебхуков. Код выше — то, что SDK делает внутри, так что перейти на него можно позже, не меняя схему.
Вопросы и ответы
Почему подпись не проходит, если передавать тело через json= в requests?
json=payload сериализует тело заново, со своими пробелами, и отправленные байты отличаются от хешированных. Сериализуйте один раз, хешируйте эти байты и передавайте их же через data=. То же на стороне вебхука: проверяйте подпись по request.get_data(), прежде чем что-то разбирать.
Можно ли использовать Django или FastAPI вместо Flask?
Да. Логика во всех фреймворках одна: прочитать сырое тело, вычислить sha256= и HMAC от метки времени, точки и тела, сравнить через hmac.compare_digest, отклонить метки, которые расходятся с вашими часами больше чем на 300 секунд, и только потом разбирать JSON. В Django сырое тело — request.body, в FastAPI — await request.body().
Как проверить интеграцию, не тратя настоящую криптовалюту?
Используйте ключ ck_test_ и тестовый адрес API от поддержки CryptoLike. Тестовые ключи работают с тестовыми сетями, где тестовые монеты ничего не стоят, а весь сценарий — страница оплаты, подтверждения, подписанные вебхуки — ведёт себя как в рабочем режиме. Держите тестовые и рабочие ключи в разных конфигурациях, чтобы они не смешивались.