RUC, DNI y tipo de cambio
Consulta de RUC, domicilio fiscal, establecimientos anexos, DNI y tipo de cambio.
lookupTaxpayer()lookupPerson()getExchangeRate()NestJS + TypeScript · v2.0.0
SDK de integración independiente que organiza las consultas SUNAT, la emisión de comprobantes y las guías de remisión en interfaces TypeScript listas para NestJS, sin que tu aplicación tenga que hablar HTTP directamente con el proveedor.
Primeros pasos
El SDK se distribuye como paquete scoped y depende de @nestjs/axios para realizar las peticiones HTTP hacia el servicio contratado.
npm install @angelitosystems/sdk-visioner7
npm install @nestjs/axios axios reflect-metadata rxjs
Si el proyecto vive dentro de un monorepo o como código interno, también puede integrarse como librería privada, por ejemplo en libs/sdk-visioner7/, o distribuirse mediante un registro privado de paquetes.
Primeros pasos
@nestjs/axios, axios, reflect-metadata y rxjs como dependencias del proyecto.Configuración
Usa forRoot para una configuración directa, o forRootAsync cuando las credenciales provienen de variables de entorno o de un ConfigService. El módulo puede registrarse como global para evitar importaciones repetidas donde se use SDKVisioner7Service.
import { Module } from '@nestjs/common';
import { SDKVisioner7Module } from '@angelitosystems/sdk-visioner7';
@Module({
imports: [
SDKVisioner7Module.forRoot({
baseUrl: 'https://visioner7-api.com/api',
authToken: process.env.SDK_VISIONER7_AUTH_TOKEN,
businessToken: process.env.SDK_VISIONER7_BUSINESS_TOKEN,
timeout: 15000,
}),
],
})
export class AppModule {}
| Opción | Descripción |
|---|---|
| baseUrl | URL base del servicio contratado. |
| authToken | Token de autenticación proporcionado para el servicio. |
| businessToken | Token utilizado por determinadas operaciones. |
| timeout | Tiempo máximo de espera de las solicitudes HTTP. |
El valor de baseUrl debe corresponder al entorno y servicio que tenga habilitado el cliente.
Recomendado cuando la configuración proviene de variables de entorno o ConfigService.
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SDKVisioner7Module } from '@angelitosystems/sdk-visioner7';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
SDKVisioner7Module.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
baseUrl: config.get<string>('SDK_VISIONER7_BASE_URL'),
authToken: config.get<string>('SDK_VISIONER7_AUTH_TOKEN'),
businessToken: config.get<string>('SDK_VISIONER7_BUSINESS_TOKEN'),
timeout: 15000,
}),
}),
],
})
export class AppModule {}
Configuración
Nunca almacenes credenciales reales directamente en el código fuente. Usa variables de entorno, un secret manager o los secretos administrados por tu proveedor de infraestructura.
SDK_VISIONER7_BASE_URL=https://visioner7-api.com/api
SDK_VISIONER7_AUTH_TOKEN=your_token_here
SDK_VISIONER7_BUSINESS_TOKEN=your_business_token_here
Uso
Una vez registrado el módulo, SDKVisioner7Service queda disponible para cualquier servicio de dominio o controlador de NestJS.
import { Injectable } from '@nestjs/common';
import { SDKVisioner7Service } from '@angelitosystems/sdk-visioner7';
@Injectable()
export class FacturacionService {
constructor(private readonly sdkVisioner7Service: SDKVisioner7Service) {}
async validarCliente(ruc: string) {
const response = await this.sdkVisioner7Service.lookupTaxpayer(ruc);
return response.taxpayer;
}
}
Referencia de API
Cada grupo se identifica con un color a lo largo de toda la guía, para que sea fácil ubicar a qué frente pertenece cada método.
Consulta de RUC, domicilio fiscal, establecimientos anexos, DNI y tipo de cambio.
lookupTaxpayer()lookupPerson()getExchangeRate()Emisión de guías por tipo de remitente o transportista, y consulta de estado mediante ticket.
issueRemittanceGuide()getRemittanceGuideTicketStatus()Generación de comprobantes de pago electrónicos, al contado o al crédito.
generateVoucher()Realiza una consulta de RUC mediante el servicio contratado. La aplicación debe contar con las credenciales y permisos correspondientes para utilizar esta operación.
const response = await sdkVisioner7Service.lookupTaxpayer('20611187719');
console.log(response.taxpayer.businessName);
Consulta el domicilio fiscal o los establecimientos anexos de un RUC. El tipo de consulta acepta el enum EstablishmentQueryType o su valor numérico equivalente, por ejemplo EstablishmentQueryType.FISCAL_ADDRESS o 1.
const domicilio = await sdkVisioner7Service.lookupEstablishments(
'20611187719',
EstablishmentQueryType.FISCAL_ADDRESS,
);
Obtiene los datos asociados a un DNI. El uso de información personal debe realizarse de acuerdo con la normativa aplicable y con una finalidad legítima.
const persona = await sdkVisioner7Service.lookupPerson('10292315');
console.log(persona.person.givenNames);
Devuelve el tipo de cambio de compra y venta para el año y mes indicados. Cuando corresponda, el SDK utiliza el businessToken configurado en el módulo.
const response = await sdkVisioner7Service.getExchangeRate({ year: 2025, month: 7 });
const compra = response.data.find(item => item.side === 'C')?.value;
const venta = response.data.find(item => item.side === 'V')?.value;
Emite una guía de remisión con los datos del documento, el emisor y el detalle de ítems transportados. Los campos requeridos dependen del tipo de guía y de las especificaciones del servicio contratado.
Los tres tipos de guía (remitente público, privado o transportista) se especifican combinando los campos correspondientes de RemittanceGuideRequest.
const resultado = await sdkVisioner7Service.issueRemittanceGuide({
processType: '1',
companyDocumentNumber: 'YOUR_RUC',
companySolUsername: 'YOUR_SOL_USER',
companySolPassword: 'YOUR_SOL_PASSWORD',
signaturePassword: 'YOUR_SIGNATURE_PASSWORD',
idToken: 'YOUR_ID_TOKEN',
tokenKey: 'YOUR_TOKEN_KEY',
documentTypeCode: '09',
documentNumber: 'T001-00000002',
documentDate: '2025-08-10',
companyDocumentType: '6',
companyBusinessName: 'EMPRESA DE EJEMPLO S.A.C.',
recipientDocumentType: '6',
recipientDocumentNumber: 'YOUR_CLIENT_RUC',
recipientBusinessName: 'CLIENTE DE EJEMPLO S.A.C.',
shipmentItem: '1',
transferReasonCode: '01',
transferReasonDescription: 'VENTA',
grossWeightUnit: 'KGM',
grossWeight: '10.00',
transportModalityCode: '01',
startDate: '2025-08-10',
originUbigeoCode: '150101',
originAddress: 'AV. EJEMPLO 123',
destinationUbigeoCode: '150101',
destinationAddress: 'AV. DESTINO 456',
items: [
{ item: '1', unitOfMeasure: 'NIU', quantity: '1', orderItem: '1', description: 'PRODUCTO DE EJEMPLO', code: 'PROD001' },
],
});
// los valores mostrados son ilustrativos: sustitúyelos por los de tu propio entorno
Consulta el estado de una guía a partir del ticket devuelto en la emisión.
const estado = await sdkVisioner7Service.getRemittanceGuideTicketStatus({
ticket: 'YOUR_TICKET',
companyDocumentNumber: 'YOUR_RUC',
companySolUsername: 'YOUR_SOL_USER',
companySolPassword: 'YOUR_SOL_PASSWORD',
idToken: 'YOUR_ID_TOKEN',
tokenKey: 'YOUR_TOKEN_KEY',
documentTypeCode: '31',
documentNumber: 'V001-00000001',
processType: '1',
});
Genera un comprobante de pago electrónico. La modalidad de pago se determina mediante la información enviada en paymentTerms (contado o crédito con cuotas).
La respuesta expone sunatCode, sunatMessage, file, cdrHash y el bloque cdrData.
const factura = await sdkVisioner7Service.generateVoucher({
operationType: '0101',
totalTaxableAmount: '305.08',
subtotal: '305.08',
igvPercentage: '18.00',
totalIgv: '54.92',
total: '360.00',
voucherTypeCode: '01',
currencyCode: 'PEN',
voucherNumber: 'F001-00000001',
issueDate: '2025-08-10',
totalInWords: 'TRESCIENTOS SESENTA CON 00/100 SOLES',
clientDocumentNumber: 'YOUR_CLIENT_DOCUMENT',
clientBusinessName: 'CLIENTE DE EJEMPLO',
clientDocumentType: '6',
companyDocumentNumber: 'YOUR_RUC',
companyDocumentType: '6',
companyBusinessName: 'EMPRESA DE EJEMPLO S.A.C.',
companySolUsername: 'YOUR_SOL_USER',
companySolPassword: 'YOUR_SOL_PASSWORD',
certificatePassword: 'YOUR_CERT_PASSWORD',
signaturePassword: 'YOUR_SIGNATURE_PASSWORD',
processType: '1',
paymentTerms: [{ paymentFormCode: 'Contado', amount: '360.00' }],
items: [{
item: '1', unitOfMeasure: 'NIU', quantity: '1.00',
price: '360.00', amount: '305.08', igv: '54.92',
code: 'PROD001', description: 'PRODUCTO DE EJEMPLO',
priceTypeCode: '01', igvPercentage: '18.00', isc: '0.00',
operationTypeCode: '10', priceWithoutIgv: '305.08',
icbperFlag: 0, icbperTaxAmount: '0.00', icbperTotalAmount: '0.00',
}],
});
console.log(factura.sunatMessage, factura.file);
Operación
El SDK centraliza los errores mediante SDKVisioner7ApiException, que extiende HttpException de NestJS, para integrarse con los ExceptionFilter globales de tu aplicación.
import { SDKVisioner7ApiException } from '@angelitosystems/sdk-visioner7';
try {
await sdkVisioner7Service.lookupTaxpayer('00000000000');
} catch (error) {
if (error instanceof SDKVisioner7ApiException) {
console.error(error.endpoint, error.providerResponse);
}
throw error;
}
Operación
El frontend no debe comunicarse directamente con el servicio externo usando credenciales privadas. Las credenciales permanecen exclusivamente en el backend, detrás de SDKVisioner7Service.
Los distintos servicios de dominio de tu backend hablan con SDKVisioner7Service; solo esa capa conoce el servicio externo.
Seguridad
No expongas tokens SOL ni credenciales en frontend, JavaScript de navegador, apps móviles sin protección o repositorios públicos. Usa variables de entorno o un secret manager.
.env
.env.local
.env.production
Seguridad
Las operaciones de consulta y emisión pueden involucrar información empresarial o datos personales. La aplicación que utilice este SDK es responsable de:
El SDK no pretende sustituir las obligaciones legales, regulatorias o contractuales del sistema que lo utilice.
Referencia
El servicio integra con conceptos tributarios y logísticos de Perú. Esta sección explica cada término que aparece en el SDK y en los payloads del proveedor.
| Término | Significado |
|---|---|
| SUNAT | Superintendencia Nacional de Aduanas y de Administración Tributaria: entidad del Estado peruano que administra impuestos y valida los comprobantes electrónicos. |
| RUC | Registro Único de Contribuyentes: número de 11 dígitos que identifica a una empresa o persona con negocio ante SUNAT. |
| DNI | Documento Nacional de Identidad: documento de identidad de personas naturales peruanas (8 dígitos). |
| CPE | Comprobante de Pago Electrónico: factura o boleta electrónica enviada a SUNAT para su validación antes de considerarse emitida. |
| Factura / Boleta | Tipos de comprobante. Códigos SUNAT: 01 = factura, 03 = boleta (campo voucherTypeCode). |
| Guía de Remisión (GRE) | Documento electrónico que sustenta el traslado de bienes (campo documentTypeCode: '09'). |
| Remitente público / privado / transportista | Modalidades de guía de remisión según quién traslada los bienes. Se definen por los campos incluidos en el payload. |
| Ticket | Código que devuelve el proveedor al emitir una guía; permite consultar después el resultado de la validación (getRemittanceGuideTicketStatus). |
| CDR | Constancia de Recepción: respuesta oficial de SUNAT con el resultado de la validación del comprobante. responseCode/sunatCode en "0" significa aceptado. |
| Hash CDR / CPE | Resumen criptográfico (huella) del XML del comprobante o de la constancia. |
| XML / UBL | Formato estándar en el que se genera y firma el comprobante electrónico. |
| IGV | Impuesto General a las Ventas: IVA peruano (18% habitual). Campos igv, igvPercentage, totalIgv. |
| ISC | Impuesto Selectivo al Consumo: aplica a ciertos bienes (bebidas, combustibles, etc.). Campos isc, totalIsc. |
| ICBPER | Impuesto a la Bolsa Plástica de un solo uso. En el proveedor aparece como IMPUESTO_BP/IMPORTE_BP y el flag FLG_ICBPER (mapeado a icbperFlag, icbperTaxAmount, icbperTotalAmount). |
| Gravado | Operación afecta al IGV (totalTaxableAmount). |
| Exonerado | Operación no afecta al IGV por ley (totalExemptAmount). |
| Inafecto | Operación no sujeta al IGV por naturaleza (totalUntaxedAmount). |
| Gratuito | Entregas gratuitas (totalFreeAmount). |
| Detracción | Retención de un porcentaje del pago a una cuenta del Banco de la Nación para ciertos bienes/servicios (campos detractionCode, detractionPercentage, detractionsTotal). |
| Percepción | Cobro anticipado del IGV en la venta (campos perceptions*). |
| Retención | Retención del IGV al proveedor (campos retentions*). |
| Contado / Crédito | Formas de pago del CPE. En el proveedor: COD_FORMA_PAGO = 'Contado' o 'Credito' + cuotas Cuota001, Cuota002, ... (mapeado a paymentTerms). |
| Tipo de cambio | Precio de referencia del dólar (USD) publicado por SUNAT, con valores de compra (side: 'C') y venta (side: 'V'). |
| Ubigeo | Código geográfico oficial (departamento / provincia / distrito) usado en direcciones. |
| Usuario SOL / Clave SOL | Credenciales del portal de SUNAT con las que se firma y envía el comprobante (companySolUsername, companySolPassword). |
| Certificado digital / firma | Certificado con el que se firma el XML del comprobante (signaturePassword, certificatePassword). |
| Habido / condición de domicilio | Condición del contribuyente frente a SUNAT (ubicable o no). Campos statusCode y presenceCode en el lookup de RUC. |
| Establecimientos anexos | Sucursales o locales adicionales declarados por un contribuyente además de su domicilio fiscal. |
Tipo de proceso (processType) | Modo de emisión según el proveedor: producción o beta ('1' / '2'). |
| MTC | Ministerio de Transportes y Comunicaciones: registros de vehículos y conductores usados en guías transportista (campos *MtcRegistrationId). |
| NIU / KGM | Unidades de medida: NIU = unidades, KGM = kilogramos (campos unitOfMeasure, grossWeightUnit). |
| PEN / USD | Códigos de moneda ISO: sol peruano y dólar estadounidense (campo currencyCode). |
Referencia
Desde la versión 2.0.0 la API pública del SDK (métodos, clases e interfaces) está nombrada en inglés, y el SDK traduce internamente los payloads hacia el formato del proveedor (capa de mapping/). Los alias antiguos (SunatModule, consultarRuc, etc.) fueron eliminados.
| v1 (anterior) | v2 (actual) |
|---|---|
| SunatModule | SDKVisioner7Module |
| SunatService | SDKVisioner7Service |
| SunatApiException | SDKVisioner7ApiException |
| consultarRuc() | lookupTaxpayer() |
| consultarLocalesEstablecimientos() | lookupEstablishments() |
| consultarDni() | lookupPerson() |
| obtenerTipoCambio() | getExchangeRate() |
| emitirGuiaRemision() | issueRemittanceGuide() |
| consultarTicketGuiaRemision() | getRemittanceGuideTicketStatus() |
| generarCpe() | generateVoucher() |
| TipoConsultaLocal | EstablishmentQueryType |
| SUNAT_* (variables de entorno) | SDK_VISIONER7_* |
Los payloads y respuestas también llegan tipados en inglés (por ejemplo response.taxpayer.businessName en vez de response.comprobante.desRazonSocial).
Proyecto
Compilar con npm run build genera los archivos JavaScript y las declaraciones TypeScript en dist/.
La carpeta mapping/ traduce entre la API pública del SDK (en inglés) y el formato que espera el proveedor (campos como txtTOTAL, NRO_DOCUMENTO_EMPRESA, etc.).
La carpeta example/ contiene una integración de referencia completa, registrando el módulo con forRootAsync a partir de ConfigService.
Proyecto
Este proyecto es una librería de integración independiente. No constituye una API propia de SUNAT ni un producto oficial de Visioner7, y no implica afiliación, asociación, patrocinio o representación por parte de Visioner7. Se limita a ofrecer una interfaz de software para integrar una aplicación con un servicio externo al que el usuario o cliente tenga acceso autorizado.
Responsabilidad del usuario de la librería
Descargo de responsabilidad
El desarrollador de esta librería no garantiza la disponibilidad permanente, exactitud, continuidad, tiempos de respuesta o modificaciones futuras del servicio externo. Cambios en endpoints, autenticación, formatos de respuesta, límites o funcionalidades por parte del proveedor pueden requerir actualizaciones del SDK. Usar este SDK no sustituye la revisión de la documentación, condiciones contractuales o requisitos técnicos del servicio externo.
La licencia debe definirse según la forma en que se distribuya la librería. Para uso privado en proyectos propios o de clientes, se recomienda mantener el repositorio privado y establecer por contrato las condiciones de uso, distribución y soporte.
Para conocer las condiciones, disponibilidad y características actuales del servicio externo, consulta directamente visioner7-api.com.