From 1673f417aedfcadc31784447413e52a34d0c1b17 Mon Sep 17 00:00:00 2001 From: Lucas Garcia Date: Fri, 28 Aug 2026 22:42:55 +0200 Subject: [PATCH 1/2] feat: verifactuCollationLink reusable method --- class/actions_autoverifactu.class.php | 46 +++++++++------------------ lib/verifactu.lib.php | 38 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/class/actions_autoverifactu.class.php b/class/actions_autoverifactu.class.php index fec4d13..1377bf1 100644 --- a/class/actions_autoverifactu.class.php +++ b/class/actions_autoverifactu.class.php @@ -116,27 +116,19 @@ public function doActions($parameters, &$object, &$action) } elseif ($result < 0) { $this->errors[] = $langs->trans('InconsistentInvoiceData'); } - // url de verificacion en caso de test o production. - $testMode = (bool) getDolGlobalString('AUTOVERIFACTU_TEST_MODE'); - $base_url = $testMode ? VERIFACTU_TEST_COLLATION_BASE_URL : VERIFACTU_COLLATION_BASE_URL; - $endpoint = '/wlpl/TIKE-CONT/ValidarQR'; - //en caso de tener IRPF hay que quitarselo ya que en verifactu no hay que tenerlo en cuenta - // por ello le sumo el irpf al total - $query = http_build_query(array( - 'nif' => $mysoc->idprof1, - 'numserie' => $object->ref, - 'fecha' => date('d-m-Y', $object->date), - 'importe' => number_format($object->total_ttc - $object->total_localtax2, 2, '.', ''), - 'formato' => 'json', - )); + + $collation_url = autoverifactuCollationLink($object, true); + $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $base_url . $endpoint . '?' . $query); + curl_setopt($ch, CURLOPT_URL, $collation_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_FAILONERROR, 1); curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'P12'); + $certPath = DOL_DATA_ROOT . '/' . getDolGlobalString('AUTOVERIFACTU_CERT'); curl_setopt($ch, CURLOPT_SSLCERT, $certPath); + $certPass = getDolGlobalString('AUTOVERIFACTU_PASSWORD'); curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $certPass); @@ -283,7 +275,6 @@ public function beforePDFCreation($parameters, &$object, &$action) */ public function printUnderHeaderPDFline($parameters, &$pdfhandler) { - global $mysoc; $object = $parameters['object']; $modelpdf = $object->model_pdf; if ( @@ -295,25 +286,17 @@ public function printUnderHeaderPDFline($parameters, &$pdfhandler) ) { $pdf = &$parameters['pdf']; - // url de verificacion en caso de test o production. - $testMode = (bool) getDolGlobalString('AUTOVERIFACTU_TEST_MODE'); - $base_url = $testMode ? VERIFACTU_TEST_COLLATION_BASE_URL : VERIFACTU_COLLATION_BASE_URL; - $endpoint = '/wlpl/TIKE-CONT/ValidarQR'; - $query = http_build_query(array( - 'nif' => $mysoc->idprof1, - 'numserie' => $object->ref, - 'fecha' => date('d-m-Y', $object->date), - 'importe' => number_format($object->total_ttc - $object->total_localtax2, 2, '.', ''), - )); - //El código «QR» deberá tener un tamaño entre 30x30 y 40x40 milímetros y seguir las especificaciones de la norma ISO/IEC 18004:2015 - //A este respecto, se deben mantener como mínimo 2 milímetros de espacio vacío (en blanco) alrededor de los cuatro lados del código «QR», recomendándose que sean 6 milímetros. - //La presentación del código «QR» incluirá también un texto que siempre deberá ir precediéndolo: «QR tributario:», y que se situará encima del propio código «QR» + // El código «QR» deberá tener un tamaño entre 30x30 y 40x40 milímetros y seguir las especificaciones de la norma ISO/IEC 18004:2015 + // A este respecto, se deben mantener como mínimo 2 milímetros de espacio vacío (en blanco) alrededor de los cuatro lados del código «QR», recomendándose que sean 6 milímetros. + // La presentación del código «QR» incluirá también un texto que siempre deberá ir precediéndolo: «QR tributario:», y que se situará encima del propio código «QR» // (preferiblemente centrado con respecto a este), de manera que sirva para identificarlo y distinguirlo de otros posibles códigos «QR» que pudiera contener la factura para otros cometidos. $pdf->setTopMargin($pdfhandler->tab_top - 5); $pdf->MultiCell(30, 10, 'QR tributario:', 0, 'C', 0, 1); + $collation_url = autoverifactuCollationLink($object); + $pdf->write2DBarcode( - $base_url . $endpoint . '?' . $query, + $collation_url, 'QRCODE,M', $pdfhandler->marge_gauche, $pdfhandler->tab_top - 1, @@ -323,21 +306,22 @@ public function printUnderHeaderPDFline($parameters, &$pdfhandler) 'border' => false, 'padding' => 2, 'fgcolor' => array(25, 25, 25), - 'bgcolor' => array(255, 255, 255), //margen color blanco con padding 2mm + 'bgcolor' => array(255, 255, 255), // margen color blanco con padding 2mm 'module_width' => 1, 'module_height' => 1, ), 30, ); + $pdf->setTopMargin($pdfhandler->tab_top + 32); $pdf->MultiCell(30, 10, 'VERI*FACTU', 0, 'C', 0, 1); + $this->results = array('extra_under_address_shift' => 40); } return 0; } - /** * Execute action on card page buttons render. If it is a facture page, * it adds a "verifactu" button to the row. diff --git a/lib/verifactu.lib.php b/lib/verifactu.lib.php index 0caada7..1aea303 100644 --- a/lib/verifactu.lib.php +++ b/lib/verifactu.lib.php @@ -1616,3 +1616,41 @@ function autoverifactuIsDeliveryAllowed(&$lasting_time = 0) $lasting_time = max($time - $now, 0); return $lasting_time === 0; } + +/** + * Returns the validation URL corresponding to the giving invoice. + * + * @param Facture $invoice Invoice object. + * @param bool $as_json Switch to json response format. + * + * @return string. + */ +function autoverifactuCollationLink($invoice, $as_json = false) +{ + global $mysoc; + + // En caso de tener IRPF hay que substraerlo del tota, ya que en verifactu no lo tiene en cuenta. + $invoice_total = $invoice->total_ttc; + if ($invoice->total_localtax2) { + $invoice_total -= $invoice->total_localtax2; + } + + $test_mode = (bool) getDolGlobalString('AUTOVERIFACTU_TEST_MODE'); + $base_url = $test_mode ? VERIFACTU_TEST_COLLATION_BASE_URL : VERIFACTU_COLLATION_BASE_URL; + $endpoint = '/wlpl/TIKE-CONT/ValidarQR'; + + $query_args = array( + 'nif' => $mysoc->idprof1, + 'numserie' => $invoice->ref, + 'fecha' => date('d-m-Y', $invoice->date), + 'importe' => number_format($invoice_total, 2, '.', ''), + ); + + if ($as_json) { + $query_args['formato'] = 'json'; + } + + $query = http_build_query($query_args); + + return $base_url . $endpoint . '?' . $query; +} From 368b7d7d5ca754caad0f23a165dc25b39b8f19a7 Mon Sep 17 00:00:00 2001 From: Lucas Garcia Date: Fri, 28 Aug 2026 22:52:51 +0200 Subject: [PATCH 2/2] feat: use collationLink method in the pdf template --- .../facture/doc/pdf_Autoverifactu.modules.php | 18 ++++-------------- lib/verifactu.lib.php | 8 +++++++- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/core/modules/facture/doc/pdf_Autoverifactu.modules.php b/core/modules/facture/doc/pdf_Autoverifactu.modules.php index 2b834c2..696fdc2 100644 --- a/core/modules/facture/doc/pdf_Autoverifactu.modules.php +++ b/core/modules/facture/doc/pdf_Autoverifactu.modules.php @@ -40,6 +40,7 @@ require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/pdf.lib.php'; +require_once AUTOVERIFACTU_DIR . '/lib/verifactu.lib.php'; require_once AUTOVERIFACTU_DIR . '/lib/validation.lib.php'; require_once AUTOVERIFACTU_DIR . '/lib/autoverifactu.lib.php'; @@ -1940,19 +1941,6 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output && $object->type <= Facture::TYPE_DEPOSIT && autoverifactuEnabled() ) { - global $mysoc; - - $testMode = (bool) getDolGlobalString('AUTOVERIFACTU_TEST_MODE'); - $base_url = $testMode ? VERIFACTU_TEST_COLLATION_BASE_URL : VERIFACTU_COLLATION_BASE_URL; - $endpoint = '/wlpl/TIKE-CONT/ValidarQR'; - - $query = http_build_query(array( - 'nif' => $mysoc->idprof1, - 'numserie' => $object->ref, - 'fecha' => date('d-m-Y', $object->date), - 'importe' => number_format($object->total_ttc - $object->total_localtax2, 2, '.', ''), - )); - $qr_width = 36; $qr_x = ($this->page_largeur - $qr_width) / 2; $qr_y = 8; @@ -1962,8 +1950,10 @@ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $output $pdf->MultiCell(30, 10, 'QR tributario:', 0, 'C', 0, 1); + $collation_url = autoverifactuCollationLink($object); + $pdf->write2DBarcode( - $base_url . $endpoint . '?' . $query, + $collation_url, 'QRCODE,M', $qr_x, $qr_y, diff --git a/lib/verifactu.lib.php b/lib/verifactu.lib.php index 1aea303..89074b2 100644 --- a/lib/verifactu.lib.php +++ b/lib/verifactu.lib.php @@ -1629,14 +1629,18 @@ function autoverifactuCollationLink($invoice, $as_json = false) { global $mysoc; - // En caso de tener IRPF hay que substraerlo del tota, ya que en verifactu no lo tiene en cuenta. + // En caso de tener IRPF hay que substraerlo del tota, ya que en verifactu no + // lo tiene en cuenta. $invoice_total = $invoice->total_ttc; if ($invoice->total_localtax2) { $invoice_total -= $invoice->total_localtax2; } + // Seleccionamos entorno en base al modo actual de Auto-Veri*Factu. $test_mode = (bool) getDolGlobalString('AUTOVERIFACTU_TEST_MODE'); $base_url = $test_mode ? VERIFACTU_TEST_COLLATION_BASE_URL : VERIFACTU_COLLATION_BASE_URL; + + // Endpoint de cotejo de registors de facturación. $endpoint = '/wlpl/TIKE-CONT/ValidarQR'; $query_args = array( @@ -1646,6 +1650,8 @@ function autoverifactuCollationLink($invoice, $as_json = false) 'importe' => number_format($invoice_total, 2, '.', ''), ); + // El campo formato solo ha de ser informado cuando se espera una + // respuesta en formato json. if ($as_json) { $query_args['formato'] = 'json'; }