Saltar al contenido

Imprimir en una impresora POS desde PHP

octubre 21, 2021
apple touch icon@2

Autor de escpos-php aquí.

Si sus impresoras son compatibles con ESC / POS (la mayoría de las impresoras térmicas de recibos parecen usar algún subconjunto), entonces creo que el controlador se adaptará a su caso de uso: USB o impresión en red, logotipo, algún formato. Algunas de estas son adiciones bastante recientes.

Impresión USB

escpos-php imprime en un puntero de archivo. En Linux, puede hacer que la impresora USB sea visible como un archivo usando el usblp conductor, y luego solo fopen() eso (Ejemplo de recibo USB, entrada de blog sobre la instalación de una impresora USB en Linux).

Por lo tanto, imprimir «Hola mundo» en una impresora USB es solo ligeramente diferente a imprimir en una impresora en red:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42EscposPrintConnectorsFilePrintConnector;
use Mike42EscposPrinter;
$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);

$printer -> text("Hello World!n");
$printer -> cut();

$printer -> close();

O, más como el código que está utilizando actualmente con éxito, puede escribir en un archivo temporal y copiarlo:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42EscposPrintConnectorsFilePrintConnector;
use Mike42EscposPrinter;

/* Open file */
$tmpdir = sys_get_temp_dir();
$file =  tempnam($tmpdir, 'ctk');

/* Do some printing */
$connector = new FilePrintConnector($file);
$printer = new Printer($connector);
$printer -> text("Hello World!n");
$printer -> cut();

$printer -> close();

/* Copy it over to the printer */
copy($file, "//localhost/KoTickets");
unlink($file);

Entonces, en su sistema POS, necesitaría una función que devuelva un puntero de archivo según la configuración de su cliente y el destino preferido. Las impresoras de recibos responden con bastante rapidez, pero si tiene algunos iPads haciendo pedidos, debe ajustar las operaciones a cada impresora con un bloqueo de archivo (rebaño()) para evitar problemas relacionados con la concurrencia.

También tenga en cuenta que la compatibilidad con USB en Windows no está probada.

Logotipo y formato

Una vez que haya descubierto cómo planea hablar con la impresora, puede usar el conjunto completo de comandos de formato e imagen.

Se puede imprimir un logotipo desde un archivo PNG así:

use Mike42EscposEscposImage;
$logo = EscposImage::load("foo.png");
$printer -> graphics($logo);

Y para formatear, el README.md y el siguiente ejemplo debería ayudarlo a comenzar. Para la mayoría de los recibos, solo necesita:

  • selectPrintMode() para alterar los tamaños de fuente.
  • setEmphasis() para alternar en negrita.
  • setJustification() para alinear a la izquierda o centrar algunos textos o imágenes.
  • cut() después de cada recibo.

También sugeriría que, donde actualmente está usando un ejemplo que dibuja cuadros como este:

=========
|       |
=========

Podrías hacer uso de los personajes en IBM Página de códigos 437 que están diseñados para dibujar cuadros que son compatibles con muchas impresoras, solo incluya los caracteres 0xB3 a 0xDA en la salida. No son perfectos, pero parece mucho menos «texto» -y.

$box = "xda".str_repeat("xc4", 10)."xbfn";
$box .= "xb3".str_repeat(" ", 10)."xb3n";
$box .= "xc0".str_repeat("xc4", 10)."xd9n";
$printer -> textRaw($box);

Ejemplo completo

El siguiente ejemplo es también ahora incluido con el conductor. Creo que parece un recibo de tienda bastante típico, en cuanto al formato, y podría adaptarse fácilmente a su escenario de cocina.

Salida escaneada:

Ejemplo de recibo formateado con logotipo

Código fuente PHP para generarlo:

<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42EscposPrinter;
use Mike42EscposEscposImage;
use Mike42EscposPrintConnectorsFilePrintConnector;

/* Open the printer; this will change depending on how it is connected */
$connector = new FilePrintConnector("/dev/usb/lp0");
$printer = new Printer($connector);

/* Information for the receipt */
$items = array(
    new item("Example item #1", "4.00"),
    new item("Another thing", "3.50"),
    new item("Something else", "1.00"),
    new item("A final item", "4.45"),
);
$subtotal = new item('Subtotal', '12.95');
$tax = new item('A local tax', '1.30');
$total = new item('Total', '14.25', true);
/* Date is kept the same for testing */
// $date = date('l jS of F Y h:i:s A');
$date = "Monday 6th of April 2015 02:56:25 PM";

/* Start the printer */
$logo = EscposImage::load("resources/escpos-php.png", false);
$printer = new Printer($connector);

/* Print top logo */
$printer -> setJustification(Printer::JUSTIFY_CENTER);
$printer -> graphics($logo);

/* Name of shop */
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
$printer -> text("ExampleMart Ltd.n");
$printer -> selectPrintMode();
$printer -> text("Shop No. 42.n");
$printer -> feed();

/* Title of receipt */
$printer -> setEmphasis(true);
$printer -> text("SALES INVOICEn");
$printer -> setEmphasis(false);

/* Items */
$printer -> setJustification(Printer::JUSTIFY_LEFT);
$printer -> setEmphasis(true);
$printer -> text(new item('', '$'));
$printer -> setEmphasis(false);
foreach ($items as $item) {
    $printer -> text($item);
}
$printer -> setEmphasis(true);
$printer -> text($subtotal);
$printer -> setEmphasis(false);
$printer -> feed();

/* Tax and total */
$printer -> text($tax);
$printer -> selectPrintMode(Printer::MODE_DOUBLE_WIDTH);
$printer -> text($total);
$printer -> selectPrintMode();

/* Footer */
$printer -> feed(2);
$printer -> setJustification(Printer::JUSTIFY_CENTER);
$printer -> text("Thank you for shopping at ExampleMartn");
$printer -> text("For trading hours, please visit example.comn");
$printer -> feed(2);
$printer -> text($date . "n");

/* Cut the receipt and open the cash drawer */
$printer -> cut();
$printer -> pulse();

$printer -> close();

/* A wrapper to do organise item names & prices into columns */
class item
{
    private $name;
    private $price;
    private $dollarSign;

    public function __construct($name="", $price="", $dollarSign = false)
    {
        $this -> name = $name;
        $this -> price = $price;
        $this -> dollarSign = $dollarSign;
    }

    public function __toString()
    {
        $rightCols = 10;
        $leftCols = 38;
        if ($this -> dollarSign) {
            $leftCols = $leftCols / 2 - $rightCols / 2;
        }
        $left = str_pad($this -> name, $leftCols) ;

        $sign = ($this -> dollarSign ? '$ ' : '');
        $right = str_pad($sign . $this -> price, $rightCols, ' ', STR_PAD_LEFT);
        return "$left$rightn";
    }
}

close