sunatlib

package module
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 13 Imported by: 0

README

SUNATLib - Librería Go para Firmas Digitales XML SUNAT

Una librería en Go para firmar documentos XML y enviarlos a SUNAT (Superintendencia Nacional de Aduanas y de Administración Tributaria) de Perú.

Características

  • ✅ Firma digital XML compatible con SUNAT usando xmlsec1
  • ✅ Soporte para certificados PKCS#12 (.pfx) y PEM
  • ✅ Comunicación SOAP con servicios web de SUNAT
  • ✅ Manejo automático de ZIP y codificación base64
  • ✅ Validación de certificados
  • ✅ Procesamiento de respuestas CDR (Constancia de Recepción)
  • Consulta RUC usando servicio directo SUNAT (Gratuito - Nuevo)
  • Consulta DNI/CE usando servicio EsSalud (Gratuito - Nuevo)
  • Comunicación de Baja (Anulación de Documentos) - Nuevo
  • Consulta de Validez de Documentos Electrónicos - Nuevo
  • Validación de CPE con credenciales master SUNAT - Nuevo

Requisitos

  • Go 1.19 o superior
  • xmlsec1 instalado en el sistema
Instalación de xmlsec1

Ubuntu/Debian:

sudo apt-get install xmlsec1

MacOS:

brew install xmlsec1

RHEL/CentOS:

sudo yum install xmlsec1

Instalación

go mod init your-project
go get github.com/henrybravos/sunatlib

Uso Básico

Opción 1: Proceso completo (todo en uno)
package main

import (
    "fmt"
    "log"
    "os"
    "github.com/henrybravos/sunatlib"
)

func main() {
    // Configure SUNAT client
    client := sunatlib.NewSUNATClient(
        "20123456789",  // Your RUC number
        "MODDATOS",     // SOL username
        "moddatos",     // SOL password
        "https://e-beta.sunat.gob.pe/ol-ti-itcpfegem-beta/billService", // Beta endpoint
    )
    defer client.Cleanup()

    // Configure certificate from PFX
    err := client.SetCertificateFromPFX("certificate.pfx", "your_password", "/tmp/certs")
    if err != nil {
        log.Fatal(err)
    }

    // Read invoice XML
    xmlContent, err := os.ReadFile("invoice.xml")
    if err != nil {
        log.Fatal(err)
    }

    // Sign and send (convenience method)
    response, err := client.SignAndSendInvoice(xmlContent, "01", "F001-00000001")
    if err != nil {
        log.Fatal(err)
    }

    // Check result
    if response.Success {
        fmt.Println("✅ Invoice accepted")
        response.SaveApplicationResponse("cdr.zip")
    } else {
        fmt.Printf("❌ Error: %s\n", response.Message)
    }
}
Opción 2: Control separado (Recomendado)
func main() {
    client := sunatlib.NewSUNATClient("20123456789", "MODDATOS", "moddatos", endpoint)
    defer client.Cleanup()

    err := client.SetCertificateFromPFX("certificate.pfx", "password", "/tmp/certs")
    if err != nil {
        log.Fatal(err)
    }

    xmlContent, err := os.ReadFile("invoice.xml")
    if err != nil {
        log.Fatal(err)
    }

    // Step 1: Sign XML (you get the signed XML back)
    signedXML, err := client.SignXML(xmlContent)
    if err != nil {
        log.Fatal(err)
    }

    // Optional: Save signed XML for inspection or later use
    os.WriteFile("invoice_signed.xml", signedXML, 0644)

    // Step 2: Send to SUNAT when ready
    response, err := client.SendToSUNAT(signedXML, "01", "F001-00000001")
    if err != nil {
        log.Fatal(err)
    }

    if response.Success {
        fmt.Println("✅ Invoice accepted")
        response.SaveApplicationResponse("cdr.zip")
    }
}

Uso Avanzado

Para mayor control sobre certificados y configuración:

// Extraer certificado PEM de PFX
privateKey, cert, err := utils.ExtractPEMFromPFX("cert.pfx", "password", "/tmp")
if err != nil {
    log.Fatal(err)
}

// Validar certificado
certInfo, err := utils.GetCertificateInfo(cert)
if err != nil {
    log.Fatal(err)
}

// Configurar con archivos PEM
client.SetCertificate(privateKey, cert)

Estructura de Directorios

sunatlib/
├── signer/          # Firma XML con xmlsec1
│   └── xmlsigner.go
├── utils/           # Utilidades para certificados
│   └── cert.go
├── examples/        # Ejemplos de uso
│   ├── simple_example.go
│   └── advanced_example.go
├── sunat.go         # Cliente principal SUNAT
└── README.md

Casos de Uso

🔧 Firma únicamente (sin envío a SUNAT)
client := sunatlib.NewSUNATClient("", "", "", "") // Sin credenciales SUNAT
client.SetCertificateFromPFX("cert.pfx", "password", "/tmp")

signedXML, err := client.SignXML(xmlContent)
// Usar signedXML para almacenamiento, validación, etc.
📦 Procesamiento por lotes
documents := []string{"inv1.xml", "inv2.xml", "inv3.xml"}

for _, doc := range documents {
    xmlContent, _ := os.ReadFile(doc)
    signedXML, _ := client.SignXML(xmlContent)

    // Decidir cuándo enviar a SUNAT
    if shouldSendNow(doc) {
        client.SendToSUNAT(signedXML, "01", getSeriesNumber(doc))
    } else {
        saveForLater(signedXML, doc)
    }
}
⏰ Firmar ahora, enviar después
// Fase 1: Firmar durante horario de oficina
signedXML, _ := client.SignXML(xmlContent)
os.WriteFile("signed_invoice.xml", signedXML, 0644)

// Fase 2: Enviar durante ventana de transmisión
signedXML, _ := os.ReadFile("signed_invoice.xml")
response, _ := client.SendToSUNAT(signedXML, "01", "F001-00000001")

Servicios de Consulta (Independientes de Facturación)

Cliente de Consulta Completo
// Cliente independiente con ambos servicios (RUC + DNI)
consultationClient := sunatlib.NewConsultationClient("")

// O clientes específicos:
rucClient := sunatlib.NewRUCConsultationClient("")  // Solo RUC (Gratuito)
dniClient := sunatlib.NewDNIConsultationClient()     // Solo DNI/CE (Gratuito)

// Consulta básica de RUC
rucResult, err := consultationClient.ConsultRUC("20601030013")
if err != nil {
    log.Fatal(err)
}

if rucResult.Success {
    fmt.Printf("Razón Social: %s\n", rucResult.Data.RazonSocial)
    fmt.Printf("Estado: %s\n", rucResult.Data.Estado)
    fmt.Printf("Dirección: %s\n", rucResult.Data.Direccion)
}

