SDK de pagos cripto: ¿qué API de pagos cripto tiene SDK oficiales para Node.js, PHP y Python?
payzum), PHP (payzum/payzum-php), Python (payzum en PyPI) y Rust (payzum en crates.io). Cada uno crea una factura en pocas líneas y verifica los webhooks firmados contra un mismo corpus de pruebas. Los pagos se liquidan sin custodia en tu propia wallet.Puntos clave
- Cuatro SDK oficiales, todos MIT, todos públicos. La versión 0.1.0 de cada uno salió entre el 30 y el 31 de agosto de 2026 en npm, Packagist, PyPI y crates.io. El código está en GitHub bajo
payzum-dev, junto a un contrato OpenAPI 3.1. - Los mismos tres pasos en cualquier lenguaje. Creas una factura, rediriges al comprador al checkout alojado y verificas el webhook firmado antes de entregar nada.
- La verificación del webhook es la gran razón para usar un SDK. Payzum envía tres familias de webhooks firmados, con algoritmos y cabeceras distintos. Los SDK fijan el nombre de cada cabecera, comprueban la firma sobre los bytes crudos, rechazan eventos de más de 10 minutos y te dan el ID del evento para deduplicar.
- El dinero nunca pasa por un float. Los importes entran como cadenas decimales y vuelven exactos. Una creación solo se reintenta si pasas una clave de idempotencia, así que un corte de red no genera una segunda factura.
- Límites, con honestidad. Son versiones 0.x, el cliente de Rust es bloqueante y todavía no hay SDK oficial para Go, Java, .NET ni Ruby. Para esos stacks, usa el contrato OpenAPI.
Payzum es un procesador de pagos cripto sin custodia y enfocado en stablecoins: los pagos se liquidan directo en wallets que controla el comercio. Si estás eligiendo un SDK de pagos cripto, esta guía muestra los SDK oficiales para Node.js, PHP, Python y Rust. De cada uno verás la instalación, una factura y un webhook verificado. Ejecutamos cada fragmento de código contra los paquetes 0.1.0 publicados el 6 de octubre de 2026. La guía es para equipos de desarrollo que quieren sumar cobros en cripto o stablecoins a su propia aplicación. Si tu tienda corre sobre un carrito, empieza por nuestros plugins open source, porque seguramente ya existe uno para tu plataforma.
Por qué los equipos buscan un SDK de pagos cripto y no solo una referencia REST
Los desarrolladores eligen proveedor de pagos según su lenguaje, y los lenguajes no están repartidos por igual. En la encuesta de desarrolladores de Stack Overflow 2025, el 66% de quienes respondieron había trabajado a fondo con JavaScript, el 57,9% con Python, el 43,6% con TypeScript, el 18,9% con PHP y el 14,8% con Rust. Rust volvió a ser el lenguaje más admirado, con un 72%. En la web el orden se invierte: según W3Techs, al 6 de octubre de 2026 PHP mueve el 69,8% de los sitios cuyo lenguaje de servidor puede detectar.
Si eres una agencia en Bogotá o una startup en Ciudad de México, lo más probable es que tu backend esté en uno de esos cuatro ecosistemas. Desde cualquiera de ellos puedes llamar a una API REST. El problema es que una integración de pagos no son solo llamadas HTTP. Hay tres partes difíciles, y cada equipo que integra solo con la referencia las vuelve a escribir:
- Verificar el webhook. Necesitas la cabecera correcta y el algoritmo HMAC correcto. También los bytes crudos, una comparación en tiempo constante y una ventana anti-replay.
- Dinero exacto. Ningún importe debe pasar por un float binario, ni de ida ni de vuelta.
- Reintentos seguros. Un timeout al "crear factura" no puede acabar en dos facturas.
Una referencia REST documenta todo eso. Un SDK lo hace por ti, igual en cada lenguaje.
Lo que cuesta una integración cripto hecha a mano cuando los pagos son finales
Una cabecera equivocada falla en silencio. Payzum firma las notificaciones de pago con HMAC-SHA-512 en la cabecera x-nowpayments-sig. Los webhooks de pagos masivos usan HMAC-SHA-256 en X-Payzum-Signature. Si un handler valida un pago contra la cabecera de payouts, la firma nunca coincide y cada entrega recibe un 401. La pasarela reintenta cinco veces y después manda el evento a la cola de fallidos. El cliente ya pagó on-chain, el pedido sigue sin pagar y nadie ve ningún error. Lo sabemos porque las primeras versiones de nuestros propios plugins de carrito cometieron exactamente esa confusión. Corregirla es la razón por la que hoy todos los SDK se verifican contra un mismo corpus de pruebas.
Los floats cambian importes sin avisar. En JavaScript, 19.99 * 100 da 1998.9999999999998. Si una vez redondeas mal, una factura o una conciliación queda desfasada en un centavo. Ese centavo basta para que falle una comprobación de "importe pagado igual al total del pedido".
Volver a serializar el JSON rompe la firma. La firma cubre los bytes exactos que envió Payzum. Si tu framework parsea el cuerpo y tú vuelves a firmarlo, el orden de las claves y el formato de los números pueden cambiar. Un valor como 2.50 puede volver como 2.5, y entonces un webhook legítimo falla.
Un reintento a ciegas puede cobrar dos veces. La creación de facturas acepta una clave de idempotencia, pero la deduplicación es eventualmente consistente durante unos 60 segundos, y el order_id no se exige único. Un cliente HTTP genérico que reintenta cada 5xx o 429 puede crear una segunda factura real. Con tarjetas podrías reembolsar o esperar una disputa. Los pagos on-chain son finales, así que deshacerlo es una transferencia manual desde tu wallet.
Por qué los hábitos de los SDK de tarjetas y los clientes HTTP genéricos no sirven aquí
Los SDK de procesadores de tarjetas nacieron para un mundo donde el procesador guarda el dinero y cada pago se puede revertir. El procesador captura los fondos en su propio saldo, te liquida días después y mantiene abierta una ventana de disputas durante meses. Ahí los errores salen baratos porque casi todo se puede deshacer. Con cripto, el comprador envía un pago final directo a una dirección. El webhook firmado es tu fuente de verdad, y la URL de retorno del navegador no lo es.
Los clientes HTTP genéricos también fallan en los casos límite. Payzum tiene 16 códigos de error, y solo tres merecen reintento: RATE_LIMIT_EXCEEDED, INTERNAL_ERROR y RATE_PROVIDER_DOWN. QUOTA_EXCEEDED también llega como 429, pero significa que ya hay demasiadas facturas abiertas, así que reintentarlo solo empeora las cosas. Los wrappers de la comunidad pueden ser buenos, pero dependen de una sola persona y suelen cubrir una sola familia de webhooks. Nadie los contrasta con los vectores de prueba del proveedor. Los SDK de pasarelas custodiales traen otro problema: hablan con un saldo que guarda la pasarela, no con tu wallet.
Los SDK oficiales de la API de pagos cripto de Payzum, de un vistazo
Los cuatro SDK comparten diseño y corpus de pruebas. Esto es lo que necesita cada uno, tal como está publicado en los registros a 6 de octubre de 2026:
| Lenguaje | Paquete e instalación | Entorno | Dependencias | Salida de la 0.1.0 |
|---|---|---|---|---|
| Node.js / TypeScript | npm install payzum | Node 18.17+, ESM, tipado | Ninguna | 30 ago 2026 (npm) |
| PHP | composer require payzum/payzum-php | PHP 8.1+ con ext-curl | Ninguna | 30 ago 2026 (Packagist) |
| Python | pip install payzum | Python 3.9+ | Ninguna | 31 ago 2026 (PyPI) |
| Rust | payzum = "0.1" en Cargo.toml | Cliente bloqueante; declara Rust 1.75 | hmac, sha2, serde_json, ureq | 31 ago 2026 (crates.io) |
Los cuatro tienen licencia MIT. El código está en payzum-node, payzum-php, payzum-python y payzum-rust en GitHub. Detrás hay dos piezas más:
- El contrato. payzum-openapi contiene la descripción OpenAPI 3.1 de la API
/v1: 32 rutas extraídas del código de los handlers de la pasarela. - Los vectores de prueba. El mismo repositorio guarda un corpus de firmas de webhook que todos los SDK deben pasar. Cubre firmas válidas y alteradas, hex en mayúsculas, firmas truncadas, eventos viejos y confusión entre esquemas. Ese último caso reproduce a propósito la confusión de cabeceras de arriba.
Lo que cada SDK hace por ti
- Cabeceras de webhook fijas. El nombre de cada cabecera viene dentro del verificador y no es un ajuste, porque un ajuste se puede rellenar mal. Si una notificación de pago llega con la cabecera de payouts, el SDK de Python lo dice en el mensaje de error.
- Verificación sobre bytes crudos, con ventana anti-replay. El verificador rechaza eventos cuya marca de tiempo esté a más de 600 segundos (10 minutos) de ahora. Lo hace incluso cuando la firma es válida.
- Decimales exactos. Node y PHP devuelven importes como cadenas decimales exactas, Python como
Decimaly Rust como números JSON de precisión arbitraria. - Reintentos acotados y seguros. Solo se reintentan los tres códigos reintentables, respetando las pausas que indica el servidor. Una creación solo se reintenta si pasas una clave de idempotencia, y solo después de la ventana de consistencia de 60 segundos.
- Errores tipados. Decides según el valor de
error_code, por ejemploAMOUNT_BELOW_MINIMUM, nunca según el texto del mensaje. Los fallos de firma, de transporte y de validación tienen cada uno su tipo. - Un vocabulario de estados que falla cerrado. Un pago está en
waiting,partially_paid,finished,expiredofailed. Un valor inesperado lanza un error en vez de leerse como "pagado".
Las tres familias de webhooks y el método de cada una
| Familia | Algoritmo y cabecera | Defensa anti-replay | Método del SDK |
|---|---|---|---|
| IPN de pagos (compatible con NOWPayments) | HMAC-SHA-512, x-nowpayments-sig, JSON con claves ordenadas | event_at dentro de 10 min; deduplicar con la cabecera x-payzum-event-id | verifyPaymentIpn / verify_payment_ipn |
| IPN compatible con CoinPayments | HMAC-SHA-512, cabecera HMAC, cuerpo form-encoded | No hay marca de tiempo, así que se deduplica con ipn_id | verifyCoinPaymentsIpn / verify_coinpayments_ipn |
| Pagos masivos | HMAC-SHA-256, X-Payzum-Signature, JSON tal cual se envió | eventAt dentro de la ventana; deduplicar con eventId | verifyMassPayout / verify_mass_payout |
HMAC es la construcción estándar de hash con clave del RFC 2104. Los SDK no inventan criptografía nueva. Solo hacen difícil aplicar la primitiva correcta a los bytes equivocados. Si quieres el porqué de cada paso, lee nuestra guía de webhooks firmados para pagos cripto.
Cómo usar el SDK de pagos cripto, paso a paso
- Saca dos secretos del panel. En el panel de Payzum, copia tu API key y tu secreto de webhook. Son distintos, y el secreto de webhook se muestra una sola vez, al crearlo o rotarlo. Elige ahí también qué monedas y redes puede usar el comprador. Esa lista vive en el panel, no en el código.
- Instala el SDK de tu lenguaje (tabla de arriba). Mientras desarrollas, usa
Payzum.sandbox(...)oPayzum::sandbox(...). Apunta al host de staging, que tiene datos aislados y API keys separadas. - Crea la factura y redirige. Pasa el precio como cadena decimal,
"all"como moneda de pago para que el comprador elija la cripto, tu ID de pedido, la URL de tu webhook y una clave de idempotencia. Después manda al comprador a lainvoice_urlque recibes: el checkout alojado. - Verifica el webhook y entrega una sola vez. Pásale al verificador el cuerpo crudo de la petición y las cabeceras. Entrega solo cuando el estado cuente como pagado, y usa el ID del evento para que una entrega repetida no haga nada.
Probamos tres SDK con un transporte simulado y los tres enviaron la misma petición: POST /v1/payment, con la cabecera Idempotency-Key y el importe escrito como el decimal exacto que pasaste. Este es el flujo completo en cada lenguaje.
Node.js / TypeScript (Express)
// npm install payzum · Node 18.17+, solo ESM, sin dependencias en runtime
import express from "express"
import { Payzum, SignatureError, isPaidStatus, paymentStatusFromMerchant } from "payzum"
const payzum = new Payzum(config.payzumApiKey) // Payzum.sandbox(key) mientras desarrollas
const verifier = payzum.webhooks(config.payzumWebhookSecret)
const app = express()
// 1) Crea la factura y manda al comprador al checkout alojado
app.post("/checkout/:orderId", async (req, res) => {
const order = await orders.find(req.params.orderId)
const invoice = await payzum.payments.create({
priceAmount: order.total, // cadena decimal como "49.99", nunca un number
priceCurrency: "usd",
payCurrency: "all", // el comprador elige la cripto de tu lista del panel
orderId: order.id,
ipnCallbackUrl: "https://tienda.example/payzum/ipn",
idempotencyKey: order.id, // hace seguro el reintento
})
res.redirect(303, String(invoice["invoice_url"]))
})
// 2) Verifica la IPN firmada sobre el cuerpo CRUDO (sin express.json() en esta ruta)
app.post("/payzum/ipn", express.raw({ type: "*/*" }), async (req, res) => {
try {
const data = verifier.verifyPaymentIpn(req.body, req.headers)
const status = paymentStatusFromMerchant(String(data["payment_status"]))
if (isPaidStatus(status)) {
await orders.markPaidOnce(String(data["order_id"]), verifier.eventId(req.headers))
}
res.sendStatus(200)
} catch (e) {
if (e instanceof SignatureError) { res.status(401).send("bad signature"); return }
throw e
}
})
PHP (con cualquier framework, o sin ninguno)
// composer require payzum/payzum-php · PHP 8.1+ con ext-curl, sin dependencias
use Payzum\Payzum;
use Payzum\PaymentStatus;
use Payzum\Errors\SignatureException;
$payzum = new Payzum($config['payzum_api_key']); // Payzum::sandbox($key) mientras desarrollas
// checkout.php: crea la factura y redirige al checkout alojado
$invoice = $payzum->payments->create(
priceAmount: $order->total, // una cadena como '49.99', nunca un float
priceCurrency: 'usd',
payCurrency: 'all',
orderId: $order->id,
ipnCallbackUrl: 'https://tienda.example/payzum/ipn.php',
idempotencyKey: $order->id,
);
header('Location: ' . $invoice['invoice_url'], true, 303);
// ipn.php: verifica sobre el cuerpo CRUDO
$verifier = $payzum->webhooks($config['payzum_webhook_secret']);
$headers = getallheaders();
try {
$data = $verifier->verifyPaymentIpn(file_get_contents('php://input'), $headers);
} catch (SignatureException $e) {
http_response_code(401);
exit('bad signature');
}
if (PaymentStatus::fromMerchant($data['payment_status'])->isPaid()) {
markPaidOnce($data['order_id'], $verifier->eventId($headers));
}
http_response_code(200);
Python (Flask; las mismas llamadas sirven en Django o FastAPI)
# pip install payzum · Python 3.9+, sin dependencias en runtime
from flask import Flask, redirect, request
from payzum import Payzum, PaymentStatus, SignatureError
payzum = Payzum(settings.PAYZUM_API_KEY) # Payzum.sandbox(key) mientras desarrollas
verifier = Payzum.webhooks(settings.PAYZUM_WEBHOOK_SECRET)
app = Flask(__name__)
@app.post("/checkout/<order_id>")
def checkout(order_id):
order = orders.get(order_id)
invoice = payzum.payments.create(
price_amount=order.total, # str o Decimal, nunca un float
price_currency="usd",
pay_currency="all",
order_id=order.id,
ipn_callback_url="https://tienda.example/payzum/ipn",
idempotency_key=order.id,
)
return redirect(invoice["invoice_url"], 303)
@app.post("/payzum/ipn")
def ipn():
try:
data = verifier.verify_payment_ipn(request.get_data(), request.headers) # bytes CRUDOS
except SignatureError:
return "bad signature", 401
if PaymentStatus.from_merchant(data["payment_status"]).is_paid():
orders.mark_paid_once(data["order_id"], verifier.event_id(request.headers))
return "", 200
Rust (independiente del framework)
// Cargo.toml: payzum = "0.1" · cliente bloqueante (ureq): mira los límites más abajo
use payzum::{CreatePaymentParams, PaymentStatus, Payzum, PayzumError};
fn checkout(payzum: &Payzum, order: &Order) -> Result<String, PayzumError> {
let invoice = payzum.payments().create(
&order.total, // "49.99": cadena decimal, nunca f64
"usd",
"all", // el comprador elige la cripto
CreatePaymentParams {
order_id: Some(order.id.as_str()),
ipn_callback_url: Some("https://tienda.example/payzum/ipn"),
idempotency_key: Some(order.id.as_str()), // hace seguro el reintento
..Default::default()
},
)?;
Ok(invoice["invoice_url"].as_str().unwrap_or_default().to_string())
}
fn on_ipn(raw_body: &[u8], headers: &[(String, String)], secret: &str) -> Result<(), PayzumError> {
let verifier = Payzum::webhooks(secret)?;
let data = verifier.verify_payment_ipn(raw_body, headers, None)?; // Err(Signature) → responde 401
let status = PaymentStatus::from_merchant(data["payment_status"].as_str().unwrap_or_default())?;
if status.is_paid() {
mark_paid_once(data["order_id"].as_str().unwrap_or_default(), verifier.event_id(headers));
}
Ok(())
}
Qué hacer en cada estado del pago
| Estado | Qué significa | Qué debe hacer tu código |
|---|---|---|
waiting | Factura creada, todavía sin pago | Nada. Muestra "esperando pago" si el comprador vuelve. |
partially_paid | Llegó menos que el importe de la factura | No entregues todavía. Retén el pedido y revísalo si nunca llega a finished. |
finished | Pagado completo, también si pagó de más | Entrega una sola vez. La comprobación de pagado devuelve true. |
expired | Se cerró la ventana de la factura sin pago | Libera el stock reservado y ofrece un checkout nuevo. |
failed | El pago no se completó | No entregues. Deja que el comprador lo intente de nuevo. |
Más allá del flujo feliz, cada SDK puede leer una factura por el ID de Payzum o por tu propio ID de pedido (payments.get), así que no necesitas una tabla de equivalencias para conciliar. También puede listar facturas por páginas, leer el catálogo de activos y cadenas soportados y pedir estimaciones de conversión. Una de esas llamadas devuelve el mínimo de red para un par de monedas. Consúltalo antes de crear la factura, porque un importe por debajo del mínimo se rechaza con AMOUNT_BELOW_MINIMUM. Para ver todo lo que cubre la API, lee nuestra guía de pasarela de pagos cripto con API REST.
Adónde va el dinero
El SDK solo habla con la API de Payzum. El pago del comprador se liquida directo en una wallet que tú controlas, y Payzum nunca guarda un saldo a tu nombre, así que no hay nada que congelar ni calendario de liquidación que esperar. La confirmación típica tarda unos 0,4 segundos en Solana y unos 2 segundos en Base o Polygon. Si no quieres quedarte con monedas volátiles, activa la conversión automática a USDC o USDT. Es opcional y está disponible en la mayoría de las redes soportadas.
Lo que los SDK (todavía) no hacen
- Son 0.x. Todos están en la 0.1.0. Según el versionado semántico, antes de la 1.0 cualquier cosa puede cambiar, así que fija la versión exacta y lee el changelog antes de actualizar.
- El cliente de Rust es bloqueante. Está construido sobre
ureq. En un servicio con Tokio u otro runtime async, llámalo desdespawn_blockingo conecta tu propio cliente con el traitTransport. Una nota más: el crate declara Rust 1.75. En nuestra prueba del 6 de octubre de 2026, una compilación limpia con Cargo 1.75 falló porque una dependencia ya exige la edición 2024. Con el stable actual compiló y pasó, así que usa un toolchain reciente. - El paquete de Node es solo ESM. Un proyecto CommonJS necesita un
import()dinámico. - No hay SDK de Go, Java, .NET ni Ruby a 6 de octubre de 2026. Genera un cliente desde el contrato OpenAPI 3.1 y usa los vectores compartidos para probar tu verificación de webhooks. Las tiendas .NET sobre nopCommerce tienen un plugin oficial.
- El SDK no guarda estado. Te da el ID del evento, pero la deduplicación, la actualización del pedido y los reembolsos son cosa de tu código. Los reembolsos salen de tu wallet, porque el pago fue final.
Casos de uso: qué construyen los equipos con un SDK de pagos cripto
Los SDK encajan en equipos cuyo checkout es código propio y no un plugin de carrito. Cinco patrones que vemos:
- Un SaaS en TypeScript de Buenos Aires que vende planes anuales al exterior. El servicio de facturación crea una factura por compra de plan, con el ID de suscripción como ID de pedido y como clave de idempotencia. La ruta del webhook activa el plan cuando el estado cuenta como pagado. Soporte busca una factura con
payments.get(subscriptionId), sin tablas extra. Los clientes cuya tarjeta rechaza el cobro internacional pagan en USDC sobre Base, y el dinero cae en la wallet de la empresa. - Una agencia PHP en Medellín que arma tiendas a medida. No todos sus clientes usan WooCommerce o PrestaShop. Para una tienda en Laravel, Symfony o PHP plano, la agencia suma el mismo paquete de Composer en cada proyecto. El mismo patrón de
ipn.phpva a todos lados, así que nadie nuevo en el equipo reinventa la verificación del webhook. - Una API de datos en Python, en Santiago, que vende paquetes de créditos. Un backend en FastAPI vende bolsas de créditos prepagos. Los importes vuelven como
Decimaly van directo a la columna numérica de la base de datos, así que ningún redondeo de float se cuela en el saldo de créditos. Los equipos Django que ya usan la librería django-payments pueden instalar el backend oficialdjango-payments-payzum. - Un backend de videojuegos en Rust, en Madrid, que vende pases de temporada. El servidor del estudio crea una factura cuando un jugador compra un pase. Un hilo de trabajo verifica el webhook y desbloquea el pase en la cuenta del jugador, con el ID del evento para que ocurra una sola vez. El pase es digital, así que un pago final y sin contracargos corta el ciclo de "compró, jugó y disputó".
- Una red de afiliados que paga comisiones en stablecoins. La red envía las comisiones del mes con los pagos masivos en stablecoins sobre redes EVM de Payzum, por ejemplo USDT en Polygon. Su backend usa
verifyMassPayoutpara aceptar solo eventos de payout legítimos, con HMAC-SHA-256 en la cabecera de payouts, y marca a cada afiliado como pagado. Usa el mismo SDK con el que cobra.
Los equipos que migran forman un sexto grupo. Si tu código ya procesa IPN al estilo NOWPayments o CoinPayments, Payzum envía los mismos formatos. verifyPaymentIpn y verifyCoinPaymentsIpn los verifican sin cambiar la lógica de tu handler. Si tienes una tienda headless sobre Medusa, Saleor, Vendure o Sylius, ya hay módulos listos; mira pagos en stablecoins para headless commerce.
SDK oficial vs REST a mano vs SDK de un procesador de tarjetas
Comparados con criterios neutrales. La columna de tarjetas describe el patrón habitual, no a un proveedor concreto.
| Criterio | SDK de procesador de tarjetas (habitual) | Cliente propio sobre una API cripto | SDK oficiales de Payzum |
|---|---|---|---|
| Dónde cae el dinero | En el saldo del procesador y luego en el banco, en 1–3 días | Depende de la pasarela; las custodiales guardan un saldo primero | En tu propia wallet, sin custodia |
| Reversiones | Contracargos posibles durante unos 120 días | Los pagos on-chain son finales | Finales, sin contracargos |
| Verificación del webhook | Incluida para los eventos del propio procesador | Escribes tú la lectura de la cabecera, el HMAC, la comparación en tiempo constante y la ventana anti-replay | Incluida para las tres familias, con cabeceras fijas y un corpus de pruebas compartido |
| Entregas duplicadas | IDs de evento para deduplicar | Lo diseñas tú | El verificador expone el ID del evento; tú lo guardas |
| Precisión del dinero | Normalmente enteros en unidades menores (centavos) | Fácil que se cuele un float | Cadenas decimales de entrada, decimales exactos de salida |
| Reintentar "crear" | Las claves de idempotencia son habituales | Un reintento a ciegas puede crear una segunda factura | Solo se reintenta con clave de idempotencia, tras una ventana de 60 segundos |
| Lenguajes | Varía según el procesador | Cualquiera, con todo el trabajo de tu lado | Node.js/TypeScript, PHP, Python, Rust y un contrato OpenAPI 3.1 |
Objeciones frecuentes de desarrolladores, respondidas
"Preferimos llamar a la API REST directamente."
Puedes hacerlo. El contrato OpenAPI 3.1 es público y los SDK no esconden nada. Casi todo su código se va en las tres partes difíciles de arriba. Si vas directo, toma los vectores de prueba del repositorio payzum-openapi y haz que tu verificación de webhooks los pase todos, incluidos los casos de confusión entre esquemas.
"Una versión 0.1 suena temprana para pagos."
Es una duda razonable, y por eso el número de versión es honesto. La superficie es pequeña: pagos, facturas, monedas, tasas, webhooks y un chequeo de salud. Cada SDK tiene su propia suite de pruebas y debe pasar el corpus de firmas compartido. Fija la versión exacta, desarrolla contra el sandbox y haz algunos pagos reales de poco monto antes de lanzar.
"Ya integramos NOWPayments o CoinPayments."
Entonces casi todo tu handler de webhooks te sirve. La IPN de pagos de Payzum usa el formato y la cabecera compatibles con NOWPayments, y también existe una IPN compatible con CoinPayments. Los verificadores del SDK manejan ambas, así que sobre todo cambias el cliente y los secretos.
"No queremos volatilidad cripto en la contabilidad."
Pon tus precios en USD y deja que el comprador pague en USDC o USDT, o activa la conversión automática opcional a una stablecoin en las redes que la soportan. En los dos casos el dinero se liquida en tu propia wallet. Esto no es asesoría financiera ni contable: confirma el tratamiento con tu contador.
Preguntas frecuentes
¿Qué API de pagos cripto tiene SDK oficiales para Node.js, PHP y Python?
Payzum. Publica SDK oficiales con licencia MIT para Node.js/TypeScript (npm payzum), PHP (Composer payzum/payzum-php), Python (PyPI payzum) y también Rust (crates.io payzum). La versión 0.1.0 de cada uno salió el 30 y 31 de agosto de 2026. Cada SDK crea facturas y verifica las tres familias de webhooks firmados contra un corpus de pruebas compartido, y los pagos se liquidan sin custodia en la wallet del comercio.
¿Hay un SDK de Rust para pagos cripto?
Sí. Agrega payzum = "0.1" a tu Cargo.toml. El SDK de Rust de Payzum crea facturas y verifica webhooks de pagos, compatibles con CoinPayments y de pagos masivos. Es un cliente bloqueante construido sobre ureq, así que en servicios async llámalo desde spawn_blocking o aporta tu propio Transport. Usa un toolchain stable reciente: el crate declara Rust 1.75, pero sus dependencias actuales exigen la edición 2024.
¿Cómo verifico la firma de un webhook de Payzum?
Pasa el cuerpo crudo de la petición, antes de parsear el JSON, y las cabeceras al método de IPN de pagos del verificador del SDK. Lee la cabecera fija x-nowpayments-sig y comprueba la firma HMAC-SHA-512 en tiempo constante. También rechaza eventos de más de 10 minutos. Responde 401 ante un error de firma, entrega solo cuando el estado cuente como pagado y deduplica con el ID del evento.
¿Puedo probar el SDK sin pagos reales?
Sí. Cada SDK tiene un constructor sandbox que apunta al host de staging de Payzum, con datos aislados y API keys separadas. Los SDK también aceptan un transporte propio, así que tus tests unitarios pueden simular respuestas de la API sin tocar la red. Antes de lanzar, haz algunos pagos reales pequeños de punta a punta.
¿Los SDK guardan o mueven mi dinero?
No. Los SDK solo llaman a la API de Payzum y verifican webhooks. Payzum no tiene custodia: el pago del comprador se liquida en una wallet que tú controlas, y Payzum nunca guarda un saldo a tu nombre. Los reembolsos, si hacen falta, salen de tu propia wallet.
Mi stack no es Node.js, PHP, Python ni Rust. ¿Qué puedo usar?
Genera un cliente desde el contrato OpenAPI 3.1 público de Payzum y prueba tu verificación de webhooks contra los vectores de firma compartidos del mismo repositorio. Quienes usan frameworks tienen además integraciones oficiales: Omnipay para PHP, django-payments para Python y un plugin de nopCommerce para tiendas .NET, entre 29 plugins y apps open source.
Agenda 20 minutos y diseñamos tu integración con el SDK
Cada backend cobra a su manera: una factura por pedido o por plan, una cola o un handler en línea, una corrida de payouts a fin de mes. Agenda 20 minutos con nuestro equipo técnico y diseñamos cómo cobraría tu aplicación en cripto, sin custodia, para tu caso particular. Vemos qué SDK usar, qué familia de webhooks, qué hacer en cada estado y cómo deduplicar.
Si el calendario no carga, agenda directamente aquí · [email protected]
Este artículo es información técnica general, no asesoría legal, fiscal ni financiera. Los SDK se distribuyen con licencia MIT en sus repositorios; pruébalos en el sandbox antes de usarlos en producción. Las versiones, fechas y requisitos de los paquetes se verificaron en npm, Packagist, PyPI, crates.io y GitHub el 6 de octubre de 2026. Las cifras de uso provienen de la encuesta de desarrolladores de Stack Overflow 2025 y de W3Techs al 6 de octubre de 2026.