Cómo crear ticket en PDF con PHP en 3 pasos pdf ticket

Facebook
Twitter
LinkedIn
WhatsApp
Ticket en PDF

Table of Contents

Si dispones de algún ERP o POS y lo que quieres es crear ticket o una factura simplificada, este es tu POST.

Existen varias librerías para poder generar ficheros PDF en PHP, pero vamos a usar la librería FPDF.

¿Qué es FPDF?

Generar pdf con FPDF
FPDF es una librería para generar PDF con PHP.

FPDF es una clase PHP que permite generar ficheros PDF con PHP (no utiliza la biblioteca PDFlib). Es gratuito: puedes usarlo y modificarlo para cualquier tipo de uso. Puedes personalizarlo de la siguiente manera:

  • Selección de unidad de medida, formato de página y márgenes.
  • Encabezado de página y gestión de pie de página.
  • Salto de página automático.
  • Salto de línea automático y justificación de texto.
  • Soporte de imágenes (JPEG, PNG y GIF).
  • Colores.
  • Enlaces.
  • TrueType, Type1 y soporte de codificación.
  • Compresión de página.

FPDF no requiere extensión (excepto Zlib para habilitar la compresión y GD para soporte GIF). La última versión requiere al menos PHP 5.1.

Empezamos..

  1. Vamos a crear un fichero php, lo vamos a llamar factura.php
  2. Descargamos la última versión que ofrece FPDF que es la versión 1.81.
  3. Enlazamos la librería con nuestro fichero mediante «require».
  4. (Opcional) Almacenamos en una constante el símbolo Euro.
  5. Llamamos a la función FPDF y tenemos que pasar 3 parámetros:
    • Orientación de la página:
      • (P) Vertical
      • (L) Horizontal
    • Unidad de medida:
      • (pt) Punto
      • (mm) Milímetro
      • (cm) Centímetro
      • (in) Pulgada
    • Tamaño de la Página:
      • A3
      • A4 (Por defecto)
      • A5
      • Carta
      • Documento legal
      • Personalizado ► array(x,y) ► El ancho del ticket es de 80mm y de largo añadimos 150mm
  6. Añadimos la página del PDF.

Este sería el resultado:

// CONFIGURACIÓN PREVIA
require('fpdf181/fpdf.php');
define('EURO',chr(128)); // Constante con el símbolo Euro.
$pdf = new FPDF('P','mm',array(80,150)); // Tamaño tickt 80mm x 150 mm (largo aprox)
$pdf->AddPage();

Preparamos la cabecera del ticket en PDF

En la cabecera vamos a poner los datos de la empresa, CIF, dirección, teléfono y página web. Las funciones que nos vamos a encontrar en el siguiente código son:

  • SetFont. Deberemos de rellenar los siguientes parámetros:
    • Fuente (Escribimos el nombre de la fuente)
    • Estilo:
      • Vacío Normal
      • B Negrita
      • I Itálica
      • U Subrayado
    • Tamaño (valor en pt)
  • Cell. Imprime una celda con bordes, color de fondo y un string. La posición inicial se ubica arriba a la izquierda. El texto puede estar alineado o centrado. (Opcional) existe la posibilidad de añadir un enlace al string. Estos son los parámetros que hay que rellenar:
    • Anchura de la celda. Si es 0, la celda se extiende hasta el margen derecho.
    • Altura de la celda. Por defecto es 0
    • La cadena o el string a imprimir.
    • Borde en la celda:
      • 1 Si
      • 0 No (Por defecto)
      • O una cadena que contiene algunos o todos los siguientes caracteres (en cualquier orden):
        • L: Izquierda
        • T: Parte superior
        • R: Derecha
        • B: Parte inferior
    • Indica en qué posición debe de ir la celda después de la llamada. Poner 1es equivalente a poner 0y llamar a Ln () justo después. Hay 3 opciones:
      • 0Derecha
      • 1 Al comienzo de la siguiente línea
      • 2 Abajo
    • Permite centrar o alinear el texto. Los valores posibles son:
      • L (o vacío) Alinear texto a la izquierda (valor predeterminado)
      • C: Alinear texto al centro
      • R: Alinear texto a la derecha
    • Opcional: Indica si el fondo de la celda debe estar pintado ( true) o transparente ( false).
    • Opcional: URL del enlace.
  • Ln. Realiza uno o varios saltos de línea. Vuelve al márgen izquierdo y según la cantidad pasada como parámetro, se sitúa más abajo.