// Consulta completa de RUC (incluye más detalles)
rucFullResult, err := consultationClient.ConsultRUCFull("20601030013")
if err != nil {
    log.Fatal(err)
}

if rucFullResult.Success {
    fmt.Printf("Actividad Económica: %s\n", rucFullResult.Data.ActividadEconomica)
    fmt.Printf("Número de Trabajadores: %s\n", rucFullResult.Data.NumeroTrabajadores)
    fmt.Printf("Tipo de Facturación: %s\n", rucFullResult.Data.TipoFacturacion)
}
Consulta DNI con EsSalud (Gratuito)
// DNI consultation (always free, independent from billing)
dniClient := sunatlib.NewDNIConsultationClient()

dniResult, err := dniClient.ConsultDNI("12345678")
if err != nil {
    log.Fatal(err)
}

if dniResult.Success {
    fmt.Printf("Nombre Completo: %s\n", dniResult.Data.NombreCompleto)
    fmt.Printf("DNI: %s\n", dniResult.Data.DNI)
}

// Carnet de Extranjería consultation
ceResult, err := client.ConsultCE("001234567")
if err != nil {
    log.Fatal(err)
}

if ceResult.Success {
    fmt.Printf("Nombre: %s\n", ceResult.Data.NombreCompleto)
}
Funciones de Validación
// Validar formato de documentos
isValidRUC := sunatlib.IsValidRUC("20601030013")     // true
isValidDNI := sunatlib.IsValidDNI("12345678")        // true
isValidCE := sunatlib.IsValidCE("001234567")         // true

Comunicación de Baja (Anulación de Documentos) - Nuevo!

Envío de Comunicación de Baja
// Crear cliente para comunicaciones de baja (PRODUCCIÓN)
client := sunatlib.NewVoidedDocumentsClient("20123456789", "MODDATOS", "moddatos")
defer client.Cleanup()

// Para pruebas, usar cliente BETA:
// client := sunatlib.NewVoidedDocumentsClientBeta("20123456789", "MODDATOS", "moddatos")

// Configurar certificado
err := client.SetCertificateFromPFX("certificate.pfx", "password", "/tmp/certs")
if err != nil {
    log.Fatal(err)
}

// Crear solicitud de baja
now := time.Now()
referenceDate := now.AddDate(0, 0, -1) // Documentos de ayer

request := &sunatlib.VoidedDocumentsRequest{
    RUC:           "20123456789",
    CompanyName:   "MI EMPRESA S.A.C.",
    SeriesNumber:  sunatlib.GenerateVoidedDocumentsSeries(referenceDate, 1), // RA-YYYYMMDD-001
    IssueDate:     now,
    ReferenceDate: referenceDate,
    Description:   "Comunicación de baja de documentos",
    Documents: []sunatlib.VoidedDocument{
        {
            DocumentTypeCode: "01",     // Factura
            DocumentSeries:   "F001",   // Serie
            DocumentNumber:   "000123", // Número
            VoidedReason:     "Error en datos del cliente",
        },
        {
            DocumentTypeCode: "03",     // Boleta
            DocumentSeries:   "B001",   // Serie
            DocumentNumber:   "000456", // Número
            VoidedReason:     "Duplicado por error del sistema",
        },
    },
}

// Enviar comunicación de baja
response, err := client.SendVoidedDocuments(request)
if err != nil {
    log.Fatal(err)
}

if response.Success {
    fmt.Printf("✅ Comunicación enviada. Ticket: %s\n", response.Ticket)

    // Consultar estado usando el ticket (método básico)
    statusResponse, err := client.GetVoidedDocumentsStatus(response.Ticket)
    if err == nil && statusResponse.Success {
        statusResponse.SaveApplicationResponse("baja_cdr.zip")
    }

    // O usar el método mejorado para consulta de tickets
    ticketResponse, err := client.QueryVoidedDocumentsTicket(response.Ticket)
    if err == nil {
        if ticketResponse.IsSuccessful() {
            fmt.Println("✅ Procesado exitosamente")
            ticketResponse.SaveApplicationResponse("baja_cdr.zip")
        } else if ticketResponse.IsInProgress() {
            fmt.Println("⏳ Aún en proceso...")
        } else if ticketResponse.HasErrors() {
            fmt.Println("❌ Procesado con errores")
        }
    }
}
Consulta Avanzada de Tickets de Comunicación de Baja - Nuevo!

🎯 Filosofía de la Librería: Esta librería proporciona los datos, el usuario decide qué hacer con ellos. No fuerza dónde o cómo guardar archivos.

// Consulta individual de ticket con información detallada
ticketResponse, err := client.QueryVoidedDocumentsTicket("12345678901234567890")
if err != nil {
    log.Fatal(err)
}

// Verificar estado usando métodos de conveniencia
if ticketResponse.IsSuccessful() {
    fmt.Println("✅ Comunicación procesada exitosamente")

    // La librería proporciona los datos, el usuario decide qué hacer
    if ticketResponse.HasApplicationResponse() {
        cdrData := ticketResponse.GetApplicationResponse()

        // El usuario puede:
        // 1. Guardar donde desee
        os.WriteFile("mi_directorio/cdr.zip", cdrData, 0644)

        // 2. Procesar directamente
        fmt.Printf("CDR size: %d bytes\n", len(cdrData))

        // 3. Enviar por email, subir a la nube, guardar en BD, etc.
        // sendEmail(cdrData)
        // uploadToCloud(cdrData)
        // saveToDatabase(ticketResponse.Ticket, cdrData)
    }
} else if ticketResponse.IsInProgress() {
    fmt.Println("⏳ Comunicación en proceso...")
} else if ticketResponse.HasErrors() {
    fmt.Println("❌ Comunicación procesada con errores")

    // Obtener detalles del error para análisis del usuario
    if ticketResponse.HasApplicationResponse() {
        errorData := ticketResponse.GetApplicationResponse()
        // Usuario decide cómo manejar los errores
        analyzeErrors(errorData)
        logToSystem(ticketResponse.Ticket, errorData)
    }
}

// Esperar procesamiento con timeout
finalResponse, err := client.WaitForTicketProcessing(
    "12345678901234567890",
    10*time.Minute, // Tiempo máximo de espera
    30*time.Second, // Intervalo de consulta
)

// Consulta múltiple de tickets
tickets := []string{"ticket1", "ticket2", "ticket3"}
responses, err := client.BatchQueryTickets(tickets)
if err == nil {
    for _, response := range responses {
        fmt.Printf("Ticket %s: %s\n", response.Ticket, response.GetTicketStatusDescription())
    }
}

