Integración del checkout en USDC
Una guía de ingeniería realista para integrar pagos en USDC en el checkout: los patrones de API, la elección de red, la idempotencia de los webhooks y los modos de fallo que encontrarás en producción.
En resumen
Una integración de checkout en USDC sigue un patrón conocido: crear una intención de pago en tu servidor (importe, moneda, preferencias de red), recibir de tu adquirente una URL de checkout alojado o la configuración de un widget, dejar que el comprador pague desde su monedero y gestionar el webhook de confirmación de forma idempotente. Las decisiones de ingeniería que más importan son la elección de red (por defecto, Solana o Base, con comisiones inferiores a un céntimo), la idempotencia de los webhooks (usa ID de pedido + hash de la transacción), el flujo de reembolsos (recoge la dirección del monedero en el checkout y ofrece una API de reembolsos) y una UX fluida en el paso de firma en el monedero (enlaces profundos a monederos móviles y código QR como alternativa en escritorio). Bien hecho, el checkout en USDC se completa de principio a fin en menos de 30 segundos y le cuesta al comercio entre el 0.3% y el 1% según el adquirente.
La forma estándar de la API
Las API de adquirencia en USDC siguen, en líneas generales, el patrón de intención de pago que popularizó Stripe. Lo mínimo imprescindible:
El servidor crea la intención de pago
POST /v1/paymentscon un cuerpo que contieneamount,currency(USD si cotizas en moneda fiat; USDC si cotizas en stablecoin),settlement_preference(USDC o fiat),networks(lista de redes permitidas),order_id(tu clave de idempotencia),success_url,cancel_urly un bloquemetadatapara tu propia conciliación.El adquirente devuelve la URL de checkout o la configuración del widget
Con checkout alojado: una URL a la que se redirige al comprador. Con widget integrado: una configuración del lado del cliente (clave publicable, ID de la intención) que carga el widget. Ambos flujos gestionan la detección del monedero, la selección de red y la visualización de la cotización.
El comprador firma en su monedero y se difunde la transferencia on-chain
Móvil: enlace profundo a MetaMask, Phantom, Trust, etc. Escritorio: código QR de WalletConnect o ventana emergente de la extensión del navegador. El comprador revisa el importe y firma.
El adquirente espera las confirmaciones y envía el webhook
POST your_webhook_urlcon un payload que contieneevent_type: “payment.succeeded”,order_id,amount,tx_hash,networky una firma que verificas con el secreto de webhook del adquirente.El servidor marca el pedido como pagado de forma idempotente
Verifica la firma del webhook, busca
(order_id, tx_hash)en tu base de datos, marca el pedido como pagado si aún no lo está y lanza la gestión del envío.
Elección de red
Decidir qué redes aceptar es un equilibrio entre UX y coste:
- Solana: comisión de red inferior a un céntimo, confirmación en menos de un segundo. La mejor opción predeterminada para un valor medio de pedido bajo.
- Base: comisión de red de unos pocos céntimos, confirmación en unos segundos. Buen soporte de monederos; buena opción predeterminada para públicos nativos cripto.
- Polygon, Arbitrum: comisiones y velocidad similares a las de Base. Puedes añadirlas, pero no son estrictamente necesarias.
- Mainnet de Ethereum: comisión de red de $1–$8+ según el gas. Resulta penosa para los compradores en pedidos pequeños. Acéptala para pedidos de valor medio alto (más de $500) o como alternativa.
- Tron: si te diriges a flujos de USDT en Asia/África, merece la pena plantearse admitir USDT-TRON junto a USDC.
Idempotencia de los webhooks
Los webhooks se reintentan. Tu handler debe ser idempotente. El patrón estándar:
- Verifica la firma del webhook con HMAC-SHA256 y el secreto de tu adquirente.
- Extrae
(order_id, tx_hash)del payload. - Busca ese par en tu tabla
processed_payments. - Si lo encuentras: devuelve 200 OK sin hacer nada más.
- Si no lo encuentras: inserta la fila (con una restricción UNIQUE sobre el par), marca después el pedido como pagado en tu tabla principal de pedidos y, por último, lanza la gestión del envío.
- Envuelve el paso 5 en una única transacción de base de datos para que un fallo a mitad del flujo no provoque un envío duplicado.
La mayoría de los webhooks de adquirencia incluyen un ID de entrega: regístralo para depurar, pero no lo uses como clave de idempotencia. Las confirmaciones de red y los reintentos del adquirente pueden generar eventos payment.succeeded duplicados con distintos ID de entrega pero el mismo tx_hash; la deduplicación debe basarse en la identidad on-chain, no en la entrega.
Flujo de reembolsos
Predominan dos patrones:
- Reembolso al remitente: el adquirente devuelve los USDC a la dirección desde la que pagó originalmente el comprador. Es la UX más limpia; funciona porque el registro on-chain del pago contiene la dirección de origen.
- Reembolso a una dirección indicada: el comprador indica un destino para el reembolso (puede ser distinto del origen si pagó desde un exchange o un monedero caliente). La mayoría de los adquirentes lo admiten mediante un
POST /v1/refundscondestination_address.
El comercio paga la comisión de red del tramo de reembolso. Se admiten tanto reembolsos totales como parciales. El reembolso tarda en confirmarse on-chain lo mismo que el pago original.
Modos de fallo en producción
- El comprador abandona tras firmar. La transferencia on-chain se difunde, pero cierra la pestaña antes de que se envíe el webhook. El adquirente igualmente detecta y confirma el pago mediante la monitorización on-chain; tu gestión del envío se ejecuta a partir del webhook, no de la redirección.
- El comprador paga un importe incorrecto. La mayoría de los adquirentes rechazan los importes que no coinciden en el momento de la detección on-chain. Algunos permiten coincidencias aproximadas (dentro de una tolerancia) y señalan la discrepancia en el webhook.
- El comprador paga en la red equivocada. Si firma en Ethereum pero solo aceptas Solana, el pago queda totalmente fuera de la monitorización de tu adquirente. La mayoría de los proveedores devuelven los fondos mediante un flujo de recuperación; algunos los pierden. Deja clara la elección de red en el checkout.
- El comprador paga desde una dirección de un exchange. Los reembolsos al origen pueden ser rechazados o acabar en una cuenta equivocada. Pide explícitamente una dirección de destino para reembolsos en el checkout de cualquier producto en el que sean probables.
- Pérdida de paridad de la stablecoin. Es poco frecuente, pero ocurre. Si USDC pierde significativamente la paridad durante el breve intervalo entre la cotización y la liquidación on-chain, el comercio o el adquirente asume la diferencia según lo acordado.
Añade el checkout en USDC con DPT Acquiring
Desde 0.3% por transacción. Liquidación en el mismo día en USDC o en moneda fiat. URL de checkout alojado o widget integrable. Documentación del SDK y de webhooks en merchant.dpt.xyz.
DPT Acquiring · Vías de integración con Shopify y WooCommerce