Inicio rápido
Tres pasos de registrado a "en vivo en tu sitio." La página de proyecto del panel genera los fragmentos exactos con tu ID de proyecto incluido. Los bloques de abajo son ilustrativos.
- Pega el script tag una vez, en el
<head>de tu sitio(o justo antes de</body>). Una copia es suficiente sin importar cuántos botones de compra tengas.<script src="https://sdk.coinmoebius.com/v1/coin-moebius-buy.js" crossorigin="anonymous" defer></script> - Agrega el producto a tu catálogo en el panel.Abre tu proyecto, ve a la pestaña Productos, haz clic en "Agregar producto" y configura el
product-ref, nombre, precio y moneda. Por defecto Coin Moebius está en modo estricto, lo que significa que el precio que configuras aquí es el precio canónico (un comprador no puede editar el precio en su navegador para pagar menos). - Pega un botón de compra donde quieras que aparezcaen el cuerpo de la página. Referencia el producto por su
product-refen el atributoproduct-id. Repite con unproduct-idylabeldiferente para cada producto adicional.<coin-moebius-buy project-id="proj_YOUR_ID_HERE" product-id="t-shirt-medium" label="Buy a t-shirt"> </coin-moebius-buy> - Conecta al menos un proveedor en el panel.Abre tu proyecto, ve a la pestaña Proveedores, haz clic en "Agregar proveedor" y sigue los pasos por proveedor en Configuración de proveedores abajo.
El botón de compra
El botón de compra son unas líneas de HTML que pegas en cualquier página. Sin framework, sin paso de instalación de tu parte. El botón se renderiza en el primer pintado; el selector de proveedor y los SDKs de proveedores de pago se cargan bajo demanda la primera vez que un comprador hace clic. Funciona en cualquier sitio o framework que renderice HTML, incluyendo los constructores de sitios sin código que te permiten pegar bloques HTML.
Confirmado funcionando con: Angular, Hugo, Jekyll, HTML plano, Webflow (bloque de código personalizado), Carrd (elemento Embed), Framer (embed HTML), Squarespace (Bloque de código), WordPress (bloque HTML personalizado), Ghost, sitios Notion (widgets de embed HTML). Si tu sitio te deja pegar HTML en una página, el botón de compra funciona ahí.
Referencia de atributos
| Atributo | Requerido | Qué acepta | Notas |
|---|---|---|---|
endpoint | No | Cadena de URL | Casi siempre omítelo. El botón detecta su base de API automáticamente: https://api.coinmoebius.com en producción, http://localhost:8787 en localhost. Solo configúralo como override para una configuración inusual (ej., un proxy autoalojado frente a la API). |
project-id | Sí | Cadena, con prefijo proj_ | Desde la página de tu proyecto en el panel. Es seguro exponerlo públicamente, es un identificador, no una credencial. |
product-id | Sí (en modo estricto) / Recomendado (en modo ad-hoc) | Cadena, cualquier formato que elijas | Tu identificador interno de producto. En modo estricto (el predeterminado), así es como el worker busca el precio en tu catálogo. En modo ad-hoc, aún se pasa a tus webhooks en metadata.productId para que puedas mapear transacciones a tu inventario. Consulta la sección Modo estricto vs modo ad-hoc abajo. |
amount | Solo en modo ad-hoc | Número decimal como cadena | El precio en unidades mayores (ej., dólares, no centavos). Debe ser positivo. Omítelo en modo estricto. El worker lee el precio canónico de tu catálogo e ignora cualquier valor en el HTML. Requerido solo cuando el proyecto está en modo ad-hoc y el product-id no está en el catálogo. |
currency | Solo en modo ad-hoc | Código ISO 4217 de tres letras o nombre de tu propia unidad | USD, EUR, etc. para tarjetas / rieles cripto. El proveedor de pago por correo acepta cualquier cadena (ej., GBK) porque el comerciante es quien liquida la transacción. Misma regla que amount: omitir en modo estricto, requerido en modo ad-hoc para productos que no están en el catálogo. |
label | No | Cadena | El texto del botón. Por defecto es Buy. Úsalo para distinguir botones en la misma página. |
customer-ref | No | Cadena, cualquier formato que elijas | Un identificador opaco para el comprador en tu propio sistema, como un id de usuario autenticado. El botón lo envía al worker como metadata.customerRef, y el worker etiqueta la transacción con él. Después puedes preguntar "cuál de mis usuarios pagó?" usando tu propio id, sin que nosotros guardemos datos del cliente. Omítelo para compras anónimas. |
theme | No | dark o light | Elige el esquema de color integrado para el botón y la ventana juntos. Por defecto es dark. Usa theme="light" para el esquema claro. Tus variables CSS anulan cualquiera de los dos. Ver la guía de personalización. |
editable-amount | No | true o false | Cuando es true, la ventana muestra un campo de cantidad que el comprador rellena (propinas, donaciones, paga-lo-que-quieras). Por defecto es false, donde la amount que fijes queda fija y no aparece ningún campo. Los botones de pago quedan deshabilitados hasta que la cantidad sea un número positivo. |
Múltiples botones en una página
El script registra el botón una vez, luego cualquier cantidad de instancias puede renderizarse en una página. Cada instancia es independiente. El ejemplo de abajo usa modo estricto (el predeterminado): sin amount ni currency en el HTML, porque el worker busca el precio de cada producto en tu catálogo.
<coin-moebius-buy
project-id="proj_YOUR_ID"
product-id="t-shirt-medium"
label="T-shirt (medium)">
</coin-moebius-buy>
<coin-moebius-buy
project-id="proj_YOUR_ID"
product-id="mug-blue"
label="Blue mug">
</coin-moebius-buy>Si tu proyecto está en modo ad-hoc (widgets de donación, botes de propinas), cada botón también incluye amount y currency. Consulta Modo estricto vs modo ad-hoc para el panorama completo.
Personalizar el botón
El botón de compra se renderiza dentro de un Shadow DOM, lo que significa que nada del CSS existente de tu página llega hasta él. Eso es intencional: mantiene el botón con la misma apariencia en cada sitio, y evita que una regla suelta * { box-sizing: ... } rompa el modal del selector. Lo personalizas a través de dos superficies desde tu propia hoja de estilos: propiedades personalizadas de CSS para colores, fuentes y forma, y selectores ::part() para todo lo demás. Sin JavaScript.
Cada variable y parte está documentada en la guía de personalización, con ejemplos en vivo que puedes hacer clic y copiar:
Abre la guía interactiva de personalización →
Precios: fijo vs precio del comprador
Cada producto en tu catálogo es fijo (el precio que configuras es lo que se cobra) o precio del comprador (el comprador o el HTML incrustado elige el monto). La opción es por producto, no por proyecto, así que un solo proyecto puede tener un catálogo de descargas a precio fijo junto a un bote de propinas y una página de "pon tu propio precio" en el mismo sitio, con una URL de webhook y un conjunto de credenciales de proveedor.
Nunca aceptamos un pago por un producto que no esté listado en tu catálogo. No hay una opción de "confiar en todo" a nivel de proyecto; cada checkout debe referenciar un producto que hayas configurado.
Por qué importa
Si el worker confiara en el atributo amount de cada botón de compra, un comprador podría abrir las herramientas de desarrollador de su navegador, editar amount="29.99" a amount="0.01", hacer clic en Comprar y pagar un centavo por un producto de $30. Los productos en modo fijo hacen eso imposible.
Modo fijo (el predeterminado seguro)
Los productos nuevos se crean en modo fijo. Configuras el precio en la pestaña Productos de tu panel; el elemento de compra en tu sitio referencia el producto por id. El worker lee el precio de tu catálogo e ignora cualquier monto o moneda que el elemento de compra pueda tener.
<coin-moebius-buy
project-id="proj_YOUR_ID"
product-id="t-shirt-medium"
label="Buy a t-shirt">
</coin-moebius-buy>Un comprador editando el HTML no puede cambiar el precio. El catálogo gana, siempre.
Modo precio del comprador (para botes de propinas, donaciones y paga lo que quieras)
Algunos productos solo tienen sentido si el comprador elige el monto: widgets de donación, botes de propinas, páginas de pon-tu-propio-precio. Para esos, configura el Precio del producto a Precio del comprador en el formulario del producto. El panel muestra un diálogo de seguridad primero porque es un cambio real de comportamiento: cualquiera con herramientas de desarrollador del navegador puede editar el monto antes de pagar. El precio que configuras en el producto se convierte en el predeterminado sugerido que el elemento de compra prellenará.
<coin-moebius-buy
project-id="proj_YOUR_ID"
product-id="tip-jar"
amount="5.00"
currency="USD"
label="Leave a tip">
</coin-moebius-buy>El generador de snippets por producto del panel produce la forma correcta automáticamente, con el monto sugerido ya incluido.
Cambiar un producto entre modos
Fijo y precio del comprador se alternan por producto, en el formulario del producto. Cambiar a precio del comprador abre un diálogo de seguridad único porque es la dirección destructiva; volver a fijo es inmediato. Los nuevos checkouts usan el nuevo modo de inmediato; las transacciones ya completadas no se afectan.
Suscripciones
Coin Moebius puede vender suscripciones recurrentes en cada proveedor fiat de tu menú. El comerciante configura el precio y el intervalo una vez en un producto; el botón de compra en el sitio se queda exactamente igual. El proveedor de pago maneja la facturación recurrente, guarda la tarjeta, reintenta renovaciones fallidas y aloja la página de cancelación. Coin Moebius retransmite los eventos del ciclo de vida a tu código.
Configurar un producto recurrente
En la pestaña Productos del panel, configura el campo Facturación a Mensual o Anual en lugar de Única. Un campo opcional de Prueba gratuita aparece para los días de prueba que quieras otorgar antes del primer cargo. Guarda el producto.
El HTML del botón de compra no cambia. El mismo atributo product-id="pro-plan" funciona para único o recurrente; el worker verifica la configuración de facturación del producto al momento del checkout y lo enruta por la API de suscripción del proveedor cuando aplique.
<coin-moebius-buy
project-id="proj_YOUR_ID"
product-id="pro-plan"
label="Subscribe to Pro">
</coin-moebius-buy>Lo que no tienes que construir
El proveedor maneja la programación. No guardamos tarjetas. No ejecutamos cron jobs. No reintentamos cargos fallidos. No enviamos correos de cobro. No alojamos una página de cancelación. Todo ese lado del sistema vive dentro de Stripe (o el proveedor fiat que hayas conectado). Estás externalizando las partes difíciles de la facturación recurrente a la compañía que ya las maneja para millones de comerciantes.
Eventos de suscripción
Las renovaciones y cancelaciones aparecen como eventos de webhook a los que tu servidor puede reaccionar. Cinco tipos normalizados cubren el ciclo de vida:
| Evento | Cuándo se dispara |
|---|---|
subscription.created | Nuevo registro. Lleva el monto del primer ciclo. |
subscription.renewed | Un ciclo no inicial tuvo éxito. Extiende el acceso hasta el nuevo fin de periodo. |
subscription.payment_failed | La tarjeta de un ciclo fue rechazada. El reintento de cobro del proveedor sigue su propio calendario; usualmente solo registras esto para visibilidad. |
subscription.canceled | Cancelación terminal. El comprador canceló, se agotaron los reintentos de cobro, o el comerciante canceló. |
subscription.updated | Cambio de estado, actualización de tarjeta, cambio de plan. Inspecciona el nuevo estado. |
Identificar compradores sin almacenarlos
Coin Moebius es un enrutador de pagos, no una base de datos de clientes. Nunca almacenamos correos, nombres, direcciones ni los ids internos del proveedor de los compradores. Si tu aplicación tiene cuentas de usuario (la mayoría de las apps de suscripción las tienen), pasa tu propio id de usuario opaco como customer-ref en el botón de compra. El botón lo envía al worker como metadata.customerRef, lo pasamos al proveedor, lo devolvemos en cada evento, y solo almacenamos esa cadena opaca. Para nosotros no tiene significado; para ti es la llave foránea a tu propio sistema de usuarios.
<coin-moebius-buy
project-id="proj_YOUR_ID"
product-id="pro-plan"
customer-ref="user_bob_42">
</coin-moebius-buy>Cuando necesites más detalle del comprador (correo, últimos cuatro dígitos de la tarjeta, notas de disputa), el panel le da a cada transacción un enlace "Ver en Stripe". Haces clic para ir al proveedor, donde realmente vive el registro del comprador. Nosotros nunca lo duplicamos.
Cancelación: enlaza, no construyas
Los compradores cancelan en el portal alojado del proveedor: el Portal de Cliente de Stripe, la página de cuenta PayPal del comprador, y así sucesivamente. El portal maneja cancelación, actualizaciones de tarjeta, descarga de recibos y cambios de plan, toda la interfaz que no tienes que construir. Puedes llevar al comprador al portal con una sola llamada API:
const res = await fetch(
`https://api.coinmoebius.com/api/subscriptions/${projectId}/${subId}/portal-url`,
{ method: 'POST', body: JSON.stringify({ returnUrl: 'https://you.example/account' }) },
);
const { url } = await res.json();
window.location.assign(url);Qué proveedores soportan suscripciones hoy
Stripe y PayPal funcionan de principio a fin a través del botón de compra alojado. Configura un producto como Mensual o Anual en tu panel, pega el botón en tu página, y el clic inicia una suscripción real. El proveedor ejecuta las renovaciones.
Square y Authorize.Net no funcionan a través del botón de compra alojado. Sus APIs de suscripción necesitan que la tarjeta del comprador se recolecte en tu propia página, usando el widget JavaScript del proveedor (Square Web Payments SDK, Authorize.Net Accept.js). Si estás dispuesto a agregar ese paso, el resto del sistema (enrutamiento de webhook, panel, endpoint de estado, vinculación de cliente) funciona exactamente igual que con las suscripciones de Stripe y PayPal. Consulta la siguiente sección.
Los proveedores de cripto (NOWPayments) no soportan facturación recurrente en este producto. La recurrencia cripto genera mucha fricción en cada gateway que hemos evaluado; preferimos no enviar nada que enviar una historia incompleta.
Úsalo sin el botón de compra
El botón de compra es una capa de conveniencia. Debajo, Coin Moebius es un webhook rentado más algunos endpoints JSON. Si prefieres construir tu propia interfaz, ejecutar tu propio flujo de checkout, o conectar Coin Moebius a algo que el botón no puede manejar (suscripciones de Square o Authorize.Net, un formulario de pago personalizado, un script del lado del servidor, una app móvil), cada endpoint que usa el botón también es accesible desde cualquier cosa. Sin cambios de código de nuestro lado.
Esto es lo que está disponible:
| Endpoint | Qué hace |
|---|---|
POST /api/checkout/{provider}/{projectId} | Inicia un checkout. POST { productId, metadata }; recibe lo que el proveedor necesita (una URL de redirección para Stripe, una URL de aprobación para PayPal, un token para Authorize.Net Accept Hosted). Renderízalo como quieras. |
POST /webhook/{provider}/{projectId} | El proveedor publica aquí. Verificamos la firma, normalizamos el evento, lo almacenamos, contamos cuota. Apunta el webhook del proveedor a esta URL sin importar si el checkout original vino de nuestro botón o de tu propia integración. |
GET /status/{projectId}/{txId} | Consulta el estado actual de un pago o suscripción. Devuelve la misma forma normalizada que obtiene el botón de compra. |
POST /api/subscriptions/{projectId}/{subscriptionId}/portal-url | Genera una URL de portal alojado por el proveedor para que el comprador administre su suscripción. Funciona para cualquier proveedor que tenga portal. |
Identifica al comprador en tu propio sistema pasando metadata.customerRef en la llamada de checkout. Se hila a través del proveedor y de vuelta en cada evento de webhook, para que puedas unir los registros de Coin Moebius a tu propia base de datos de usuarios sin que nosotros almacenemos nada sobre el comprador.
Por qué alguien usa este camino: un creador de sitios estáticos que quiere escribir su propio botón para que combine con el diseño de su sitio y solo necesita que el webhook se maneje. Un desarrollador que quiere saltarse el botón por completo y llamar a la API desde su propio servidor. Un comerciante que quiere ejecutar suscripciones de Square o Authorize.Net y no le importa configurar la recolección de tarjetas. El botón es un punto de partida. La API es el producto real.
Escuchar eventos del comprador
El elemento dispara tres eventos del navegador. Escucha con addEventListener en el elemento (o en document, los eventos burbujean). Todos los eventos son cancelables, llamar a event.preventDefault() detiene el flujo predeterminado.
| Evento | Cuándo se dispara | Payload de detalle |
|---|---|---|
cm-load-providers | El modal del selector está a punto de pedir a la API la lista de proveedores configurados en este proyecto. | Vacío. |
cm-checkout-started | El comprador eligió un proveedor y Coin Moebius está a punto de crear una sesión de checkout (Stripe / NOWPayments) o generar un código de referencia (manual). | { provider: 'stripe' | 'nowpayments' | 'manual', ... } |
cm-error | Algo falló: error de red, falla de firma, ningún proveedor configurado. | { error: Error } |
document.addEventListener('cm-error', (event) => {
console.error('Coin Moebius:', event.detail.error);
// Show your own error UI, send to your analytics, etc.
});No hay un evento cm-success en el navegador del comprador. Para cuando el pago realmente se completa, el comprador ha sido redirigido al checkout alojado del proveedor de pago (Stripe Checkout, página de factura de NOWPayments). Regresan a tu sitio a través de la success_url que configuraste (consulta la siguiente sección), y tu servidor se entera del pago a través del panel o consultando el endpoint /status.
Las URLs de éxito y cancelación
Cuando conectas Stripe o NOWPayments en la pestaña de Proveedores del panel, configuras dos URLs:
- URL de éxito, donde aterriza el comprador después de un pago exitoso. Stripe y NOWPayments agregan un parámetro de consulta (
?session_id=...para Stripe,?NP_id=...para NOWPayments) para que tu página de éxito pueda identificar qué transacción se completó. La mayoría de los sitios estáticos solo muestran un mensaje genérico de "Gracias, tu pago se está procesando" y confían en el panel como fuente de verdad. - URL de cancelación, donde aterriza el comprador si se retira antes de pagar. Frecuentemente es la misma que tu página de carrito.
Ambas URLs se configuran por proveedor en el panel, el elemento no necesita saber de ellas.
Configuración de proveedores
Stripe
- Inicia sesión en dashboard.stripe.com.
- Publishable key: Developers → API keys → "Publishable key" (comienza con
pk_live_opk_test_). - Secret key: misma página → "Secret key" → revelar (comienza con
sk_live_osk_test_). - Webhook signing secret: Developers → Webhooks → Add endpoint. La URL del endpoint se muestra en la página de tu proyecto en nuestro panel, cópiala de ahí. Suscribe el endpoint a
checkout.session.completed,charge.refundedycharge.dispute.created. Stripe muestra el signing secret una vez después de la creación (comienza conwhsec_). - En la pestaña de Proveedores de nuestro panel, haz clic en "Agregar proveedor" → Stripe, pega los tres valores más tu URL de éxito y URL de cancelación, guarda.
Pruebas: Usa las llaves de modo de prueba de Stripe (comienzan con pk_test_ y sk_test_) para ejecutar compras de prueba con los números de tarjeta de prueba de Stripe. No se mueve dinero real. También puedes usar el botón "Enviar evento de prueba" en la pestaña de Transacciones para crear una fila de Stripe de muestra al instante sin involucrar a Stripe en lo absoluto.
NOWPayments
- Inicia sesión en account.nowpayments.io.
- API key: Account → Store Settings → "API key".
- IPN secret: misma página → "IPN Secret Key".
- IPN callback URL: pega la URL del webhook de la página de tu proyecto en nuestro panel en el campo "IPN callback URL" de NOWPayments.
- En nuestro panel, haz clic en "Agregar proveedor" → NOWPayments, pega la API key y el IPN secret más tu URL de éxito y URL de cancelación, guarda.
Pruebas: NOWPayments no ofrece sandbox ni modo de prueba. Para verificar el viaje completo (checkout, callback IPN y fila de transacción en tu panel), envía un pago real usando una moneda de baja comisión (como TRX o LTC) al monto mínimo. Puedes revisar los mínimos actuales en la página de estado de NOWPayments. Unos centavos confirman que todo funciona de principio a fin. Si quieres ver cómo se ve una transacción de NOWPayments en tu panel antes de gastar algo, usa el botón "Enviar evento de prueba" en la pestaña de Transacciones y elige NOWPayments como proveedor.
Pago por correo (manual)
Sin cuentas externas, sin API keys, sin credenciales. Tú proporcionas una dirección postal y Coin Moebius genera un código de referencia único para cada transacción. Esto funciona para efectivo, cheques, giros postales, Goldbacks, metales preciosos, o cualquier otra cosa que un comprador pueda meter en un sobre.
- En tu panel, haz clic en "Agregar proveedor" → Pago por correo.
- Ingresa tu dirección postal. Esto es exactamente lo que el comprador ve cuando elige "Pago por correo" en el selector, así que usa la dirección donde realmente recibes paquetes.
- Ingresa la moneda esperada. Es formato libre: escribe
USDpara efectivo o cheques,GBKpara metales preciosos, o cualquier unidad que tenga sentido para lo que estás aceptando. Tú eres quien abre el sobre, así que tú decides qué cuenta. - Guarda. El comprador ahora puede elegir "Pago por correo" en el selector junto a cualquier otro proveedor que hayas conectado (Stripe, NOWPayments, etc.) y obtener un código de referencia único como
X2M-K9P-R7QWpara incluir con su envío.
No necesitas botones de compra separados para diferentes métodos de pago. El selector maneja la elección. Un solo botón en tu página puede ofrecer tarjetas, cripto y pago por correo a la vez.
Estados de transacción
Cada fila de transacción en el panel tiene uno de estos estados. El estado refleja el evento más reciente para esa transacción; los reembolsos y disputas actualizan la fila existente en lugar de insertar una fila hermana.
| Estado | Significado |
|---|---|
succeeded | Pago completado. El dinero está en tu cuenta (neto de comisiones del proveedor). |
pending | Pago en curso. Común con métodos de pago asíncronos (ACH, algunos rieles cripto) donde la confirmación toma minutos a horas. |
failed | El pago no se completó: tarjeta rechazada, autorización expirada, rechazo duro. No se movió dinero. |
partial | El comprador pagó menos de lo facturado (común cuando un comprador cripto envía un monto reducido por comisión de red). El amount de la fila refleja lo que realmente se recibió; revisa metadata.invoicedAmount para lo que se solicitó. |
refunded | El dinero ha sido devuelto al comprador, total o parcialmente. El amount de la fila es el monto reembolsado; los reembolsos pueden ocurrir días o semanas después del pago original. |
disputed | El comprador (o su banco) abrió una disputa o contracargo. Revisa la interfaz del proveedor para la ventana de respuesta. El metadata.reason de la fila lleva la clasificación del proveedor tal cual. |
pending_manual | Una transacción de pago por correo está esperando tu confirmación física. Consulta la siguiente sección. |
manual_canceled | Hiciste clic en Cancelar en una fila de pago por correo pendiente antes de que llegara el pago del comprador. |
manual_expired | Una fila de pago por correo pendiente estuvo 30 días sin confirmación y expiró automáticamente. |
manual_revoked | Confirmaste la recepción de un pago por correo pero después deshiciste la confirmación (ej., el pago resultó ser inválido). La fila pasa de succeeded a este estado terminal. |
El flujo de pago por correo
- El comprador hace clic en el botón de Coin Moebius en tu sitio y elige "Pago por correo" en el selector. Primero ve una vista previa: tu dirección postal, el monto a pagar y cualquier instrucción que hayas puesto, con un botón <strong>"Confirmar, enviaré el pago"</strong>. Todavía no se registra nada y no hay código de referencia en esta etapa.
- El comprador hace clic en "Confirmar, enviaré el pago." Ese es el paso que crea la transacción: Coin Moebius genera un código de referencia único como
X2M-K9P-R7QWy lo muestra junto a tu dirección postal. El comprador pone el código de referencia dentro del paquete o en el cheque. - Una vez que confirma, aparece una fila en la pestaña de Transacciones de tu panel con estado
pending_manual. La parte superior de la lista también muestra un aviso recordándote que hay confirmaciones de pago por correo esperando. - Cuando el pago del comprador llega a tu buzón (efectivo, cheque, Goldback, cualquiera que fuera la moneda esperada), escribe el código de referencia en la caja de búsqueda de la pestaña de Transacciones para encontrar la fila correspondiente. Haz clic en Marcar recibido. La URL de éxito del comprador se dispara (para que obtenga una página de confirmación), y procedes a enviar lo que compraron.
- Si el pago del comprador nunca llega, la fila expira automáticamente después de 30 días. También puedes Cancelar una fila manualmente antes de eso.
- Si confirmaste la recepción pero después descubres que el pago era inválido (falsificado, artículo equivocado, sobre vacío), haz clic en Deshacer confirmación en la fila. El estado cambia a
manual_revoked. Esto corrige tus registros en el panel. La comunicación con el comprador sobre lo que sucedió después es entre ustedes.
Probar pago por correo
El pago por correo no tiene sandbox, ni llaves de prueba, ni cuenta externa que configurar. Todo el flujo ocurre entre tu sitio y tu panel. Hay dos formas de probarlo: el viaje completo desde un botón de compra en una página, o una prueba rápida directo desde el panel.
Prueba rápida desde el panel
El panel puede crear una transacción de prueba para cualquier proveedor sin involucrar un pago real. Esto es útil para ver cómo se ve una fila de transacción, practicar el flujo de "Marcar recibido" para pago por correo, o previsualizar cómo aparece un pago cripto en tu lista antes de gastar dinero real.
- Abre la pestaña de Transacciones en tu proyecto y haz clic en Enviar evento de prueba.
- Elige un producto, selecciona qué paso (pago, reembolso, pago por correo, renovación de suscripción), y elige el proveedor que quieres simular (Stripe, NOWPayments o Pago por correo). Para eventos de pago por correo, el proveedor se configura automáticamente.
- Haz clic en Enviar evento de prueba. Una nueva fila aparece etiquetada "test" para que no se mezcle con datos reales. La fila aparece bajo el filtro de proveedor correcto, igual que una transacción real.
Para pago por correo específicamente, elige "Un pedido de pago por correo está esperando" para crear una fila pending_manual con un código de referencia real. Luego puedes practicar haciendo clic en "Marcar recibido," "Cancelar" y "Deshacer confirmación" en ella.
Los eventos de prueba no cuentan para tu cuota mensual de transacciones.
Viaje completo desde un botón de compra
Para probar el flujo completo (lo que tu comprador ve hasta lo que tú ves), sigue estos pasos. Todo toma unos dos minutos.
- Configura el proveedor. En tu panel, ve a la pestaña de Proveedores de tu proyecto y haz clic en "Agregar proveedor" → Pago por correo. Ingresa cualquier dirección postal (la tuya está bien para pruebas) y cualquier moneda (ej.,
USD,GBK). Guarda. - Agrega un producto. En la pestaña de Productos, crea un producto con un nombre como "Artículo de prueba" y un precio. Configura la moneda para que coincida con lo que ingresaste para el proveedor.
- Pon el botón de compra en una página. Pega el HTML del botón de compra en cualquier página, incluso un archivo HTML básico en tu computadora. Apunta el atributo
endpointa la URL de tu proyecto Cloud. Si estás ejecutando el worker localmente, usahttp://localhost:8787en su lugar. - Haz clic en el botón y elige "Pago por correo." El selector se abre mostrando cada proveedor que hayas conectado. Elige "Pago por correo." Verás una vista previa con tu dirección postal, el monto y moneda esperados, y un botón "Confirmar, enviaré el pago". Todavía sin código de referencia.
- Haz clic en "Confirmar, enviaré el pago." Esto es el comprador comprometiéndose a enviar el pago. Coin Moebius registra la transacción y muestra un código de referencia como
X2M-K9P-R7QW. - Abre el panel. Ve a la pestaña de Transacciones. Una nueva fila aparece con estado
pending_manualy el mismo código de referencia que acabas de ver. Si esta es tu primera fila pendiente, un aviso en la parte superior de la lista te recuerda que hay pagos por correo esperando confirmación. - Haz clic en "Marcar recibido." El estado de la fila cambia a
succeeded. Ese es el camino feliz completo, desde el clic del comprador hasta tu confirmación.
Encontrar una transacción por código de referencia
Cuando un pago llega a tu buzón, busca el código de referencia que incluyó el comprador (impreso en el sobre, escrito en el memo del cheque, o metido dentro del paquete). Luego escribe ese código en la caja de búsqueda de la pestaña de Transacciones y presiona Enter. La tabla filtra a las filas que coinciden para que puedas hacer clic en "Marcar recibido" en la correcta sin navegar por todo tu historial de transacciones.
Probar los otros resultados
Repite los mismos pasos, pero en lugar de marcar la fila como recibida, prueba cada uno de estos:
- Cancélala. Haz clic en "Cancelar" en la fila pendiente. El estado cambia a
manual_canceled. Esto es lo que harías cuando un comprador te dice que cambió de opinión antes de enviar algo. - Déjala expirar. Deja una fila pendiente sola. Después de 30 días expira automáticamente a
manual_expired. No necesitas esperar 30 días para verificar el comportamiento. La expiración funciona igual que Cancelar, excepto que sucede automáticamente en un calendario. - Ingresa un monto diferente. Al hacer clic en "Marcar recibido," ingresa un monto recibido que difiera de lo esperado (ej., el comprador envió 4 Goldbacks en lugar de 5). La transacción aún tiene éxito, pero el panel muestra tanto el monto esperado como el recibido para que tus registros reflejen lo que realmente llegó.
- Deshaz una confirmación. Primero marca una fila como recibida para que muestre
succeeded, luego haz clic en "Deshacer confirmación" en esa fila. El estado cambia amanual_revoked. Así es como corriges un error o marcas un pago que resultó ser inválido después del hecho.
Qué buscar
- El código de referencia en el selector coincide con el código de referencia en la fila del panel.
- Tu dirección postal se muestra correctamente en el selector.
- Los botones "Marcar recibido" y "Cancelar" aparecen solo en filas
pending_manual, no en transacciones de tarjeta o cripto. - Después de marcar como recibido, la fila muestra
succeededcon el monto correcto. - Buscar por código de referencia en la caja de búsqueda encuentra la fila correcta.
Las transacciones de viaje completo creadas durante las pruebas cuentan para tu cuota mensual. En el plan gratuito (100 transacciones/mes), un puñado de pruebas no hace mella. Los eventos de prueba enviados desde el botón "Enviar evento de prueba" del panel no cuentan en absoluto.
Reembolsos, disputas, pagos parciales
Coin Moebius escucha estos eventos del proveedor y actualiza la fila de transacción original en el panel. Específicamente:
- Reembolsos: el evento
charge.refundedde Stripe (reembolsos totales o parciales, incluyendoamount_refundedpara que los reembolsos parciales muestren la porción devuelta). El IPNrefundedde NOWPayments. El estado de la fila cambia arefunded, elamountrefleja el monto reembolsado, ymetadata.originalChargeId/metadata.originalAmountllevan el contexto del pago original. - Disputas (contracargos): el evento
charge.dispute.createdde Stripe. El estado de la fila cambia adisputed. La razón declarada por el proveedor pasa tal cual ametadata.reason, puedes renderizarla en tu propia interfaz como quieras. - Pagos parciales: el IPN
partially_paidde NOWPayments. El estado de la fila cambia apartial. Elamountrefleja lo que realmente se recibió (actually_paid);metadata.invoicedAmountes lo que se solicitó.
En v1, estos eventos se muestran en el panel y a través del endpoint /status. Una versión futura agregará notificaciones por correo y un reenviador de webhooks salientes para que tu propio backend pueda reaccionar automáticamente. Por ahora, configura un pequeño trabajo de consulta (consulta la siguiente sección) o revisa el panel.
Consultas desde tu backend
Para una fuente de verdad del lado del servidor, consulta GET /status/:projectId/:txId desde tu backend. La forma de la respuesta:
{
"status": "succeeded",
"amount": 29.99,
"currency": "USD",
"isTest": false,
"createdAt": "2026-05-14T01:04:21.000Z",
"updatedAt": "2026-05-14T01:04:21.000Z"
}Los valores de estado siguen el mismo enum que el panel (consulta Estados de transacción). El endpoint no requiere autenticación pero tiene un límite de 60 solicitudes / minuto por IP. El id de transacción que pasas es lo que el SDK devolvió en el evento cm-checkout-started o lo que se muestra en la columna de Referencia del panel.
Un patrón típico: cuando tu página success_url carga, inicia un trabajo en backend que consulta /status/:projectId/:txId cada 15 segundos hasta que vea succeeded (o failed / un timeout), luego completa el pedido.