1 Introducción

ReceiptPrint SDK es una librería JavaScript desarrollada por Tapara Dev que permite imprimir recibos térmicos en dispositivos Sunmi POS directamente desde su aplicación web. Un solo script, una sola API — sin necesidad de conocer el SDK nativo de Sunmi.

Compatibilidad Sunmi V1s, V2, V2 Pro, V2s, T2s, P2, D2s y cualquier dispositivo Sunmi con impresora térmica integrada y servicio de impresión activo.

Cómo funciona

  • Validación de licenciaEl script consulta los servidores de Tapara Dev para verificar que la licencia es válida y que la solicitud proviene del dominio autorizado.
  • Carga del bundle cifradoSe descarga el núcleo del SDK autenticado con un token de sesión de corta duración.
  • Conexión con la impresoraEl SDK establece conexión WebSocket local (ws://localhost:7070/ws) con el servicio de impresión del dispositivo Sunmi.

2 Requisitos previos

RequisitoDetalle
Dispositivo SunmiCualquier Sunmi POS con impresora térmica integrada.
Servicio de impresiónEl servicio Sunmi Printer Service debe estar corriendo en el dispositivo (normalmente activo por defecto). Escucha en ws://localhost:7070/ws.
Llave de licenciaProvista por Tapara Dev. Está ligada a su dominio de producción. Sin llave válida el SDK no carga.
Dominio HTTPSSu aplicación debe servirse desde el dominio exacto registrado en la licencia. www.mitienda.com y mitienda.com son dominios diferentes.
Conexión a internetNecesaria al cargar la página para la validación inicial. La impresión ocurre localmente y no requiere internet.
Solo funciona en Sunmi La conexión WebSocket local (localhost:7070) solo existe en dispositivos Sunmi. Desde un PC o celular no-Sunmi el SDK cargará pero init() fallará con un error de conexión.

3 Integración en 2 pasos

Paso 1 — Agregar el script al <head>

Incluya el tag en el <head> de todas las páginas que necesiten imprimir. Reemplace SU_LLAVE_AQUI con la llave entregada por Tapara Dev.

HTML
<!-- ReceiptPrint SDK -->
<script src="https://sdk.taparadev.com/static/sdk/receipt-print.js?key=SU_LLAVE_AQUI"></script>
Un solo script por página No incluya el script más de una vez. El parámetro ?key= debe ser la llave completa exactamente como la recibió.

Paso 2 — Inicializar y usar la API

JavaScript
// Inicializar (conecta con la impresora)
ReceiptPrint.init("SU_LLAVE_AQUI")
  .then(function() { console.log("Impresora lista"); })
  .catch(function(err) { console.error("Error:", err.message); });

// Imprimir un recibo
ReceiptPrint.print({
  header: { name: "Mi Tienda", address: "Av. Principal 123", phone: "2222-3333" },
  items: [
    { description: "Producto A", qty: 2, price: 1500 },
    { description: "Producto B", qty: 1, price: 3000 }
  ],
  totals: { subtotal: 6000, tax: 780, total: 6780, paymentMethod: "Efectivo" },
  footer: "¡Gracias por su compra!"
});

4 ReceiptPrint.init()

ReceiptPrint.init(key, options?) → Promise<void>

Inicializa el SDK y establece conexión con la impresora Sunmi. Debe llamarse antes de cualquier operación de impresión. Se resuelve cuando la impresora está lista, o se rechaza si hay un error.

Parámetros

ParámetroTipoDescripción
key requeridostringLlave de licencia provista por Tapara Dev.
options opcionalobjectOpciones de inicialización.

Opciones

OpciónTipoPor defectoDescripción
paperWidthnumberSegún licenciaAncho del papel en mm. Valores válidos: 58 o 80.
Ejemplo
ReceiptPrint.init("MI_LLAVE").then(...);
ReceiptPrint.init("MI_LLAVE", { paperWidth: 58 }).then(...);
Llamar init() una sola vez Llame a init() una vez al cargar la aplicación. No es necesario llamarlo antes de cada impresión. Si ya está inicializado, la llamada retorna inmediatamente.

5 ReceiptPrint.print(receipt)

ReceiptPrint.print(receipt) → Promise<void>

Imprime un recibo completo a partir de un objeto JSON. Todos los campos son opcionales excepto items y totals.total.

header — encabezado del negocio

CampoTipoDescripción
header.namestringNombre del negocio (centrado, grande).
header.addressstringDirección física.
header.phonestringNúmero de teléfono.
header.taxIdstringCédula jurídica / RUC / NIT.
header.extrastringLínea adicional de encabezado.
logostring (URL)Logo del negocio. PNG cuadrado, mínimo 200×200 px, fondo blanco.

meta — metadatos del recibo

CampoTipoDescripción
meta.numberstringNúmero de recibo / factura.
meta.datestringFecha y hora de la venta.
meta.cashierstringNombre del cajero.
meta.customerstringNombre del cliente.

items — líneas de producto requerido

CampoTipoDescripción
items[].descriptionstringNombre del producto o servicio.
items[].qtynumberCantidad vendida.
items[].pricenumberPrecio unitario.

totals — totales

CampoTipoDescripción
totals.subtotalnumberSubtotal antes de impuestos.
totals.taxnumberMonto del impuesto (IVA, IGV, etc.).
totals.discountnumberDescuento aplicado.
totals.tipnumberPropina.
totals.total requeridonumberMonto total a cobrar.
totals.paymentMethodstringForma de pago (ej: "Efectivo", "Tarjeta Visa").
totals.cashReceivednumberEfectivo recibido del cliente.
totals.changenumberCambio devuelto al cliente.

QR, barcode, imagen y otros

CampoTipoDescripción
qrstringContenido del código QR (URL, texto, etc.).
qrLabelstringEtiqueta debajo del QR.
barcodestringContenido del código de barras.
barcodeLabelstringEtiqueta debajo del código de barras.
imagestring (URL)Imagen adicional (ej: firma digital).
footerstringMensaje de cierre.
currencystringSímbolo de moneda. Por defecto:

Ejemplo completo

JavaScript
ReceiptPrint.print({
  logo:   "https://mitienda.com/logo.png",
  header: { name: "Supermercado Don Pepe", address: "Av. Central 45", phone: "2222-3333", taxId: "3-101-999999" },
  meta:   { number: "REC-00421", date: "25/04/2026 10:45", cashier: "María López" },
  items: [
    { description: "Arroz 1kg",        qty: 2, price: 950  },
    { description: "Frijoles 500g",     qty: 3, price: 650  },
    { description: "Aceite vegetal 1L", qty: 1, price: 1800 }
  ],
  totals: { subtotal: 5750, tax: 747, total: 6497, paymentMethod: "Efectivo", cashReceived: 7000, change: 503 },
  qr:     "https://mitienda.com/factura/REC-00421",
  footer: "¡Gracias por su preferencia!",
  currency: "₡"
})
.then(() => console.log("Impreso ✓"))
.catch(err => console.error(err.message));

6 Métodos adicionales

ReceiptPrint.printImage(url, align?) → Promise<void>

Imprime una sola imagen. align: "left", "center" (por defecto) o "right".

ReceiptPrint.printQR(data, label?) → Promise<void>

Imprime un código QR. data es el texto o URL a codificar. label es la etiqueta opcional debajo.

ReceiptPrint.printBarcode(data, label?) → Promise<void>

Imprime un código de barras. label es la etiqueta opcional debajo.

ReceiptPrint.getStatus() → Promise<StatusObj>

Consulta el estado de la impresora. Retorna { ok, status, message, raw }. Los valores de status: "ready" · "cover_open" · "paper_jam" · "no_paper" · "overheating" · "error".

ReceiptPrint.isReady() → boolean

Retorna true si el SDK ya fue inicializado. Útil para verificación sincrónica.

7 Manejo de errores

Todas las operaciones del SDK devuelven Promises. Use siempre .catch() o try/catch con async/await para capturar errores.

Errores comunes

  • License invalidLa llave no existe o está inactiva. Contacte a Tapara Dev.
  • License expiredLa licencia venció. Contacte a Tapara Dev para renovarla.
  • Domain not allowedLa página se carga desde un dominio diferente al registrado en la licencia.
  • Impresora no disponibleEl servicio Sunmi no está corriendo o localhost:7070 no está accesible.
  • Not initializedSe llamó a print() antes de que init() completara.

Patrón recomendado

JavaScript
async function imprimirRecibo(datos) {
  try {
    if (!ReceiptPrint.isReady()) {
      await ReceiptPrint.init("MI_LLAVE");
    }
    await ReceiptPrint.print(datos);
  } catch (err) {
    alert("No se pudo imprimir: " + err.message);
  }
}

8 Ejemplos completos

Página HTML mínima

HTML
<!DOCTYPE html><html>
<head>
  <script src="https://sdk.taparadev.com/static/sdk/receipt-print.js?key=MI_LLAVE"></script>
</head>
<body>
  <button onclick="imprimir()">Imprimir</button>
  <script>
    ReceiptPrint.init("MI_LLAVE").catch(e => alert(e.message));

    function imprimir() {
      ReceiptPrint.print({
        header: { name: "Mi Tienda", phone: "2222-3333" },
        items:  [{ description: "Artículo", qty: 1, price: 1000 }],
        totals: { total: 1000, paymentMethod: "Efectivo" },
        footer: "¡Gracias!"
      }).catch(e => alert(e.message));
    }
  </script>
</body></html>

Con async/await y verificación de estado

JavaScript
ReceiptPrint.init("MI_LLAVE")
  .then(() => { btnImprimir.disabled = false; })
  .catch(err => mostrarError(err.message));

async function procesarVenta(venta) {
  const s = await ReceiptPrint.getStatus();
  if (!s.ok) throw new Error("Impresora no disponible: " + s.message);

  await ReceiptPrint.print({
    header: { name: venta.tienda },
    items:  venta.lineas.map(l => ({ description: l.producto, qty: l.cantidad, price: l.precio })),
    totals: { total: venta.total, paymentMethod: venta.metodoPago },
    footer: "¡Gracias por su compra!"
  });
}

Solo QR o código de barras

JavaScript
await ReceiptPrint.printQR("https://mitienda.com/cliente/12345", "Escanee para ver sus puntos");
await ReceiptPrint.printBarcode("7501055360006", "Arroz Premium 1kg");

9 Preguntas frecuentes

¿Funciona en cualquier navegador del dispositivo Sunmi?
Sí, mientras sea un navegador moderno con soporte para ES6 Promises y Fetch API. El navegador integrado de Sunmi (basado en WebView/Chromium) es compatible. También funciona en Chrome u otros navegadores instalados.
¿Puedo usar el SDK en localhost para desarrollo?
Sí, pero necesita una licencia configurada para localhost. Solicite a Tapara Dev una licencia de desarrollo. La impresora seguirá siendo inaccesible a menos que esté en un dispositivo Sunmi.
¿Qué pasa si la licencia expira?
El script deja de cargar en nuevas sesiones. Las sesiones actualmente abiertas seguirán funcionando hasta que la página se cierre. Contacte a Tapara Dev para renovar antes del vencimiento.
¿El SDK envía mis datos de ventas a algún servidor?
No. Los datos del recibo nunca abandonan el dispositivo. La única comunicación con servidores externos es la validación de licencia al cargar la página.
¿Puedo cambiar el símbolo de moneda?
Sí, use el campo currency en el objeto receipt. El valor por defecto es . Puede usar cualquier símbolo: "$", "€", "Q", "S/", etc.
¿Cómo sé que el ancho de papel está bien configurado?
El ancho (58 mm o 80 mm) se configura en la licencia por Tapara Dev. Si nota que el texto se corta o hay espacios en blanco extraños, contacte a soporte para ajustar el parámetro.

10 Soporte

Para consultas técnicas, renovación de licencias o reportar incidencias:

CanalContacto
Correo electrónico[email protected]
Sitio webtaparadev.com
Tiempo de respuesta Respondemos en horario hábil (lunes a viernes, 8am – 6pm, GMT-6). Para emergencias en producción indique en el asunto: "URGENTE – [nombre de su empresa]".