Consulta de Validez de Documentos Electrónicos - Nuevo!

Validación de Documentos con SOAP SUNAT
// Crear cliente de validación con credenciales SOL (PRODUCCIÓN)
client := sunatlib.NewDocumentValidationClient(
    "20123456789", // RUC
    "MODDATOS",    // Usuario SOL
    "moddatos",    // Clave SOL
)

// Para pruebas, usar cliente BETA:
// client := sunatlib.NewDocumentValidationClientBeta("20123456789", "MODDATOS", "moddatos")

// Validar una factura
response, err := client.ValidateInvoice(
    "20123456789", // RUC emisor
    "F001",        // Serie
    "000123",      // Número
    "15/01/2025",  // Fecha emisión (DD/MM/YYYY)
    "118.00",      // Importe total
)

if err != nil {
    log.Fatal(err)
}

if response.Success {
    fmt.Printf("✅ Documento válido: %t\n", response.IsDocumentValid())
    fmt.Printf("📄 Estado: %s\n", response.GetStatusDescription())

    if response.IsValid {
        fmt.Println("🎯 Documento VÁLIDO en SUNAT")
    } else {
        fmt.Println("❌ Documento INVÁLIDO")
    }
} else {
    fmt.Printf("❌ Error: %s\n", response.GetErrorMessage())
}

// Otros métodos de validación disponibles:
receiptResp, _ := client.ValidateReceipt("20123456789", "B001", "000456", "15/01/2025", "59.00")
creditNoteResp, _ := client.ValidateCreditNote("20123456789", "FC01", "000001", "15/01/2025", "23.60")
debitNoteResp, _ := client.ValidateDebitNote("20123456789", "FD01", "000001", "15/01/2025", "15.00")

// Consulta básica de estado (sin fecha ni importe)
statusResp, _ := client.CheckDocumentStatus("20123456789", "01", "F001", "000789")

Validación CPE con Credenciales Master - Nuevo!

Validación usando credenciales master SUNAT
// Crear cliente de validación con credenciales master
validator := sunatlib.NewValidationClient(
    masterRUC,      // Master RUC (parámetro)
    masterUsername, // Master username (parámetro)
    masterPassword, // Master password (parámetro)
)

// Validar factura
invoiceResult, err := validator.ValidateInvoice(
    "20123456789",     // RUC emisor
    "F001",            // Serie
    "00000001",        // Número
    "2024-01-15",      // Fecha emisión (YYYY-MM-DD)
    1250.50,           // Importe total
)

if err != nil {
    log.Printf("Error: %v", err)
} else {
    fmt.Printf("Estado: %s\n", invoiceResult.State)         // VALIDO, NO_INFORMADO, ANULADO, RECHAZADO
    fmt.Printf("Es válido: %t\n", invoiceResult.IsValid)    // true/false
    fmt.Printf("Mensaje: %s\n", invoiceResult.StatusMessage)
}

// Validar boleta
receiptResult, err := validator.ValidateReceipt(
    "20123456789",     // RUC emisor
    "B001",            // Serie
    "00000001",        // Número
    "2024-01-15",      // Fecha emisión (YYYY-MM-DD)
    85.50,             // Importe total
)

// Validación personalizada con parámetros completos
customParams := &sunatlib.ValidationParams{
    IssuerRUC:           "20123456789",
    DocumentType:        "01", // 01=Factura, 03=Boleta
    SeriesNumber:        "F001",
    DocumentNumber:      "00000002",
    RecipientDocType:    "6", // 6=RUC, 1=DNI, 4=CE
    RecipientDocNumber:  "20987654321",
    IssueDate:           "2024-01-15", // YYYY-MM-DD
    TotalAmount:         2500.75,
    AuthorizationNumber: "", // Generalmente vacío
}

result, err := validator.ValidateDocument(customParams)

Endpoints y Ambientes - Nuevo!

Endpoints de Producción vs Beta/Pruebas

La librería incluye soporte completo para endpoints tanto de producción como de pruebas (BETA):

// ENDPOINTS DE PRODUCCIÓN
// Facturación electrónica
client := sunatlib.NewVoidedDocumentsClient("20123456789", "USUARIO", "PASSWORD")

// Validación de documentos
validationClient := sunatlib.NewDocumentValidationClient("20123456789", "USUARIO", "PASSWORD")

// ENDPOINTS DE PRUEBAS (BETA)
// Facturación electrónica (para testing)
betaClient := sunatlib.NewVoidedDocumentsClientBeta("20123456789", "MODDATOS", "moddatos")

// Validación de documentos (para testing)
betaValidationClient := sunatlib.NewDocumentValidationClientBeta("20123456789", "MODDATOS", "moddatos")
Endpoints Disponibles

Producción:

  • Facturación: https://e-factura.sunat.gob.pe/ol-ti-itcpfegem/billService
  • Validación: https://e-factura.sunat.gob.pe/ol-it-wsconsvalidcpe/billValidService

Beta/Pruebas:

  • Facturación: https://e-beta.sunat.gob.pe/ol-ti-itcpfegem-beta/billService
  • Validación: https://e-beta.sunat.gob.pe/ol-it-wsconsvalidcpe/billValidService
Credenciales de Prueba

Para el ambiente BETA, usar las credenciales estándar de SUNAT:

  • Usuario: MODDATOS
  • Contraseña: moddatos
Flujo Recomendado de Desarrollo
  1. Desarrollo: Usar endpoints BETA con credenciales de prueba
  2. Testing: Validar toda la funcionalidad en BETA
  3. Producción: Cambiar a endpoints de producción con credenciales reales

API Reference

SUNATClient
Métodos

Constructores:

  • NewSUNATClient(ruc, username, password, endpoint string) *SUNATClient - Cliente de facturación electrónica

Constructores de Consulta: - New!

  • NewConsultationClient(apiKey string) *ConsultationClient - RUC + DNI/CE (Gratuito)
  • NewRUCConsultationClient(apiKey string) *ConsultationClient - Solo RUC (Gratuito)
  • NewDNIConsultationClient() *ConsultationClient - Solo DNI/CE (Gratuito)

Constructores de Baja y Validación: - New!

  • NewVoidedDocumentsClient(ruc, username, password string) *SUNATClient - Comunicaciones de baja (PRODUCCIÓN)
  • NewVoidedDocumentsClientBeta(ruc, username, password string) *SUNATClient - Comunicaciones de baja (BETA/Pruebas)
  • NewDocumentValidationClient(ruc, username, password string) *DocumentValidationClient - Validación de documentos (PRODUCCIÓN)
  • NewDocumentValidationClientBeta(ruc, username, password string) *DocumentValidationClient - Validación de documentos (BETA/Pruebas)