// CABECERA
$pdf->SetFont('Helvetica','',12);
$pdf->Cell(60,4,'Lacodigoteca.com',0,1,'C');
$pdf->SetFont('Helvetica','',8);
$pdf->Cell(60,4,'C.I.F.: 01234567A',0,1,'C');
$pdf->Cell(60,4,'C/ Arturo Soria, 1',0,1,'C');
$pdf->Cell(60,4,'C.P.: 28028 Madrid (Madrid)',0,1,'C');
$pdf->Cell(60,4,'999 888 777',0,1,'C');
$pdf->Cell(60,4,'[email protected]',0,1,'C');
 
// DATOS FACTURA        
$pdf->Ln(5);
$pdf->Cell(60,4,'Factura Simpl.: F2019-000001',0,1,'');
$pdf->Cell(60,4,'Fecha: 28/10/2019',0,1,'');
$pdf->Cell(60,4,'Metodo de pago: Tarjeta',0,1,'');

  • Multicell. A diferencia de Cell, permite imprimir texto con saltos de línea automáticos. También se puede hacer un salto de línea manual (con el carácter \n). Crea tantas celdas como sean necesarias son creadas, uno debajo de otra.
    El texto puede ser alineado, centrado o justificado. El bloque de celda puede ser enmarcado y el fondo impreso.
    Los siguientes parámetros son:
    • Anchura de las celdas. Si es 0, las celdas se extiende hasta el margen derecho.
    • Altura de las celdas. Por defecto es 0
    • La cadena o el string a imprimir.
    • Opcional: Borde en las celdas:
      • 1 Si
      • 0 No (Por defecto)
      • O una cadena que contiene algunos o todos los siguientes caracteres (en cualquier orden):
        • L: Izquierda
        • T: Parte superior
        • R: Derecha
        • B: Parte inferior
    • Opcional: Permite centrar o alinear el texto. Los valores posibles son:
      L: Alinear texto a la izquierda
      C: Alinear texto al centro
      R: Alinear texto a la derecha
      J: Justificado (valor por defecto)
    • Opcional: Indica si el fondo de la celda debe estar pintado (true) o transparente (false).
// COLUMNAS
$pdf->SetFont('Helvetica', 'B', 7);
$pdf->Cell(30, 10, 'Articulo', 0);
$pdf->Cell(5, 10, 'Ud',0,0,'R');
$pdf->Cell(10, 10, 'Precio',0,0,'R');
$pdf->Cell(15, 10, 'Total',0,0,'R');
$pdf->Ln(8);
$pdf->Cell(60,0,'','T');
$pdf->Ln(0);
 
// PRODUCTOS
$pdf->SetFont('Helvetica', '', 7);
$pdf->MultiCell(30,4,'Manzana golden 1Kg',0,'L'); 
$pdf->Cell(35, -5, '2',0,0,'R');
$pdf->Cell(10, -5, number_format(round(3,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Cell(15, -5, number_format(round(2*3,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);
$pdf->MultiCell(30,4,'Malla naranjas 3Kg',0,'L'); 
$pdf->Cell(35, -5, '1',0,0,'R');
$pdf->Cell(10, -5, number_format(round(1.25,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Cell(15, -5, number_format(round(1.25,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);
$pdf->MultiCell(30,4,'Uvas',0,'L'); 
$pdf->Cell(35, -5, '5',0,0,'R');
$pdf->Cell(10, -5, number_format(round(1,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Cell(15, -5, number_format(round(1*5,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);

Ahora el pie de pagina del ticket en PDF

Ya casi estamos acabando nuestro ticket en PDF. En el pie de página vamos a poner la suma de los precios de los artículos,descuentos,total sin IVA,incremento del IVA, el total del IVA y para finalizar, poner el periodo de devoluciones o simplemente poner el típico mensaje como “Gracias por su compra”.

Tip: Si quieres ver como se formatea un número para los precios, totales del IVA, lee el siguiente POST.

Por último: Debemos indicar cómo queremos que interactúe nuestro ticket en PDF. Para ello vamos a utilizar el parámetro:

  • Output. Cierra y envía el documento a un destino. Los parámetros a enviar son:
    • Destino del documento:
      • I (Por defecto) : Muestra el documento en el navegador web.
      • D: Muestra el documento en el navegador web y fuerza al usuario a descargar el PDF.
      • F: Guarda el documento en el servidor web.
      • S: Devuelve el documento como una cadena.
    • Nombre del documento
    • Codificación del nombre del documento. Indica si el nombre del documento es codificado en ISO-8859-1 (false) ó UTF-8 (true). Solo usa destinos I y D. El valor por defecto es false.
//SUMATORIO DE LOS PRODUCTOS Y EL IVA 
$pdf->Ln(6); $pdf->Cell(60,0,'','T'); $pdf->Ln(2); 
$pdf->Cell(25, 10, 'TOTAL SIN I.V.A.', 0); $pdf->Cell(20, 10, '', 0); 
$pdf->Cell(15, 10, number_format(round((round(12.25,2)/1.21),2), 2, ',', ' ').EURO,0,0,'R'); 
$pdf->Ln(3); 
$pdf->Cell(25, 10, 'I.V.A. 21%', 0); $pdf->Cell(20, 10, '', 0); 
$pdf->Cell(15, 10, number_format(round((round(12.25,2)),2)-round((round(2*3,2)/1.21),2), 2, ',', ' ').EURO,0,0,'R'); 
$pdf->Ln(3); 
$pdf->Cell(25, 10, 'TOTAL', 0); $pdf->Cell(20, 10, '', 0); 
$pdf->Cell(15, 10, number_format(round(12.25,2), 2, ',', ' ').EURO,0,0,'R'); 

// PIE DE PAGINA $pdf->Ln(10); 
$pdf->Cell(60,0,'EL PERIODO DE DEVOLUCIONES',0,1,'C'); 
$pdf->Ln(3); $pdf->Cell(60,0,'CADUCA EL DIA 01/11/2019',0,1,'C'); 
$pdf->Output('ticket.pdf','i');

Ahora todo junto…

AddPage();
 
// CABECERA
$pdf->SetFont('Helvetica','',12);
$pdf->Cell(60,4,'Lacodigoteca.com',0,1,'C');
$pdf->SetFont('Helvetica','',8);
$pdf->Cell(60,4,'C.I.F.: 01234567A',0,1,'C');
$pdf->Cell(60,4,'C/ Arturo Soria, 1',0,1,'C');
$pdf->Cell(60,4,'C.P.: 28028 Madrid (Madrid)',0,1,'C');
$pdf->Cell(60,4,'999 888 777',0,1,'C');
$pdf->Cell(60,4,'[email protected]',0,1,'C');
 
// DATOS FACTURA        
$pdf->Ln(5);
$pdf->Cell(60,4,'Factura Simpl.: F2019-000001',0,1,'');
$pdf->Cell(60,4,'Fecha: 28/10/2019',0,1,'');
$pdf->Cell(60,4,'Metodo de pago: Tarjeta',0,1,'');
 
// COLUMNAS
$pdf->SetFont('Helvetica', 'B', 7);
$pdf->Cell(30, 10, 'Articulo', 0);
$pdf->Cell(5, 10, 'Ud',0,0,'R');
$pdf->Cell(10, 10, 'Precio',0,0,'R');
$pdf->Cell(15, 10, 'Total',0,0,'R');
$pdf->Ln(8);
$pdf->Cell(60,0,'','T');
$pdf->Ln(0);
 
// PRODUCTOS
$pdf->SetFont('Helvetica', '', 7);
$pdf->MultiCell(30,4,'Manzana golden 1Kg',0,'L'); 
$pdf->Cell(35, -5, '2',0,0,'R');
$pdf->Cell(10, -5, number_format(round(3,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Cell(15, -5, number_format(round(2*3,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);
$pdf->MultiCell(30,4,'Malla naranjas 3Kg',0,'L'); 
$pdf->Cell(35, -5, '1',0,0,'R');
$pdf->Cell(10, -5, number_format(round(1.25,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Cell(15, -5, number_format(round(1.25,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);
$pdf->MultiCell(30,4,'Uvas',0,'L'); 
$pdf->Cell(35, -5, '5',0,0,'R');
$pdf->Cell(10, -5, number_format(round(1,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Cell(15, -5, number_format(round(1*5,2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);
 
// SUMATORIO DE LOS PRODUCTOS Y EL IVA
$pdf->Ln(6);
$pdf->Cell(60,0,'','T');
$pdf->Ln(2);    
$pdf->Cell(25, 10, 'TOTAL SIN I.V.A.', 0);    
$pdf->Cell(20, 10, '', 0);
$pdf->Cell(15, 10, number_format(round((round(12.25,2)/1.21),2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);    
$pdf->Cell(25, 10, 'I.V.A. 21%', 0);    
$pdf->Cell(20, 10, '', 0);
$pdf->Cell(15, 10, number_format(round((round(12.25,2)),2)-round((round(2*3,2)/1.21),2), 2, ',', ' ').EURO,0,0,'R');
$pdf->Ln(3);    
$pdf->Cell(25, 10, 'TOTAL', 0);    
$pdf->Cell(20, 10, '', 0);
$pdf->Cell(15, 10, number_format(round(12.25,2), 2, ',', ' ').EURO,0,0,'R');
 
// PIE DE PAGINA
$pdf->Ln(10);
$pdf->Cell(60,0,'EL PERIODO DE DEVOLUCIONES',0,1,'C');
$pdf->Ln(3);
$pdf->Cell(60,0,'CADUCA EL DIA  01/11/2019',0,1,'C');
 
$pdf->Output('ticket.pdf','i');
?>

Si añadimos 2 salidas del Output del ticket en pdf, en el segundo parámetro ponemos ‘f’ e ‘i’ en dos líneas, vamos a poder visualizar el ticket y lo almacena en el servidor. Esto lo colocaremos al final del código del generador de tickets en PDF, vamos a añadir debajo lo siguiente:

$pdf->Output('ticket.pdf','f');
$pdf->Output('ticket.pdf','i');

¡Ya tienes tu ticket con PHP!

ticket en PDF
ticket PDF con PHP

Si necesitas más parámetros puedes verlos aquí o si quieres probar con otras librerías, aquí te mostramos las 5 librerías para generar PDF en PHP.

Nuevo: Enviar ticket por email

Para enviar el ticket por email, vamos a utilizar el framework PHPMailer (en el siguiente enlace dejo cómo descargarlo, instalarlo y configurarlo). Lo colocamos junto a la invocación de la librería FPDF, lo primero que vamos a realizar es invocar la librería de PHPMailer, que muestre el ticket por pantalla y que lo almacene en el servidor.

require('phpmailer/PHPMailer.php');
require('phpmailer/SMTP.php');
require('phpmailer/Exception.php');
require('phpmailer/OAuth.php');

Ahora, vamos a integrar PHPMailer en nuestro ticket.Para ello copiamos este código y lo dejamos al final de nuestro fichero con la generación del ticket en PDF:

// Inicializamos PHPMailer
$mail = new PHPMailer\PHPMailer\PHPMailer();

try {
//Configuración de PHPMailer
$mail->isSMTP();
$mail->SMTPDebug = 0;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Host = '(HOST SERVIDOR DE CORREO)';
$mail->Username   = '(USUARIO DEL HOST DE CORREO)';  
$mail->Password = '(CONTRASEÑA)';
$mail->Port = 587;

//Configurar remitentes y destinatarios
$mail->setFrom('[email protected]', 'Lacodigoteca.com');
$mail->addAddress('[email protected]', 'Lacodigoteca.com');
$mail->addReplyTo('[email protected]', 'Alfredo Lacodigoteca');
$mail->addBCC('[email protected]');

//Añadimos documentos adjuntos al correo
$mail->addAttachment('ticket.pdf');

//Cuerpo del correo electrónico
$mail->isHTML(true);  
$mail->CharSet = "utf-8";
// Set email format to HTML
$mail->Subject = '[Lacodigoteca] - Factura simpl. XXXXX';
$mail->Body    = 'Hola <b>Alfredo</b><br>Te enviamos el ticket de compra.<br> Un saludo.';
$mail->AltBody = 'Hola Alfredo. Te enviamos el ticket de compra.Un saludo.'; // Si no tienen habilitado el correo HTML

//Enviamos el correo
$mail->send();

//Eliminamos el ticket que hemos almacenado temporalmente en el servidor.
unlink($doc);

}catch (Exception $e) {
    echo "No se ha podido enviar el mensaje. Mailer Error: {$mail->ErrorInfo}";
}

Si necesitas saber más información con profundidad, te invito a que pases al siguiente POST:

Cómo enviar correos con PHPMailer

¿Te ha gustado el articulo?

Te invitamos a que visites la sección de PHP ya que existen más utilidades para tu proyecto.

Palabras relacionadas:

fpdf ticket – ticket de venta – imprimir ticket – tickets imprimibles – pdf php

Facebook
Twitter
LinkedIn

23 comentarios en “Cómo crear ticket en PDF con PHP en 3 pasos pdf ticket”

  1. Con un afectuoso saludo, queria agradecer por este gran aporte en el uso de Fpdf para imprimir tickets, sin embargo queira saber que luego de hacer varios intentos por hacer los tickes para ser impresos en impresoras matriciales o termicas, los caracteres o letras me salen montados, me podria ayudar que me recomienda para esto!!!

    1. Hola Oliver,

      Puede ser que el texto que quieres imprimir, sea más grande que las dimensiones de la Cell. Yo haría dos comprobaciones:
      1- Prueba con poner un texto más pequeño y comprobar que no se te monta los caracteres.
      2- Si es así del paso 1, tienes que utilizar Multicell.

      Un saludo.

  2. Muchas gracias mi estimado Alfredo, voy a probar configurando nuevamente las dimensiones del cel o por ultimo utilizar los multiCell, muy amable gracias por su ayuda, cualquier cosa le indico por este medio…saludos

  3. Mi estimado Alfredo como esta!!! le comento que probe lo que ud me sugirio en cuanto a modificar las dimensiones de los campos Cell, pero no consigo imprimir bien, me sigue saliendo los caracteres montados apesar de que he aumentado el espacio de los campos cell, ademas apesar de que tengo configurado el formato de impresion para A5 en ves de salir la impresión en este formato, me sale reducido el ancho de la impresion, adjunto el codigo haber si me puede ayudar a corregirlo, este mismo problema tengo en otros formatos, A6, A4, y tambien en formatos de 74mm X 210 mm y asi otros le comento que llevo tiempo haciendo este tipo de reportes pero no salen bien, la impresora que al momento estoy trabajando es una Epson LX-350 matricial.

    Codigo :

    Código eliminado

    Por su atencion de antemano le gradezco mi estimado Alfredo…

    Saludos

    1. Buenos días Oliver,

      Para comprobar que es correcto. Yo recogería el código de ejemplo y lo imprimiría. Yo no soy partidario de concatenar datos (que por ahí puede venir tu problema) ya que puede alterar las medidas de las celdas.

      Un saludo.

  4. Hola estimado Alfredo, era para comentarle sobre las 2 salidas del Output del pdf, donde las pongo, ahí dice al final, pero al final a donde.

    1. Hola Sebastián!
      Antes de nada, muchas gracias por visitar mi blog.
      En efecto, no estaba bien ubicado el código, y la explicación no ha sido muy detallada. Ya he actualizado el artículo y espero que te sirva de ayuda 😉
      Un saludo.

  5. Muy bueno su aporte pero tengo un problema , porque no puedo hacer un ticket de menos de 35mm de alto, quiero imprimir un ticket de código de barras, lo hace todo bien pero no puedo hacer que el alto sea menor que esa medida.

    1. Buenas tardes William,

      Gracias por visitar mi blog. Respecto a la documentación de FPDF, no existen altura mínima para generar el document. ¿Has probado con poner el siguiente código?
      Tamaño PDF 50mm (anchura) x 35 mm (altura)
      $pdf = new FPDF('P','mm',array(50,35));

      Asegúrate de las medidas del código de barras, ya que si el tamaño del EAN es más grande que el del documento pdf, puede ocasionarte problemas.

      Un saludo

  6. gotardo sulca gutierrez

    maestro gracias por compartir tu sabiduría, como haría con datos reales desde mysql extraer datos del mismo, he estado probando con WHILE pero me extrae todos los datos mas no de uno solo…gracias maestro por su respuesta

    1. Hola! La funcionalidad del WHILE hace que recorra varios registros según la consulta que tiene programada. Si sólo quiere mostrar un sólo registro, tiene dos opciones:
      1. Eliminar el WHILE y sólo mostrar una consulta.
      2. Asegurar que la consulta de base de datos muestre sólo un registro.

      Un saludo.

    1. Hola Josue,
      Me alegro que le hubiera servido de ayuda, para añadir imágenes tiene que incluir lo siguiente:
      $this->Image('logo.png',10,6,30);
      Los otros parámetros de la URL son coordenadas para ubicar la imagen.
      Un saludo 👋

  7. Hola, Alfredo.
    Excelente articulo no conocía esta herramienta.
    Tengo una duda ya hice el ticket pero como podría hacer el tamaño dinámico?
    Ejemplo, para poder imprimir en diferentes impresoras de diferentes anchos y para un largo dependiendo de los artículos?
    Muchas Gracias.

    1. Hola Noe. Lo que se me ocurre es que mandes por parámetro el tipo de impresión que vas a hacer y dentro del código del ticket tengas un Switch, si tipo de impresión es A que tenga unas medidas, si es B otras… etc. Ya nos contarás qué tal te ha ido.
      Un saludo y gracias por visitar mi blog 😊

  8. Hola, ¿qué tal?, muchas gracias me sirvió bastante.
    $pdf = new FPDF(‘P’,’mm’,array(80,150));

    Hay alguna forma que el largo sea automático según el contenido y no tenga que poner el lago solo el ancho.

    Saludos

    1. Hola Miguel,

      Muchas gracias por visitar mi blog y me llena de satisfacción que te ha servido mi ejemplo. Lo que se me puede ocurrir es que recojas el tamaño del ancho vía JavaScript. Por ejemplo:
      var ancho = document.getElementById("ancho");
      console.log(ancho.height); // esto lo deberás de llevarlo a PHP para ponerlo en la función.

      Un saludo.

  9. Henry Pandales Pandales

    $pdf=new FPDF(‘P’,’mm’,array(80,200));
    $pdf=new FPDF(‘P’,’mm’,array(80,dinamico));
    $pdf=new FPDF(‘P’,’mm’,array(80,automatico));

    Deseo Imprimir un Tickect POS pdf pero si especifico el alto de la pagina si son mas de 50 articulos me sale salto de pagina
    qué debo hacer para que se muestren los articulos o detalles en una misma pagina??

  10. hola amigo buenas, quisiera saber si me puedes ayudar en la creacion de un ticket, no entiendo como se ocupa la aplicación y necesito urgente un ticket, saludos y muchas gracias.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio