### Create Shipping Guide in PHP Source: https://context7.com/thegreenter/greenter/llms.txt This PHP snippet creates an electronic shipping guide using Greenter's Despatch model, configuring shipment details like transport mode, weights, directions, and recipient information. It builds the despatch document and submits it via the SEE client. Dependencies include Greenter model classes and a predefined $company object. Inputs are shipment parameters and client details; outputs are success or error messages, with the despatch object as intermediate data. ```php setCodTraslado('01') // 01 = Sale (Catálogo 20) ->setModTraslado('02') // 02 = Private transport (Catálogo 18) ->setFecTraslado(new DateTime('+1 day')) ->setPesoTotal(150.50) // Total weight ->setUndPesoTotal('KGM') // KGM = Kilograms ->setPartida((new Direction()) ->setUbigeo('150131') ->setDireccion('AV. REPUBLICA DE PANAMA 3545, SAN ISIDRO - LIMA')) ->setLlegada((new Direction()) ->setUbigeo('150101') ->setDireccion('AV. LARCO 1301, MIRAFLORES - LIMA')) ->setTransportist((new Transportist()) ->setTipoDoc('6') ->setNumDoc('20987654321') ->setRznSocial('TRANSPORTES S.A.C.') ->setNroMtc('12345')) // MTC registration number ->setVehicle((new Vehicle()) ->setPlaca('ABC-123')) // License plate ->setDriver((new Driver()) ->setTipoDoc('1') ->setNumDoc('43567890') ->setNombres('JUAN PEREZ GARCIA') ->setApellidos('PEREZ GARCIA')); // Create despatch details $detail = (new DespatchDetail()) ->setCantidad(10) ->setUnidad('NIU') ->setCodigo('PROD001') ->setDescripcion('Laptop Dell Inspiron 15'); // Build despatch document $despatch = (new Despatch()) ->setVersion('2022') // GRE version ->setTipoDoc('09') // 09 = Guía de Remisión ->setSerie('T001') // Must start with T ->setCorrelativo('00045') ->setFechaEmision(new DateTime()) ->setCompany($company) ->setDestinatario((new Client()) ->setTipoDoc('6') ->setNumDoc('20456789012') ->setRznSocial('CLIENTE DESTINO SAC')) ->setEnvio($shipment) ->setDetails([$detail]); $result = $see->send($despatch); if ($result->isSuccess()) { echo "Shipping guide accepted!\n"; } else { echo "Error: " . $result->getError()->getMessage() . "\n"; } ``` -------------------------------- ### Create Invoice with Detraction, Perception, and Discount Source: https://context7.com/thegreenter/greenter/llms.txt Demonstrates creating a detailed invoice with detraction, perception taxes, and global discounts using Greenter. It includes installment payment configuration and legend handling. Requires Greenter models and DateTime instances. ```php 700 soles) $invoice = (new Invoice()) ->setUblVersion('2.1') ->setTipoDoc('01') ->setSerie('F001') ->setCorrelativo('00200') ->setFechaEmision(new DateTime()) ->setFecVencimiento(new DateTime('+30 days')) ->setTipoOperacion('0101') ->setTipoMoneda('PEN') ->setCompany($company) ->setClient($client) ->setDetails([ (new SaleDetail()) ->setCodProducto('SRV001') ->setUnidad('ZZ') ->setCantidad(1) ->setDescripcion('Servicio de Consultoría Especializada') ->setMtoBaseIgv(10000.00) ->setPorcentajeIgv(18.00) ->setIgv(1800.00) ->setTipAfeIgv('10') ->setMtoValorVenta(10000.00) ->setMtoValorUnitario(10000.00) ->setMtoPrecioUnitario(11800.00) ]); // Add detraction (SPOT - Sistema de Pago de Obligaciones Tributarias) $invoice->setDetraccion((new Detraction()) ->setCodBienDetraccion('027') // Service code (Catálogo 54) ->setCodMedioPago('001') // Payment method: Bank deposit ->setCtaBanco('00123456789') // Bank account for detraction ->setPercent(12.00) // Detraction percentage ->setMount(1416.00)); // Detraction amount (11800 * 0.12) // Add perception tax (if applicable) $invoice->setPerception((new SalePerception()) ->setCodReg('01') // Perception regime ->setPorcentaje(2.00) // 2% perception ->setMto(236.00) // Perception amount ->setMtoBase(11800.00) // Base for perception ->setMtoTotal(12036.00)); // Total including perception // Add global discount $invoice->setDescuentos([ (new Charge()) ->setCodTipo('02') // 02 = Discount ->setMontoBase(10000.00) ->setFactor(0.05) // 5% discount ->setMonto(500.00) // Discount amount ]); // Configure installment payment (credit) $invoice->setFormaPago(new FormaPagoCredito()) ->setCuotas([ (new Cuota()) ->setMonto(3933.33) ->setFechaPago(new DateTime('+30 days')), (new Cuota()) ->setMonto(3933.33) ->setFechaPago(new DateTime('+60 days')), (new Cuota()) ->setMonto(3933.34) ->setFechaPago(new DateTime('+90 days')) ]); // Set totals $invoice ->setMtoOperGravadas(9500.00) // After discount ->setMtoDescuentos(500.00) ->setMtoIGV(1710.00) ->setTotalImpuestos(1710.00) ->setValorVenta(9500.00) ->setSubTotal(11210.00) ->setMtoImpVenta(11210.00) ->setLegends([ (new Legend()) ->setCode('1000') ->setValue('ONCE MIL DOSCIENTOS DIEZ CON 00/100 SOLES'), (new Legend()) ->setCode('2006') // Detraction legend ->setValue('Operación sujeta a detracción') ]); $result = $see->send($invoice); ``` -------------------------------- ### Get Signed XML Without Sending Source: https://context7.com/thegreenter/greenter/llms.txt Generates and signs an XML document from an invoice without submitting it to SUNAT. Useful for previewing or storing the XML before official submission. Requires a SEE instance and invoice object. ```php getXmlSigned($invoice); // Validate or store locally file_put_contents('invoice-preview.xml', $xmlSigned); echo "XML generated and signed successfully!\n"; // Later, send the pre-generated XML $result = $see->sendXmlFile($xmlSigned); ``` -------------------------------- ### Utilize SUNAT Tax Codes and Catalogs in PHP Source: https://context7.com/thegreenter/greenter/llms.txt This example illustrates the usage of various SUNAT catalog codes for document classification within the Greenter library. It defines common codes for document types, client document types, tax affectation, units of measure, operation types, and reason codes for credit and debit notes. ```php setTipAfeIgv('10') // Taxed operation ->setUnidad('NIU') // Unit measure ->setCodProducto('PROD001') ->setDescripcion('Product description') ->setCantidad(5); $client = (new Client()) ->setTipoDoc('6') // RUC for companies ->setNumDoc('20123456789'); $invoice = (new Invoice()) ->setTipoDoc('01') // Invoice ->setTipoOperacion('0101'); // Internal sale ``` -------------------------------- ### Send Despatch via REST API in PHP Source: https://context7.com/thegreenter/greenter/llms.txt This PHP snippet demonstrates using Greenter's REST API client to send a despatch document, including OAuth and SOL credentials setup, certificate loading, and async status polling. It builds on a predefined $despatch object. Dependencies include Greenter Api class, file_get_contents for certificate, and sleep for polling. Inputs are API credentials, despatch object, and ticket for status; outputs are success/error messages, status responses, and the last XML. ```php 'https://api-seguridad.sunat.gob.pe/v1', 'cpe' => 'https://api-cpe.sunat.gob.pe/v1' ]); // Configure OAuth credentials $api->setApiCredentials('client-id-from-sunat', 'client-secret-from-sunat'); // Configure SOL credentials $api->setClaveSOL('20123456789', 'MYUSER', 'mypassword'); // Set digital certificate $api->setCertificate(file_get_contents(__DIR__ . '/certificate.pem')); // Set builder options $api->setBuilderOptions(['cache' => false, 'strict_variables' => true]); // Send despatch via REST $result = $api->send($despatch); if ($result->isSuccess()) { echo "Document sent successfully!\n"; // For async documents, get ticket and poll status $ticket = $result->getTicket(); if ($ticket) { sleep(2); // Wait before checking status $statusResult = $api->getStatus($ticket); if ($statusResult->isSuccess()) { echo "Status: " . $statusResult->getCdrResponse()->getDescription() . "\n"; } } } else { echo "Error: " . $result->getError()->getMessage() . "\n"; } // Retrieve the last signed XML $lastXml = $api->getLastXml(); file_put_contents('last-document.xml', $lastXml); ``` -------------------------------- ### Create and Send Daily Summary in PHP Source: https://context7.com/thegreenter/greenter/llms.txt This PHP snippet creates a daily summary document for receipts and modifications using Greenter models, sends it asynchronously to SUNAT, and polls for the processing status. It requires the Greenter library and assumes a $see service and $company object are set up. Limitations include async processing delays and potential SUNAT errors. ```php setTipoDoc('03') // 03 = Receipt ->setSerieNro('B001-456') // Document being summarized ->setEstado('1') // 1 = Addition, 2 = Modification, 3 = Cancellation ->setClienteTipo('1') ->setClienteNro('43567890') ->setTotal(118.00) ->setMtoOperGravadas(100.00) ->setMtoIGV(18.00); $detail2 = (new SummaryDetail()) ->setTipoDoc('03') ->setSerieNro('B001-457') ->setEstado('1') ->setClienteTipo('1') ->setClienteNro('43567891') ->setTotal(236.00) ->setMtoOperGravadas(200.00) ->setMtoIGV(36.00); // Build summary document $summary = (new Summary()) ->setFecGeneracion(new DateTime()) // Generation date ->setFecResumen(new DateTime('-1 day')) // Date of documents being summarized ->setCorrelativo('001') // Daily sequential number ->setCompany($company) ->setMoneda('PEN') ->setDetails([$detail1, $detail2]); // Send summary (returns ticket for async processing) $result = $see->send($summary); if ($result->isSuccess()) { $ticket = $result->getTicket(); echo "Summary sent! Ticket: $ticket\n"; // Poll for status (SUNAT processes async) $maxAttempts = 10; $attempt = 0; do { sleep(3); // Wait 3 seconds between checks $statusResult = $see->getStatus($ticket); $attempt++; if ($statusResult->getCode() === '0') { echo "Summary accepted by SUNAT!\n"; $cdr = $statusResult->getCdrResponse(); echo "Description: " . $cdr->getDescription() . "\n"; // Save CDR file_put_contents('summary-cdr.zip', $statusResult->getCdrZip()); break; } elseif ($statusResult->getCode() === '98') { echo "Processing... (attempt $attempt/$maxAttempts)\n"; } else { echo "Error: " . $statusResult->getError()->getMessage() . "\n"; break; } } while ($attempt < $maxAttempts); } else { echo "Error sending summary: " . $result->getError()->getMessage() . "\n"; } ``` -------------------------------- ### Send Pre-Generated XML Source: https://context7.com/thegreenter/greenter/llms.txt Demonstrates how to send a pre-generated and signed XML file to SUNAT. Shows both automatic and explicit methods for XML submission. Requires valid XML content and SEE instance. ```php sendXmlFile($xmlContent); // Or use sendXml with explicit parameters $result = $see->sendXml( \Greenter\Model\Sale\Invoice::class, // Document class '20123456789-01-F001-00123', // Filename $xmlContent // XML content ); if ($result->isSuccess()) { echo "Pre-generated XML accepted!\n"; } ``` -------------------------------- ### Generate and Submit SUNAT Invoice using PHP Source: https://context7.com/thegreenter/greenter/llms.txt This code demonstrates creating an electronic invoice with details like company, client, line items with IGV tax calculations, and legends, then submitting it to SUNAT via SOAP for validation. It requires the Greenter library (autoloaded), a digital certificate, and SUNAT credentials. Inputs include invoice data and outputs are success/error responses with signed XML and CDR ZIP files saved locally; limitations include production endpoint usage requiring valid credentials and certificate. ```php setRuc('20123456789') ->setRazonSocial('MI EMPRESA SAC') ->setNombreComercial('MI EMPRESA') ->setAddress((new Address()) ->setUbigeo('150101') ->setDepartamento('LIMA') ->setProvincia('LIMA') ->setDistrito('LIMA') ->setDireccion('AV. LOS OLIVOS 123')); // Configure the client (buyer) $client = (new Client()) ->setTipoDoc('6') // 6 = RUC, 1 = DNI ->setNumDoc('20987654321') ->setRznSocial('EMPRESA CLIENTE SAC'); // Create invoice line items with tax calculations $detail1 = (new SaleDetail()) ->setCodProducto('PROD001') ->setUnidad('NIU') // NIU = Unit (Catálogo 03) ->setCantidad(10) ->setDescripcion('Laptop Dell Inspiron 15') ->setMtoBaseIgv(5000.00) // Base amount before IGV ->setPorcentajeIgv(18.00) // 18% IGV tax rate ->setIgv(900.00) // IGV amount (5000 * 0.18) ->setTipAfeIgv('10') // 10 = Taxed operation (Catálogo 07) ->setTotalImpuestos(900.00) ->setMtoValorVenta(5000.00) // Subtotal for this line ->setMtoValorUnitario(500.00) // Unit price without tax ->setMtoPrecioUnitario(590.00); // Unit price with tax (500 * 1.18) $detail2 = (new SaleDetail()) ->setCodProducto('PROD002') ->setUnidad('NIU') ->setCantidad(5) ->setDescripcion('Mouse Inalámbrico Logitech') ->setMtoBaseIgv(250.00) ->setPorcentajeIgv(18.00) ->setIgv(45.00) ->setTipAfeIgv('10') ->setTotalImpuestos(45.00) ->setMtoValorVenta(250.00) ->setMtoValorUnitario(50.00) ->setMtoPrecioUnitario(59.00); // Add mandatory legend (amount in words) $legend = (new Legend()) ->setCode('1000') ->setValue('CINCO MIL DOSCIENTOS CUARENTA Y CINCO CON 00/100 SOLES'); // Build the invoice document $invoice = (new Invoice()) ->setUblVersion('2.1') ->setTipoDoc('01') // 01 = Invoice (Catálogo 01) ->setSerie('F001') // Series must start with F for invoices ->setCorrelativo('00123') ->setFechaEmision(new DateTime()) ->setFecVencimiento(new DateTime('+30 days')) ->setTipoOperacion('0101') // 0101 = Internal sale (Catálogo 51) ->setTipoMoneda('PEN') // PEN = Peruvian Soles ->setCompany($company) ->setClient($client) ->setMtoOperGravadas(5250.00) // Total taxable amount ->setMtoOperExoneradas(0.00) // Tax-exempt amount ->setMtoOperInafectas(0.00) // Non-taxable amount ->setMtoIGV(945.00) // Total IGV (5250 * 0.18) ->setTotalImpuestos(945.00) ->setValorVenta(5250.00) // Sale value before taxes ->setSubTotal(6195.00) // Total with taxes ->setMtoImpVenta(6195.00) // Final invoice amount ->setDetails([$detail1, $detail2]) ->setLegends([$legend]); // Initialize SUNAT service client $see = new See(); $see->setService(SunatEndpoints::FE_PRODUCCION); // Use FE_BETA for testing $see->setCertificate(file_get_contents(__DIR__ . '/certificate.pem')); $see->setCredentials('20123456789MYUSER', 'mypassword'); // RUC + username and password $see->setBuilderOptions(['cache' => false, 'strict_variables' => true]); // Send invoice to SUNAT $result = $see->send($invoice); if ($result->isSuccess()) { $cdr = $result->getCdrResponse(); echo "Invoice accepted by SUNAT!\n"; echo "Code: " . $cdr->getCode() . "\n"; // \"0\" = accepted echo "Description: " . $cdr->getDescription() . "\n"; echo "Notes: " . count($cdr->getNotes()) . "\n"; // Observations // Save signed XML and CDR for records $xmlSigned = $see->getFactory()->getLastXml(); file_put_contents('20123456789-01-F001-00123.xml', $xmlSigned); file_put_contents('R-20123456789-01-F001-00123.zip', $result->getCdrZip()); } else { $error = $result->getError(); echo "Error: [{$error->getCode()}] {$error->getMessage()}\n"; } ``` -------------------------------- ### Configure SUNAT Service Endpoints in PHP Source: https://context7.com/thegreenter/greenter/llms.txt This code snippet shows how to configure different SUNAT service endpoints for production, beta, and testing environments using the Greenter library. It also covers setting credentials and certificates, as well as configuring cache paths and builder options. ```php setService(SunatEndpoints::FE_PRODUCCION); // Beta/Testing environment $see->setService(SunatEndpoints::FE_BETA); // Custom endpoint $see->setService('https://custom-endpoint.sunat.gob.pe/ol-ti-itcpfegem/billService'); // Set credentials (RUC + secondary user) $see->setClaveSOL('20123456789', 'MYUSER', 'mypassword'); // Or combined credentials $see->setCredentials('20123456789MYUSER', 'mypassword'); // Configure certificate $see->setCertificate(file_get_contents('/path/to/certificate.pem')); // Or from environment variable $see->setCertificate(getenv('SUNAT_CERTIFICATE')); // Set cache directory for Twig templates $see->setCachePath('/tmp/greenter_cache'); // Configure builder options $see->setBuilderOptions([ 'cache' => '/tmp/greenter_cache', // Cache directory 'strict_variables' => true, // Strict mode 'debug' => false, // Debug mode 'autoescape' => false // Disable HTML escaping ]); ``` -------------------------------- ### Handle SUNAT Responses and Validate Errors in PHP Source: https://context7.com/thegreenter/greenter/llms.txt This snippet demonstrates comprehensive error handling for SUNAT responses. It checks for success, processes CDR responses, validates response codes, and handles specific SUNAT error codes. It also shows how to retrieve a ticket for asynchronous document processing. ```php send($invoice); if ($result->isSuccess()) { $cdr = $result->getCdrResponse(); // Check response code $code = $cdr->getCode(); if ($code === '0') { echo "Document accepted without observations\n"; } elseif ($code >= 4000) { echo "Document accepted with observations:\n"; foreach ($cdr->getNotes() as $note) { echo "- $note\n"; } } // Response details echo "CDR ID: " . $cdr->getId() . "\n"; echo "Description: " . $cdr->getDescription() . "\n"; echo "Reference: " . $cdr->getReference() . "\n"; // Save CDR $cdrZip = $result->getCdrZip(); $filename = "R-{$invoice->getCompany()->getRuc()}-{$invoice->getTipoDoc()}-{$invoice->getSerie()}-{$invoice->getCorrelativo()}.zip"; file_put_contents($filename, $cdrZip); } else { // Handle error $error = $result->getError(); $errorCode = $error->getCode(); $errorMessage = $error->getMessage(); echo "SUNAT Error [$errorCode]: $errorMessage\n"; // Common error codes switch ($errorCode) { case '0151': echo "Invalid series format\n"; break; case '2801': echo "Client document type invalid for invoice\n"; break; case '3088': echo "Invalid currency code\n"; break; default: echo "Check SUNAT error code documentation\n"; } } // Get ticket for async documents $ticket = $result->getTicket(); if ($ticket) { echo "Async processing - Ticket: $ticket\n"; } ``` -------------------------------- ### Create and Send Cancellation Communication in PHP Source: https://context7.com/thegreenter/greenter/llms.txt This PHP snippet generates a voided document communication for canceling same-day invoices using Greenter models, sends it asynchronously to SUNAT, and checks the processing status. It depends on the Greenter library with pre-configured $see service and $company, and includes support for multiple cancellation reasons. Note that it's designed for same-day cancellations with async polling, which may involve delays or failures. ```php setTipoDoc('01') // Document type to cancel ->setSerie('F001') ->setCorrelativo('123') ->setDesMotivoBaja('ERROR EN EMISION'); // Cancellation reason $detail2 = (new VoidedDetail()) ->setTipoDoc('01') ->setSerie('F001') ->setCorrelativo('124') ->setDesMotivoBaja('OPERACION NO REALIZADA'); // Build voided document $voided = (new Voided()) ->setCorrelativo('001') // Daily sequential number ->setFecGeneracion(new DateTime()) // Generation date ->setFecComunicacion(new DateTime()) // Communication date (today for same-day cancellation) ->setCompany($company) ->setDetails([$detail1, $detail2]); // Send voided communication (async processing) $result = $see->send($voided); if ($result->isSuccess()) { $ticket = $result->getTicket(); echo "Voided communication sent! Ticket: $ticket\n"; // Poll for status sleep(3); $statusResult = $see->getStatus($ticket); if ($statusResult->getCode() === '0') { echo "Cancellation accepted!\n"; } elseif ($statusResult->getCode() === '98') { echo "Still processing... check again later\n"; } } else { echo "Error: " . $result->getError()->getMessage() . "\n"; } ```