Configuración de certificados:

  • SetCertificate(privateKeyPath, certificatePath string) error
  • SetCertificateFromPFX(pfxPath, password, tempDir string) error

Firma y envío a SUNAT:

  • SignXML(xmlContent []byte) ([]byte, error)
  • SendToSUNAT(signedXML []byte, documentType, seriesNumber string) (*SUNATResponse, error)
  • SignAndSendInvoice(xmlContent []byte, documentType, seriesNumber string) (*SUNATResponse, error)

Comunicaciones de Baja: - New!

  • SendVoidedDocuments(request *VoidedDocumentsRequest) (*VoidedDocumentsResponse, error)
  • GetVoidedDocumentsStatus(ticket string) (*SUNATResponse, error)
  • QueryVoidedDocumentsTicket(ticket string) (*TicketStatusResponse, error) - Nuevo!
  • WaitForTicketProcessing(ticket string, maxWaitTime, pollInterval time.Duration) (*TicketStatusResponse, error) - Nuevo!
  • BatchQueryTickets(tickets []string) ([]*TicketStatusResponse, error) - Nuevo!
  • GenerateVoidedDocumentsXML(request *VoidedDocumentsRequest) ([]byte, error)
  • GenerateVoidedDocumentsSeries(referenceDate time.Time, sequential int) string
ConsultationClient - New!

Métodos de consulta:

  • ConsultRUC(ruc string) (*RUCBasicResponse, error) - Consulta básica RUC
  • ConsultRUCFull(ruc string) (*RUCFullResponse, error) - Consulta completa RUC
  • ConsultDNI(dni string) (*DNIResponse, error) - Consulta DNI
  • ConsultCE(ce string) (*DNIResponse, error) - Consulta CE

Limpieza:

  • Cleanup() error
DocumentValidationClient - New!

Métodos de validación:

  • ValidateDocument(req *ValidationRequest) (*ValidationResponse, error) - Validación genérica
  • ValidateInvoice(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error) - Validar factura
  • ValidateReceipt(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error) - Validar boleta
  • ValidateCreditNote(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error) - Validar nota de crédito
  • ValidateDebitNote(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error) - Validar nota de débito
  • CheckDocumentStatus(ruc, documentType, series, number string) (*ValidationResponse, error) - Consulta básica de estado
VoidedDocumentsRequest - New!

Estructura para comunicaciones de baja:

  • RUC string - RUC de la empresa
  • CompanyName string - Razón social de la empresa
  • SeriesNumber string - Número de serie de la comunicación (RA-YYYYMMDD-###)
  • IssueDate time.Time - Fecha de emisión de la comunicación
  • ReferenceDate time.Time - Fecha de referencia (fecha de los documentos a anular)
  • Documents []VoidedDocument - Lista de documentos a anular
  • Description string - Descripción de la comunicación
VoidedDocument - New!

Estructura para documentos a anular:

  • DocumentTypeCode string - Código de tipo de documento (01=Factura, 03=Boleta, etc.)
  • DocumentSeries string - Serie del documento (F001, B001, etc.)
  • DocumentNumber string - Número correlativo del documento
  • VoidedReason string - Motivo de la anulación
SUNATResponse
Propiedades
  • Success bool - Indica si la operación fue exitosa
  • Message string - Mensaje de respuesta de SUNAT
  • ResponseXML []byte - XML completo de respuesta
  • ApplicationResponse []byte - CDR en formato ZIP
  • Error error - Error si lo hubo
Métodos
  • SaveApplicationResponse(outputPath string) error - Guarda el CDR
TicketStatusResponse - New!
Propiedades
  • Success bool - Indica si la consulta fue exitosa
  • Message string - Mensaje de respuesta
  • Ticket string - Número de ticket consultado
  • StatusCode string - Código de estado de SUNAT (0=Exitoso, 98=En proceso, 99=Con errores)
  • StatusDescription string - Descripción del estado
  • ProcessDate time.Time - Fecha de procesamiento
  • ResponseXML []byte - XML completo de respuesta
  • ApplicationResponse []byte - CDR en formato ZIP si está disponible
  • Error error - Error si lo hubo
Métodos
  • GetTicketStatusDescription() string - Descripción legible del estado del ticket
  • IsProcessed() bool - True si el ticket fue procesado (exitoso o con errores)
  • IsSuccessful() bool - True si el ticket fue procesado exitosamente
  • IsInProgress() bool - True si el ticket aún está en proceso
  • HasErrors() bool - True si el ticket fue procesado con errores
  • GetApplicationResponse() []byte - Obtiene los datos del CDR/respuesta
  • HasApplicationResponse() bool - True si hay datos de respuesta disponibles
RUCBasicResponse / RUCFullResponse - New!
Propiedades
  • Success bool - Indica si la consulta fue exitosa
  • Data *RUCBasicData / Data *RUCFullData - Datos de la empresa consultada
  • Message string - Mensaje de respuesta

RUCBasicData campos:

  • RUC string - Número de RUC
  • RazonSocial string - Razón social de la empresa
  • Estado string - Estado del contribuyente
  • Condicion string - Condición del contribuyente
  • Direccion string - Dirección fiscal
  • Distrito string, Provincia string, Departamento string - Ubicación

RUCFullData campos adicionales:

  • ActividadEconomica string - Actividad económica principal
  • NumeroTrabajadores string - Número de trabajadores
  • TipoFacturacion string - Tipo de sistema de facturación
  • ComercioExterior string - Si tiene actividad de comercio exterior
DNIResponse - New!
Propiedades
  • Success bool - Indica si la consulta fue exitosa
  • Data *DNIData - Datos de la persona consultada
  • Message string - Mensaje de respuesta

DNIData campos:

  • DNI string - Número de documento
  • NombreCompleto string - Nombre completo
  • Nombres string - Nombres de la persona
  • ApellidoPaterno string - Apellido paterno
  • ApellidoMaterno string - Apellido materno
Funciones de Validación - New!
  • IsValidRUC(ruc string) bool - Valida formato de RUC
  • IsValidDNI(dni string) bool - Valida formato de DNI
  • IsValidCE(ce string) bool - Valida formato de Carnet de Extranjería
Utils
Funciones
  • ExtractPEMFromPFX(pfxPath, password, outputDir string) (privateKeyPath, certPath string, err error)
  • ValidateCertificate(certPath string) (*x509.Certificate, error)
  • CheckXMLSec1Available() error
  • GetCertificateInfo(certPath string) (map[string]string, error)

Ejemplos

Ver la carpeta examples/ para ejemplos completos:

  • simple_example.go - Uso básico de la librería
  • advanced_example.go - Manejo avanzado con validación de certificados
  • flexible_usage.go - Patrones avanzados de uso
  • voided_documents_example.go - Nuevo! Ejemplos de comunicaciones de baja
  • document_validation_example.go - Nuevo! Ejemplos de validación de documentos
  • beta_testing_example.go - Nuevo! Ejemplos de testing con endpoints BETA
  • integrated_example.go - Nuevo! Ejemplo completo integrando todas las funcionalidades
  • ticket_query_example.go - Nuevo! Ejemplos de consulta avanzada de tickets de comunicación de baja

Limitaciones

  • Requiere xmlsec1 instalado en el sistema
  • Solo soporta algoritmos RSA-SHA1 (requerimiento SUNAT)
  • Diseñado específicamente para documentos UBL 2.1 de SUNAT Perú

Contribución

Las contribuciones son bienvenidas. Por favor:

  1. Fork del proyecto
  2. Crear rama para tu feature
  3. Commit de cambios
  4. Push a la rama
  5. Crear Pull Request

Licencia

MIT License

Soporte

Para reportar bugs o solicitar features, crear un issue en el repositorio.

Documentation

Overview

Package sunatlib provides functionality for SUNAT electronic document validation

Package sunatlib defines SUNAT service endpoints

Package sunatlib provides XML digital signature functionality for SUNAT Peru

Package sunatlib provides document validation functionality for SUNAT Peru

Package sunatlib provides functionality for SUNAT voided documents (comunicación de baja)

Index

Constants

View Source
const (
	// Production endpoints for electronic invoicing
	SUNATProductionBillService      = "https://e-factura.sunat.gob.pe/ol-ti-itcpfegem/billService"
	SUNATProductionRetentionService = "https://e-factura.sunat.gob.pe/ol-ti-itemision-otroscpe-gem/billService"
	SUNATProductionGuideService     = "https://e-factura.sunat.gob.pe/ol-ti-itemision-guia-gem/billService"

	// Production endpoint for document validation
	SUNATProductionValidationService = "https://e-factura.sunat.gob.pe/ol-it-wsconsvalidcpe/billValidService"
)

SUNAT Production Endpoints

View Source
const (
	// Beta endpoints for electronic invoicing (testing)
	SUNATBetaBillService      = "https://e-beta.sunat.gob.pe/ol-ti-itcpfegem-beta/billService"
	SUNATBetaRetentionService = "https://e-beta.sunat.gob.pe/ol-ti-itemision-otroscpe-gem-beta/billService"
	SUNATBetaGuideService     = "https://e-beta.sunat.gob.pe/ol-ti-itemision-guia-gem-beta/billService"

	// Beta endpoint for document validation (testing)
	SUNATBetaValidationService = "https://e-beta.sunat.gob.pe/ol-it-wsconsvalidcpe/billValidService"
)

SUNAT Beta/Testing Endpoints

Variables

This section is empty.

Functions

func GenerateVoidedDocumentsSeries added in v1.3.0

func GenerateVoidedDocumentsSeries(referenceDate time.Time, sequential int) string

GenerateVoidedDocumentsSeries generates a series number for voided documents Format: RA-YYYYMMDD-### where ### is a sequential number

func GetBillServiceEndpoint added in v1.3.0

func GetBillServiceEndpoint(env Environment) string

GetBillServiceEndpoint returns the appropriate billService endpoint based on environment

func GetGuideServiceEndpoint added in v1.3.0

func GetGuideServiceEndpoint(env Environment) string

GetGuideServiceEndpoint returns the appropriate guide service endpoint based on environment

func GetRetentionServiceEndpoint added in v1.3.0

func GetRetentionServiceEndpoint(env Environment) string

GetRetentionServiceEndpoint returns the appropriate retention/perception service endpoint based on environment

func GetValidationServiceEndpoint added in v1.3.0

func GetValidationServiceEndpoint(env Environment) string

GetValidationServiceEndpoint returns the appropriate validation service endpoint based on environment

func IsValidCE added in v1.2.0

func IsValidCE(ce string) bool

IsValidCE validates if a CE number has the correct format

func IsValidDNI added in v1.2.0

func IsValidDNI(dni string) bool

IsValidDNI validates if a DNI number has the correct format

func IsValidRUC added in v1.2.0

func IsValidRUC(ruc string) bool

IsValidRUC validates if a RUC number has the correct format

Types

type ConsultationClient added in v1.2.0

type ConsultationClient struct {
	// contains filtered or unexported fields
}

ConsultationClient handles RUC and DNI consultation services independently

func NewConsultationClient added in v1.2.0

func NewConsultationClient(apiKey string) *ConsultationClient

NewConsultationClient creates a new consultation client with both services apiKey is kept for backward compatibility but optional for RUC since it now uses direct SUNAT API

func NewDNIConsultationClient added in v1.2.0

func NewDNIConsultationClient() *ConsultationClient

NewDNIConsultationClient creates a client only for DNI/CE consultation (free)

func NewRUCConsultationClient added in v1.2.0

func NewRUCConsultationClient(apiKey string) *ConsultationClient

NewRUCConsultationClient creates a client only for RUC consultation apiKey is kept for backward compatibility but optional since it now uses direct SUNAT API

func (*ConsultationClient) ConsultCE added in v1.2.0

func (c *ConsultationClient) ConsultCE(ce string) (*DNIResponse, error)

ConsultCE performs a Carnet de Extranjería consultation

func (*ConsultationClient) ConsultDNI added in v1.2.0

func (c *ConsultationClient) ConsultDNI(dni string) (*DNIResponse, error)

ConsultDNI performs a DNI consultation

func (*ConsultationClient) ConsultRUC added in v1.2.0

func (c *ConsultationClient) ConsultRUC(ruc string) (*RUCBasicResponse, error)

ConsultRUC performs a basic RUC consultation

func (*ConsultationClient) ConsultRUCFull added in v1.2.0

func (c *ConsultationClient) ConsultRUCFull(ruc string) (*RUCFullResponse, error)

ConsultRUCFull performs a complete RUC consultation

type DNIData added in v1.2.0

type DNIData struct {
	DNI             string `json:"dni"`
	NombreCompleto  string `json:"nombre_completo"`
	Nombres         string `json:"nombres"`
	ApellidoPaterno string `json:"apellido_paterno"`
	ApellidoMaterno string `json:"apellido_materno"`
	FechaNacimiento string `json:"fecha_nacimiento,omitempty"`
	Sexo            string `json:"sexo,omitempty"`
	EstadoCivil     string `json:"estado_civil,omitempty"`
}

DNIData contains personal information from RENIEC

type DNIResponse added in v1.2.0

type DNIResponse struct {
	Success bool     `json:"success"`
	Data    *DNIData `json:"data,omitempty"`
	Message string   `json:"message,omitempty"`
}

DNIResponse represents the response from EsSalud DNI validation service

type DNIService added in v1.2.0

type DNIService struct {
	BaseURL    string
	HTTPClient *http.Client
}

DNIService handles DNI consultation operations

func NewDNIService added in v1.2.0

func NewDNIService() *DNIService

NewDNIService creates a new DNI service instance

func (*DNIService) ConsultCE added in v1.2.0

func (ds *DNIService) ConsultCE(ce string) (*DNIResponse, error)

ConsultCE performs a Carnet de Extranjería consultation

func (*DNIService) ConsultDNI added in v1.2.0

func (ds *DNIService) ConsultDNI(dni string) (*DNIResponse, error)

ConsultDNI performs a DNI consultation using EsSalud service

type DocumentValidationClient added in v1.3.0

type DocumentValidationClient struct {
	RUC      string
	Username string
	Password string
	Endpoint string
	Client   *http.Client
}

DocumentValidationClient handles document validation requests to SUNAT

func NewDocumentValidationClient added in v1.3.0

func NewDocumentValidationClient(ruc, username, password string) *DocumentValidationClient

NewDocumentValidationClient creates a new document validation client with credentials (PRODUCTION)

func NewDocumentValidationClientBeta added in v1.3.0

func NewDocumentValidationClientBeta(ruc, username, password string) *DocumentValidationClient

NewDocumentValidationClientBeta creates a new document validation client for BETA testing

func NewDocumentValidationClientWithCredentials added in v1.3.0

func NewDocumentValidationClientWithCredentials(ruc, username, password string) *DocumentValidationClient

NewDocumentValidationClientWithCredentials creates a new document validation client with SUNAT credentials (PRODUCTION)

func (*DocumentValidationClient) CheckDocumentStatus added in v1.3.0

func (c *DocumentValidationClient) CheckDocumentStatus(ruc, documentType, series, number string) (*ValidationResponse, error)

CheckDocumentStatus checks the status of a document using basic parameters

func (*DocumentValidationClient) ValidateCreditNote added in v1.3.0

func (c *DocumentValidationClient) ValidateCreditNote(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error)

ValidateCreditNote validates an electronic credit note

func (*DocumentValidationClient) ValidateDebitNote added in v1.3.0

func (c *DocumentValidationClient) ValidateDebitNote(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error)

ValidateDebitNote validates an electronic debit note

func (*DocumentValidationClient) ValidateDocument added in v1.3.0

ValidateDocument validates an electronic document with SUNAT using SOAP

func (*DocumentValidationClient) ValidateInvoice added in v1.3.0

func (c *DocumentValidationClient) ValidateInvoice(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error)

ValidateInvoice validates an electronic invoice

func (*DocumentValidationClient) ValidateReceipt added in v1.3.0

func (c *DocumentValidationClient) ValidateReceipt(ruc, series, number, issueDate, totalAmount string) (*ValidationResponse, error)

ValidateReceipt validates an electronic receipt (boleta)

type Environment added in v1.3.0

type Environment int

Environment types

const (
	Production Environment = iota
	Beta
)

type EsSaludResponse added in v1.2.0

type EsSaludResponse struct {
	Datos     string `json:"datos"`     // Nombre completo
	Apellidos string `json:"apellidos"` // Apellidos completos
	Nombres   string `json:"nombres"`   // Solo nombres
	// Campos alternativos por si cambia el formato
	NumeroDocumento string `json:"numeroDocumento"`
	TipoDocumento   string `json:"tipoDocumento"`
	ApellidoPaterno string `json:"apellidoPaterno"`
	ApellidoMaterno string `json:"apellidoMaterno"`
	NombreCompleto  string `json:"nombreCompleto"`
}

EsSaludResponse represents the raw response from EsSalud service

type RUCBasicData added in v1.2.0

type RUCBasicData struct {
	RUC                 string `json:"numero_documento"`
	RazonSocial         string `json:"razon_social"`
	Estado              string `json:"estado"`
	Condicion           string `json:"condicion"`
	Direccion           string `json:"direccion"`
	Ubigeo              string `json:"ubigeo"`
	Distrito            string `json:"distrito"`
	Provincia           string `json:"provincia"`
	Departamento        string `json:"departamento"`
	EsAgenteRetencion   bool   `json:"es_agente_retencion"`
	EsBuenContribuyente bool   `json:"es_buen_contribuyente"`
	ViaTipo             string `json:"via_tipo"`
	ViaNombre           string `json:"via_nombre"`
	ZonaCodigo          string `json:"zona_codigo"`
	ZonaTipo            string `json:"zona_tipo"`
	Numero              string `json:"numero"`
	Interior            string `json:"interior"`
}

RUCBasicData contains basic company information

type RUCBasicResponse added in v1.2.0

type RUCBasicResponse struct {
	Success bool          `json:"success"`
	Data    *RUCBasicData `json:"data,omitempty"`
	Message string        `json:"message,omitempty"`
}

RUCBasicResponse represents the standard response format

type RUCFullData added in v1.2.0

type RUCFullData struct {
	RUCBasicData
	ActividadEconomica string `json:"actividad_economica"`
	NumeroTrabajadores string `json:"numero_trabajadores"`
	TipoFacturacion    string `json:"tipo_facturacion"`
	TipoContabilidad   string `json:"tipo_contabilidad"`
	ComercioExterior   string `json:"comercio_exterior"`
	FechaInscripcion   string `json:"fecha_inscripcion"`
}

RUCFullData contains complete company information

type RUCFullResponse added in v1.2.0

type RUCFullResponse struct {
	Success bool         `json:"success"`
	Data    *RUCFullData `json:"data,omitempty"`
	Message string       `json:"message,omitempty"`
}

RUCFullResponse represents the response with full data (if available)

type RUCService added in v1.2.0

type RUCService struct {
	BaseURL    string
	HTTPClient *http.Client
}

RUCService handles RUC consultation operations

func NewRUCService added in v1.2.0

func NewRUCService(apiKey string) *RUCService

NewRUCService creates a new RUC service instance (apiKey is kept for backward compatibility but unused)

func (*RUCService) ConsultBasic added in v1.2.0

func (rs *RUCService) ConsultBasic(ruc string) (*RUCBasicResponse, error)

ConsultBasic performs a basic RUC consultation using SUNAT's direct API

func (*RUCService) ConsultFull added in v1.2.0

func (rs *RUCService) ConsultFull(ruc string) (*RUCFullResponse, error)

ConsultFull performs a RUC consultation (limited data due to simplified API)

type SUNATClient

type SUNATClient struct {
	RUC      string
	Username string
	Password string
	Endpoint string
	// contains filtered or unexported fields
}

SUNATClient handles interactions with SUNAT web services for electronic billing

func NewSUNATClient

func NewSUNATClient(ruc, username, password, endpoint string) *SUNATClient

NewSUNATClient creates a new SUNAT client for electronic billing

func NewVoidedDocumentsClient added in v1.3.0

func NewVoidedDocumentsClient(ruc, username, password string) *SUNATClient

NewVoidedDocumentsClient creates a new SUNAT client for voided documents (PRODUCTION)

func NewVoidedDocumentsClientBeta added in v1.3.0

func NewVoidedDocumentsClientBeta(ruc, username, password string) *SUNATClient

NewVoidedDocumentsClientBeta creates a new SUNAT client for voided documents (BETA/Testing)

func (*SUNATClient) BatchQueryTickets added in v1.4.0

func (c *SUNATClient) BatchQueryTickets(tickets []string) ([]*TicketStatusResponse, error)

BatchQueryTickets queries multiple tickets and returns their status

func (*SUNATClient) Cleanup

func (c *SUNATClient) Cleanup() error

Cleanup cleans up temporary files

func (*SUNATClient) GenerateVoidedDocumentsXML added in v1.3.0

func (c *SUNATClient) GenerateVoidedDocumentsXML(request *VoidedDocumentsRequest) ([]byte, error)

GenerateVoidedDocumentsXML generates the XML for voided documents communication

func (*SUNATClient) GetVoidedDocumentsStatus added in v1.3.0

func (c *SUNATClient) GetVoidedDocumentsStatus(ticket string) (*SUNATResponse, error)

GetVoidedDocumentsStatus checks the status of a voided documents communication using the ticket

func (*SUNATClient) QueryVoidedDocumentsTicket added in v1.4.0

func (c *SUNATClient) QueryVoidedDocumentsTicket(ticket string) (*TicketStatusResponse, error)

QueryVoidedDocumentsTicket queries the status of a voided documents communication ticket This is a more specific and enhanced version of GetVoidedDocumentsStatus

func (*SUNATClient) SendToSUNAT added in v1.1.0

func (c *SUNATClient) SendToSUNAT(signedXML []byte, documentType, seriesNumber string) (*SUNATResponse, error)

SendToSUNAT sends a signed XML document to SUNAT

func (*SUNATClient) SendVoidedDocuments added in v1.3.0

func (c *SUNATClient) SendVoidedDocuments(request *VoidedDocumentsRequest) (*VoidedDocumentsResponse, error)

SendVoidedDocuments sends voided documents communication to SUNAT

func (*SUNATClient) SetCertificate

func (c *SUNATClient) SetCertificate(privateKeyPath, certificatePath string) error

SetCertificate configures the XML signer with certificate files

func (*SUNATClient) SetCertificateFromPFX

func (c *SUNATClient) SetCertificateFromPFX(pfxPath, password, tempDir string) error

SetCertificateFromPFX extracts and configures certificate from PFX file

func (*SUNATClient) SignAndSendInvoice

func (c *SUNATClient) SignAndSendInvoice(xmlContent []byte, documentType, seriesNumber string) (*SUNATResponse, error)

SignAndSendInvoice signs an XML invoice and sends it to SUNAT (convenience method)

func (*SUNATClient) SignXML added in v1.1.0

func (c *SUNATClient) SignXML(xmlContent []byte) ([]byte, error)

SignXML signs an XML document and returns the signed XML

func (*SUNATClient) WaitForTicketProcessing added in v1.4.0

func (c *SUNATClient) WaitForTicketProcessing(ticket string, maxWaitTime time.Duration, pollInterval time.Duration) (*TicketStatusResponse, error)

WaitForTicketProcessing waits for a ticket to be processed, polling every interval Returns the final status response when processing is complete or timeout is reached

type SUNATResponse

type SUNATResponse struct {
	Success             bool
	Message             string
	ResponseXML         []byte
	ApplicationResponse []byte
	Error               error
}

SUNATResponse represents the response from SUNAT

func (*SUNATResponse) SaveApplicationResponse

func (r *SUNATResponse) SaveApplicationResponse(outputPath string) error

SaveApplicationResponse saves the CDR (Constancia de Recepción) to a file

type SunatRawResponse added in v1.6.0

type SunatRawResponse struct {
	Message string `json:"message"`
	Lista   []struct {
		IdProvincia     string `json:"idprovincia"`
		IdDistrito      string `json:"iddistrito"`
		RazonSocial     string `json:"apenomdenunciado"`
		IdDepartamento  string `json:"iddepartamento"`
		Direccion       string `json:"direstablecimiento"`
		DesDistrito     string `json:"desdistrito"`
		DesProvincia    string `json:"desprovincia"`
		DesDepartamento string `json:"desdepartamento"`
	} `json:"lista"`
}

SunatRawResponse represents the direct response from SUNAT service

type TicketStatusResponse added in v1.4.0

type TicketStatusResponse struct {
	Success             bool
	Message             string
	Ticket              string
	StatusCode          string    // SUNAT status code
	StatusDescription   string    // SUNAT status description
	ProcessDate         time.Time // Date when the document was processed
	ResponseXML         []byte    // Full SOAP response
	ApplicationResponse []byte    // CDR ZIP content if available
	Error               error
}

TicketStatusResponse represents the response from ticket status query

func (*TicketStatusResponse) GetApplicationResponse added in v1.4.0

func (r *TicketStatusResponse) GetApplicationResponse() []byte

GetApplicationResponse returns the CDR response data if available

func (*TicketStatusResponse) GetTicketStatusDescription added in v1.4.0

func (r *TicketStatusResponse) GetTicketStatusDescription() string

GetTicketStatusDescription returns a human-readable description of the ticket status

func (*TicketStatusResponse) HasApplicationResponse added in v1.4.0

func (r *TicketStatusResponse) HasApplicationResponse() bool

HasApplicationResponse returns true if CDR response data is available

func (*TicketStatusResponse) HasErrors added in v1.4.0

func (r *TicketStatusResponse) HasErrors() bool

HasErrors returns true if the ticket was processed but with errors

func (*TicketStatusResponse) IsInProgress added in v1.4.0

func (r *TicketStatusResponse) IsInProgress() bool

IsInProgress returns true if the ticket is still being processed

func (*TicketStatusResponse) IsProcessed added in v1.4.0

func (r *TicketStatusResponse) IsProcessed() bool

IsProcessed returns true if the ticket has been processed (successfully or with errors)

func (*TicketStatusResponse) IsSuccessful added in v1.4.0

func (r *TicketStatusResponse) IsSuccessful() bool

IsSuccessful returns true if the ticket was processed successfully

type ValidationClient added in v1.5.0

type ValidationClient struct {
	// contains filtered or unexported fields
}

ValidationClient handles SUNAT document validation with master credentials

func NewValidationClient added in v1.5.0

func NewValidationClient(masterRUC, masterUsername, masterPassword string) *ValidationClient

NewValidationClient creates a new SUNAT validation client with master credentials

func (*ValidationClient) ValidateDocument added in v1.5.0

func (vc *ValidationClient) ValidateDocument(params *ValidationParams) (*ValidationResult, error)

ValidateDocument validates a document with SUNAT using master credentials

func (*ValidationClient) ValidateInvoice added in v1.5.0

func (vc *ValidationClient) ValidateInvoice(issuerRUC, seriesNumber, documentNumber, issueDate string, totalAmount float64) (*ValidationResult, error)

ValidateInvoice is a convenience method for validating invoices

func (*ValidationClient) ValidateReceipt added in v1.5.0

func (vc *ValidationClient) ValidateReceipt(issuerRUC, seriesNumber, documentNumber, issueDate string, totalAmount float64) (*ValidationResult, error)

ValidateReceipt is a convenience method for validating receipts

type ValidationParams added in v1.5.0

type ValidationParams struct {
	IssuerRUC           string  // RUC of the document issuer
	DocumentType        string  // Document type code (01=Invoice, 03=Receipt, etc.)
	SeriesNumber        string  // Series of the document (e.g., F001)
	DocumentNumber      string  // Document number (e.g., 00000001)
	RecipientDocType    string  // Recipient document type ("-" for default)
	RecipientDocNumber  string  // Recipient document number ("" for default)
	IssueDate           string  // Issue date in YYYY-MM-DD format
	TotalAmount         float64 // Total amount of the document
	AuthorizationNumber string  // Authorization number (usually empty)
}

ValidationParams contains the parameters for document validation

type ValidationRequest added in v1.3.0

type ValidationRequest struct {
	RUC                   string // Issuer RUC
	DocumentType          string // Document type code
	Series                string // Document series
	Number                string // Document number
	IssueDate             string // Issue date (DD/MM/YYYY)
	TotalAmount           string // Total amount
	RecipientDocumentType string // Recipient document type (optional, use "-" for empty)
	RecipientDocument     string // Recipient document number (optional)
	AuthorizationNumber   string // Authorization number (optional)
}

ValidationRequest represents a document validation request

type ValidationResponse added in v1.3.0

type ValidationResponse struct {
	Success       bool
	IsValid       bool
	StatusMessage string
	ErrorMessage  string
	ResponseXML   []byte
}

ValidationResponse represents the response from SUNAT validation service

func (*ValidationResponse) GetErrorMessage added in v1.3.0

func (vr *ValidationResponse) GetErrorMessage() string

GetErrorMessage returns the error message if any

func (*ValidationResponse) GetStatusDescription added in v1.3.0

func (vr *ValidationResponse) GetStatusDescription() string

GetStatusDescription returns a human-readable status description

func (*ValidationResponse) HasError added in v1.3.0

func (vr *ValidationResponse) HasError() bool

HasError returns true if there was an error in validation

func (*ValidationResponse) IsDocumentValid added in v1.3.0

func (vr *ValidationResponse) IsDocumentValid() bool

IsDocumentValid returns true if the document is valid

type ValidationResult added in v1.5.0

type ValidationResult struct {
	Success       bool   `json:"success"`
	IsValid       bool   `json:"is_valid"`
	StatusCode    string `json:"status_code"`
	StatusMessage string `json:"status_message"`
	ErrorDetails  string `json:"error_details,omitempty"`
	State         string `json:"state"`                  // VALIDO, NO_INFORMADO, ANULADO, RECHAZADO
	ResponseXML   string `json:"response_xml,omitempty"` // Raw XML response from SUNAT
}

ValidationResult contains the result of SUNAT validation

type ValidationSOAPResponse added in v1.3.0

type ValidationSOAPResponse struct {
	XMLName xml.Name `xml:"Envelope"`
	Body    struct {
		ValidaCDPResponse struct {
			StatusCode    string `xml:"statusCode"`
			StatusMessage string `xml:"statusMessage"`
			CDPValidated  string `xml:"cdpvalidado"`
		} `xml:"validaCDPcriteriosResponse"`
		Fault struct {
			FaultCode   string `xml:"faultcode"`
			FaultString string `xml:"faultstring"`
		} `xml:"Fault"`
	} `xml:"Body"`
}

ValidationSOAPResponse represents the SOAP response structure

type VoidedDocument added in v1.3.0

type VoidedDocument struct {
	DocumentTypeCode string // Document type code (01=Invoice, 03=Receipt, etc.)
	DocumentSeries   string // Document series (e.g., "F001", "B001")
	DocumentNumber   string // Document correlative number
	VoidedReason     string // Reason for voiding the document
}

VoidedDocument represents a document to be voided

func (*VoidedDocument) Validate added in v1.3.0

func (doc *VoidedDocument) Validate() error

Validate validates a single voided document

type VoidedDocumentsRequest added in v1.3.0

type VoidedDocumentsRequest struct {
	RUC           string           // Company RUC
	CompanyName   string           // Company name/reason social
	SeriesNumber  string           // Voided document series number (RA-YYYYMMDD-###)
	IssueDate     time.Time        // Issue date
	ReferenceDate time.Time        // Reference date (date of voided documents)
	Documents     []VoidedDocument // List of documents to void
	Description   string           // Description of the voiding communication
}

VoidedDocumentsRequest represents a voided documents communication request

func (*VoidedDocumentsRequest) Validate added in v1.3.0

func (req *VoidedDocumentsRequest) Validate() error

Validate validates the voided documents request

type VoidedDocumentsResponse added in v1.3.0

type VoidedDocumentsResponse struct {
	Success     bool
	Message     string
	Ticket      string // Ticket number for async status checking
	ResponseXML []byte
	Error       error
}

VoidedDocumentsResponse represents the response from SUNAT

Directories

Path Synopsis
Package main demonstrates the correct usage of the library following best practices The library provides data, users decide what to do with it
Package main demonstrates the correct usage of the library following best practices The library provides data, users decide what to do with it
Package signer provides XML digital signature functionality for SUNAT Peru
Package signer provides XML digital signature functionality for SUNAT Peru
Package utils provides certificate and utility functions for SUNAT XML signing
Package utils provides certificate and utility functions for SUNAT XML signing

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL