Una aplicación Python recibe cripto con CryptoLike en tres pasos: firma cada solicitud a la API con los módulos estándar hmac y hashlib, crea un pago para el pedido y verifica el webhook firmado antes de marcar el pedido como pagado. Los ejemplos usan requests y Flask; la misma lógica sirve para Django, FastAPI y otros frameworks.
Una tienda en WooCommerce, OpenCart, PrestaShop o Magento 2 no necesita código: revisa las integraciones. Esta guía es para tu propio backend.
Qué necesitas
Una cuenta de CryptoLike, Python 3.10 o superior y una URL pública https:// para los webhooks. Guarda los secretos en el entorno: los ejemplos leen CRYPTOLIKE_API_KEY_ID, CRYPTOLIKE_API_SECRET y CRYPTOLIKE_WEBHOOK_SECRET, además de CRYPTOLIKE_API_URL para la URL de la API de prueba (si no está definida, se usa producción). Empieza con claves de prueba y redes de prueba.
1. Crea una clave API de prueba
En el panel abre Desarrolladores → Claves API → Crear clave con los permisos create_invoice y read. Una clave ck_test_ funciona con redes de prueba, donde las monedas no tienen valor. Las claves de prueba se crean en el entorno de prueba: el soporte de CryptoLike te da acceso a su panel, donde creas la misma clave, y la URL de su API (CRYPTOLIKE_API_URL en los ejemplos). El panel de producción emite solo claves reales, y en la red principal una clave de prueba se rechaza con 401 auth.test_key. El secreto se muestra una sola vez; ponlo de inmediato en tu entorno o en tu gestor de secretos.
2. Firma las solicitudes a la API con hmac
La firma es un HMAC-SHA256 de cuatro líneas —la marca de tiempo Unix en segundos, el método, la ruta con su query y el SHA-256 del cuerpo— con el secreto de la API como clave:
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 dataEnvía los mismos bytes de los que calculaste el hash: pasa data=body, no json=payload, que volvería a serializar el cuerpo. Compara la función con el vector de referencia de autenticación de la API.
3. Crea el pago de un pedido
Crea el pago en el servidor cuando se hace el pedido. Ponle precio en USD o EUR y deja que el cliente elija la moneda cripto, o pasa un coin_id de GET /v1/currencies. Sin coin_id, la página muestra las monedas disponibles para facturas, cada una con un monto aproximado marcado con ≈; agrega allowed_coin_ids (id con invoice_enabled: true en GET /v1/currencies firmado) para ofrecer solo algunas. Con el ID del pedido como clave de idempotencia, un reintento devuelve el mismo pago:
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"]Mantén los montos como cadenas o Decimal, nunca float.
4. Envía al cliente a la página de pago
Redirige a invoice["checkout_url"] (redirect(invoice["checkout_url"], code=303) en Flask). La página muestra el monto, la red, la dirección con código QR, el tiempo restante y el estado en vivo, y luego devuelve al cliente a return_url. Para que el cliente se quede en tu sitio, incrusta la página con el widget de pago.
5. Verifica el webhook en Flask
Agrega un endpoint de webhook en Desarrolladores → Webhooks con los eventos invoice.*. Verifica sobre el cuerpo sin procesar de request.get_data(), descarta duplicados por event_id y responde rápido:
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 "", 200Cada evento se entrega al menos una vez y puede llegar en desorden: guíate por el estado dentro de data. El procedimiento completo está en cómo verificar los webhooks de pagos cripto.
6. Prueba en una red de prueba y pasa a producción
Crea un pago con la clave de prueba y págalo con monedas de prueba en la red que indica la página: primero llega invoice.pending y después invoice.paid. Maneja también invoice.underpaid, invoice.expired e invoice.reverted; luego cambia a una clave real y sigue la lista de verificación para producción de la guía para desarrolladores.
Errores comunes y cómo corregirlos
| Error | Qué pasó | Qué hacer |
|---|---|---|
401 auth.invalid_signature |
El cuerpo de la solicitud no coincide con lo que se firmó | Envía los mismos bytes que firmaste, con data= y no con json= |
401 auth.expired_timestamp |
El reloj tiene un desfase de más de 5 minutos | Sincroniza el reloj del servidor con NTP |
401 en tu webhook |
El cuerpo se parseó o decodificó antes de la verificación | Verifica sobre request.get_data() |
400 validation_error |
Falta un campo o tiene un formato incorrecto | Lee details.field; envía los montos como cadenas |
409 conflict |
El pedido ya tiene un pago | Usa details.invoice_id en lugar de crear otro |
422 no_allowed_coins |
Ninguna moneda de allowed_coin_ids está disponible para facturas en esta divisa |
Envía otros id o quita el campo para ofrecer todas las monedas |
¿Prefieres un SDK?
El SDK oficial de Python para Python 3.10+ envuelve estas llamadas: solicitudes firmadas, reintentos ante 429 y 5xx, un Idempotency-Key en cada POST, paginación y verificación de webhooks. El código de arriba es lo que el SDK hace por dentro, así que puedes cambiar más adelante sin modificar el flujo.
Preguntas frecuentes
¿Por qué falla la firma cuando uso el argumento json= de requests?
json=payload vuelve a serializar el cuerpo con sus propios espacios, así que los bytes enviados son distintos de los bytes de los que calculaste el hash. Serializa una sola vez, calcula el hash de esos bytes y pasa los mismos bytes con data=. Lo mismo aplica del lado del webhook: verifica sobre request.get_data() antes de parsear nada.
¿Puedo usar Django o FastAPI en lugar de Flask?
Sí. La lógica es la misma en todos los frameworks: lee el cuerpo sin procesar, calcula sha256= más el HMAC de la marca de tiempo, un punto y el cuerpo, compara con hmac.compare_digest, rechaza las marcas de tiempo que se alejen más de 300 segundos de tu reloj y después parsea. En Django el cuerpo sin procesar es request.body; en FastAPI, await request.body().
¿Cómo pruebo sin gastar cripto real?
Usa una clave ck_test_ con la URL de la API de prueba que te da el soporte de CryptoLike. Las claves de prueba funcionan con redes de prueba, donde las monedas de prueba no tienen valor, y todo el flujo —página de pago, confirmaciones, webhooks firmados— se comporta igual que en producción. Guarda las claves de prueba y las reales en configuraciones separadas para que nunca se mezclen.