Uso de Greenter¶
Más opciones que tenemos al utilizar Greenter.
Generar XML firmado¶
El ejemplo básico nos mostró como realizar todo el proceso de facturacion con un solo método send()
, pero si necesitamos generar solo el XML firmado, lo cual seria útil para Boletas de Venta ya que estas no se envían a SUNAT individualmente.
<?php
use Greenter\Model\Sale\Invoice;
use Greenter\See;
$boleta = (new Invoice())
->setUblVersion('2.1')
->setTipoOperacion('0101')
->setTipoDoc('03') // Código para Boletas, ver Catalog. 51
->setSerie('B001')
->setCorrelativo('1')
// ...
;
$see = new See();
$see->setCertificate(file_get_contents(__DIR__.'/certificate.pem'));
$xml = $see->getXmlSigned($boleta);
file_put_contents('20000000001-03-B001-1.xml', $xml);
Enviar XML generado¶
Si necesitas enviar un XML previamente generado, debes seguir el siguiente ejemplo.
<?php
require __DIR__.'/vendor/autoload.php';
$see = require __DIR__.'/config.php';
$xmlSigned = file_get_contents('20000000001-01-F001-1.xml');
$result = $see->sendXmlFile($xmlSigned);
// $result se maneja del mismo modo que con el metodo send()
Resumen diario¶
Para comunicar las boletas de ventas emitidas o anuladas, así como las notas de crédito/débito releacionadas, necesita hacerlo mediante un resumen diario. A diferencia del envío de una factura, donde la respuesta es inmediata, en este documento debemos hacer un consulta adicional para conocer su estado utilizando el numero de ticket.
<?php
use Greenter\Model\Company\Company;
use Greenter\Model\Company\Address;
use Greenter\Model\Sale\Document;
use Greenter\Model\Summary\Summary;
use Greenter\Model\Summary\SummaryDetail;
$company = new Company();
$company->setRuc('20000000001')
->setRazonSocial('EMPRESA SAC')
->setNombreComercial('EMPRESA')
->setAddress((new Address())
->setUbigueo('150101')
->setDepartamento('LIMA')
->setProvincia('LIMA')
->setDistrito('LIMA')
->setUrbanizacion('Albar')
->setDireccion('AV ROSALES'));
$detail = new SummaryDetail();
$detail->setTipoDoc('07') // Nota de Credito
->setSerieNro('B001-4')
->setDocReferencia((new Document()) // Documento relacionado (Boleta)
->setTipoDoc('03')
->setNroDoc('B001-1'))
->setEstado('1') // Emisión
->setClienteTipo('1') // Tipo documento identidad: DNI
->setClienteNro('00000000') // Nro de documento identidad
->setTotal(200)
->setMtoOperGravadas(40)
->setMtoOperExoneradas(50)
->setMtoOperInafectas(100)
->setMtoIGV(7.2)
->setMtoISC(2.8);
$detail2 = new SummaryDetail();
$detail2->setTipoDoc('03') // Boleta
->setSerieNro('B001-2')
->setEstado('3') // Anulación
->setClienteTipo('1')
->setClienteNro('00000000')
->setTotal(119)
->setMtoOperGravadas(20)
->setMtoOperInafectas(24.4)
->setMtoOperExoneradas(50)
->setMtoOtrosCargos(21)
->setMtoIGV(3.6);
$resumen = new Summary();
$resumen->setFecGeneracion(new \DateTime('2020-08-01')) // Fecha de emisión de las boletas.
->setFecResumen(new \DateTime('2020-08-02')) // Fecha de envío del resumen diario.
->setCorrelativo('001') // Correlativo, necesario para diferenciar de otros Resumen diario del mismo día.
->setCompany($company)
->setDetails([$detail, $detail2]);
$result = $see->send($resumen);
// Guardar XML
file_put_contents($resumen->getName().'.xml',
$see->getFactory()->getLastXml());
if (!$result->isSuccess()) {
// Si hubo error al conectarse al servicio de SUNAT.
var_dump($result->getError());
exit();
}
$ticket = $result->getTicket();
echo 'Ticket : '.$ticket.PHP_EOL;
$statusResult = $see->getStatus($ticket);
if (!$statusResult->isSuccess()) {
// Si hubo error al conectarse al servicio de SUNAT.
var_dump($statusResult->getError());
return;
}
echo $statusResult->getCdrResponse()->getDescription();
// Guardar CDR
file_put_contents('R-'.$resumen->getName().'.zip', $statusResult->getCdrZip());
Comunicacion de Baja¶
Para comunicar a SUNAT las anulaciones de facturas y sus notas de crédito/débito releacionadas, necesita hacerlo mediante el documento de comunicación de baja.
El envío a los servicios de SUNAT se maneja de la misma forma que el resumen diario.
<?php
use Greenter\Model\Voided\Voided;
use Greenter\Model\Voided\VoidedDetail;
$detail1 = new VoidedDetail();
$detail1->setTipoDoc('01') // Factura
->setSerie('F001')
->setCorrelativo('1')
->setDesMotivoBaja('ERROR EN CÁLCULOS'); // Motivo por el cual se da de baja.
$detail2 = new VoidedDetail();
$detail2->setTipoDoc('07') // Nota de Crédito
->setSerie('FC01')
->setCorrelativo('2')
->setDesMotivoBaja('ERROR DE RUC');
$cDeBaja = new Voided();
$cDeBaja->setCorrelativo('00001') // Correlativo, necesario para diferenciar c. de baja de en un mismo día.
->setFecGeneracion(new \DateTime('2020-08-01')) // Fecha de emisión de los comprobantes a dar de baja
->setFecComunicacion(new \DateTime('2020-08-02')) // Fecha de envio de la C. de baja
->setCompany($company)
->setDetails([$detail1, $detail2]);
$result = $see->send($cDeBaja);
// Guardar XML
file_put_contents($cDeBaja->getName().'.xml',
$see->getFactory()->getLastXml());
if (!$result->isSuccess()) {
// Si hubo error al conectarse al servicio de SUNAT.
var_dump($result->getError());
exit();
}
$ticket = $result->getTicket();
echo 'Ticket : '.$ticket.PHP_EOL;
$statusResult = $see->getStatus($ticket);
if (!$statusResult->isSuccess()) {
// Si hubo error al conectarse al servicio de SUNAT.
var_dump($statusResult->getError());
return;
}
echo $statusResult->getCdrResponse()->getDescription();
// Guardar CDR
file_put_contents('R-'.$cDeBaja->getName().'.zip', $statusResult->getCdrZip());
Anulación de Boletas
Para anular boletas y NCR, NDB relacionadas, se utiliza el resumen diario indicando el campo estado=3