Stampa ESC/POS dal Browser: Guida per Sviluppatori

Il Problema della Stampa dal Browser

Se hai mai provato a stampare una ricevuta da un'applicazione web, conosci il dolore: window.print() apre una finestra di dialogo di stampa, rende la pagina come PDF e non ha alcun supporto per i comandi ESC/POS come il taglio automatico o la larghezza della carta personalizzata.

Per le stampanti termiche per ricevute, questo è un problema insormontabile. Hai bisogno di:

  • Stampa silenziosa — nessuna finestra di dialogo, nessuna interazione con l'utente
  • Comandi ESC/POS — per taglio automatico, testo in grassetto, allineamento, codici a barre
  • Codifica affidabile — UTF-8 alla pagina di codice corretta per la tua stampante
  • Supporto multipiattaforma — Mac, Windows, Linux

La soluzione è un bridge WebSocket locale — una piccola applicazione in background che gira sul computer dell'utente, accetta lavori di stampa dalla tua applicazione web e invia comandi ESC/POS grezzi alla stampante.


Come Funziona il Bridge WebSocket

La tua Web App  →  WebSocket (ws://localhost:8765)  →  Print Agent  →  Stampante Termica

Il flusso è semplice:

  1. La tua applicazione web apre una connessione WebSocket a ws://localhost:8765
  2. Invii un payload JSON che descrive la ricevuta
  3. Print Agent lo converte in ESC/POS e lo invia alla stampante
  4. La stampante stampa silenziosamente — nessuna finestra di dialogo, nessuna interazione con il driver

MenuForma Print Agent implementa questo bridge. È gratuito, open source e funziona su Mac, Windows e Linux.


Riferimento API

Connessione

const ws = new WebSocket('ws://localhost:8765');

ws.onopen = () => {
  console.log('Print Agent connesso');
};

ws.onerror = () => {
  console.log('Print Agent non in esecuzione');
};

Controlla lo Stato dell'Agente

Invia un ping per verificare che l'agente sia in esecuzione:

ws.send(JSON.stringify({ type: 'ping' }));

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.type === 'pong') {
    console.log('Versione Agente:', data.version);
  }
};

Stampa una Ricevuta

const receipt = {
  type: 'print',
  printer: 'auto',   // o IP specifico come '192.168.1.100'
  data: {
    storeName: 'Il Mio Ristorante',
    storeAddress: 'Via Principale 123',
    orderNumber: '#1042',
    tableNumber: 'Tavolo 5',
    items: [
      { name: 'Pizza Margherita', qty: 1, price: 14.90 },
      { name: 'Acqua Frizzante', qty: 2, price: 3.50 },
    ],
    subtotal: 21.90,
    tax: 1.97,
    total: 23.87,
    paymentMethod: 'Carta',
    footer: 'Grazie per aver cenato con noi!',
  }
};

ws.send(JSON.stringify(receipt));

Esempio di Integrazione React

import { useEffect, useRef, useCallback, useState } from 'react';

function usePrintAgent() {
  const wsRef = useRef(null);
  const [connected, setConnected] = useState(false);

  useEffect(() => {
    const connect = () => {
      const ws = new WebSocket('ws://localhost:8765');
      ws.onopen = () => setConnected(true);
      ws.onclose = () => {
        setConnected(false);
        setTimeout(connect, 3000); // riprova
      };
      wsRef.current = ws;
    };
    connect();
    return () => wsRef.current?.close();
  }, []);

const print = useCallback((receiptData) => { if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) { throw new Error('Print Agent not connected'); } wsRef.current.send(JSON.stringify({ type: 'print', data: receiptData })); }, []);

return { connected, print }; }


---

## Integrazione Shopify

Per i negozi Shopify, puoi attivare la stampa da un webhook d'ordine o da un'estensione del browser:

```javascript
// Nel tuo negozio Shopify o nell'estensione amministrativa
async function printShopifyOrder(order) {
  const ws = new WebSocket('ws://localhost:8765');
  
  ws.onopen = () => {
    ws.send(JSON.stringify({
      type: 'print',
      data: {
        storeName: order.shop_name,
        orderNumber: order.name,
        items: order.line_items.map(item => ({
          name: item.title,
          qty: item.quantity,
          price: parseFloat(item.price),
        })),
        total: parseFloat(order.total_price),
        paymentMethod: order.payment_gateway,
      }
    }));
  };
}

Configurazione della stampante

Il campo "printer" nel payload di stampa accetta:

Valore Descrizione
"auto" Usa la stampante configurata nelle impostazioni di Print Agent
"192.168.1.100" Connettiti direttamente a una stampante di rete tramite IP
"USB" Usa la prima stampante USB rilevata

Gestione degli errori

ws.onmessage = (event) => {
  const response = JSON.parse(event.data);
  
  if (response.type === 'print_success') {
    console.log('Stampato con successo');
  } else if (response.type === 'print_error') {
    console.error('Stampa fallita:', response.error);
    // Mostra UI di fallback o riprova
  }
};

Rilevamento dell'installazione di Print Agent

Prima di mostrare la funzionalità di stampa nella tua UI, verifica se l'agente è in esecuzione:

async function isPrintAgentAvailable() {
  return new Promise((resolve) => {
    const ws = new WebSocket('ws://localhost:8765');
    const timeout = setTimeout(() => {
      ws.close();
      resolve(false);
    }, 1000);
    ws.onopen = () => {
      clearTimeout(timeout);
      ws.close();
      resolve(true);
    };
    ws.onerror = () => {
      clearTimeout(timeout);
      resolve(false);
    };
  });
}

// Utilizzo
const agentAvailable = await isPrintAgentAvailable();
if (!agentAvailable) {
  // Mostra il prompt di download
  window.open('/print-agent', '_blank');
}

Scarica Print Agent

MenuForma Print Agent è gratuito e disponibile per Mac, Windows e Linux. Supporta stampanti termiche USB, di rete e Bluetooth, e implementa l'API WebSocket completa descritta in questa guida.

Per la documentazione completa dell'API e il codice open-source, visita la pagina di Print Agent.

Related Articles

MenuForma Products