UNPKG

apacuana-sdk-web

Version:

Apacuana SDK for Web

932 lines (697 loc) 25.8 kB
# Apacuana SDK for Web ## 1. Introducción El **Apacuana SDK for Web** es una librería de cliente diseñada para integrar las funcionalidades de la plataforma Apacuana en cualquier aplicación web. Este SDK actúa como una capa de abstracción sobre `apacuana-sdk-core`, facilitando operaciones criptográficas complejas directamente en el navegador del cliente. Utiliza tecnologías web estándar como la **Web Crypto API** para la generación de claves y la firma de documentos, y **IndexedDB** para el almacenamiento seguro y persistente de material criptográfico (certificados y claves privadas) en el dispositivo del usuario. ### Tabla de Contenidos - [Instalación](#1-instalación) - [Importación](#2-importación) - [Configuración y conceptos clave](#3-configuración-y-conceptos-clave) - [Inicialización del SDK](#4-inicialización-del-sdk) - [Conceptos Clave](#conceptos-clave) - [Tipos de Integración](#tipos-de-integración) - [Acceso a funciones públicas/privadas](#acceso-a-funciones-públicasprivadas) - [Referencia de la API](#referencia-de-la-api) - [Métodos públicos](#métodos-públicos) - [getCertTypes](#getcerttypes) - [getCertRequerimentsByType](#getcertrequerimentsbytypeparams) - [createApacuanaUser](#createapacuanauseruserdata) - [Métodos privados](#métodos-privados) - [getCustomer](#getcustomer) - [generateCert](#generatecertparams) - [getCertStatus](#getcertstatus) - [addSigner](#addsignerparams) - [getDocsByCustomer](#getdocsbycustomerparams) - [signDocument](#signdocumentparams) - [uploadSignatureVariant](#uploadsignaturevariantparams) - [getSignatureVariant](#getsignaturevariant) - [deleteSignatureVariant](#deletesignaturevariant) - [startLivenessCheck](#startlivenesscheckcontainer) - [requestRevocation](#requestrevocationparams) - [getRevocationReasons](#getrevocationreasons) - [importCertificate](#importcertificateparams) - [exportCertificateInJSON](#exportcertificateinjsonparams) - [isCertificateInDevice](#iscertificateindevice) - [Manejo de Errores](#5-manejo-de-errores) --- ## Guía de Inicio Rápido Esta sección te muestra cómo comenzar a usar el SDK Web de Apacuana en tu proyecto, desde la instalación hasta la inicialización y primer uso. ### 1. Instalación Instala el SDK usando npm o yarn: ```bash npm install apacuana-sdk-web # o yarn add apacuana-sdk-web ``` ### 2. Importación Importa la instancia única y preconfigurada del SDK en tu proyecto: ```javascript import { apacuanaWeb } from "apacuana-sdk-web"; ``` ### 3. Configuración y conceptos clave Antes de inicializar el SDK, asegúrate de tener los datos de configuración proporcionados por Apacuana: - `apiUrl`: URL base de la API de Apacuana. - `secretKey`: Clave secreta de tu integración. - `apiKey`: API Key de tu integración. - `verificationId`: ID de verificación de tu cliente. - `customerId`: (Opcional) ID único del usuario/cliente. Necesario para funciones privadas. - `integrationType`: Tipo de integración (`ONBOARDING` recomendado). > **Nota:** Si inicializas el SDK sin `customerId`, solo tendrás acceso a funciones públicas. Para acceder a funciones privadas (como firma, gestión de certificados, etc.), debes incluir `customerId` en la configuración. ### 4. Inicialización del SDK Inicializa el SDK una sola vez al cargar tu aplicación. Si la inicialización es exitosa, podrás usar todos los métodos públicos y privados según tu configuración. ```javascript import { apacuanaWeb } from "apacuana-sdk-web"; const config = { apiUrl: "https://api.tu-dominio.com", secretKey: "TU_SECRET_KEY", apiKey: "TU_API_KEY", verificationId: "ID_DE_VERIFICACION", customerId: "ID_DEL_CLIENTE", // Opcional, pero necesario para funciones privadas integrationType: "ONBOARDING", }; async function initializeApp() { try { const isInitialized = await apacuanaWeb.init(config); if (isInitialized) { console.log("El SDK Web de Apacuana se ha inicializado correctamente."); } } catch (error) { if ( error.name === "ApacuanaWebError" || error.name === "ApacuanaAPIError" ) { console.error("Error al inicializar el SDK:", error.message); } else { console.error("Error inesperado:", error); } } } initializeApp(); ``` ## Conceptos Clave ### Tipos de Integración El SDK soporta dos tipos de integración (`integrationType`) que determinan cómo se interactúa con la plataforma de Apacuana: - **`ONBOARDING`**: En este modo, Apacuana gestiona la mayor parte del proceso, como el registro de usuarios y la generación de certificados. Es el modo recomendado y soportado para la mayoría de las integraciones. - **`ONPREMISE`**: Este modo de integración no está soportado actualmente y se reserva para uso futuro. La mayoría de las operaciones del SDK lanzarán un error `NOT_IMPLEMENTED` si se utiliza este tipo. La elección del `integrationType` en la `init` es fundamental, ya que afecta a la disponibilidad y el comportamiento de muchos de los métodos del SDK. ### Acceso a funciones públicas/privadas El SDK puede inicializarse sin el parámetro `customerId`, lo que permite el acceso únicamente a las funciones públicas. Para acceder a las funciones privadas, es necesario inicializar el SDK incluyendo el `customerId` en la configuración. **Funciones públicas disponibles sin `customerId`:** - `getCertTypes()` - `getCertRequerimentsByType(params)` - `createApacuanaUser(userData)` **Funciones privadas (requieren `customerId`):** - `getCustomer()` - `generateCert(encryptedCSR)` - `getCertStatus(isCertificateInDevice)` - `addSigner(signerData)` - `getDocsByCustomer(params)` - `signDocument(signData)` - `uploadSignatureVariant(data)` - `getSignatureVariant()` - `deleteSignatureVariant()` - `startLivenessCheck()` - `requestRevocation(params)` - `getRevocationReasons()` - `importCertificate()` - `exportCertificateInJSON()` - `isCertificateInDevice()` El SDK valida automáticamente si tienes acceso a cada función según la configuración actual, y lanzará un error si intentas acceder a una función privada sin haber inicializado correctamente con el `customerId`. ## Referencia de la API Todos los métodos deben ser llamados a través de la instancia `apacuanaWeb`. ## Métodos públicos ### `getCertTypes()` Obtiene los tipos de certificados disponibles. #### Comportamiento - Solo disponible para `integrationType: ONBOARDING`. Si se usa con `ONPREMISE`, lanzará un error `NOT_IMPLEMENTED`. - Devuelve una instancia de `ApacuanaSuccess` con la propiedad `types`, que es un array de tipos de certificado. #### Respuesta ```js { success: true, data: { types: [ { /* tipo de certificado */ }, // ...otros tipos de certificado ] } } ``` #### Ejemplo: ```javascript try { const response = await apacuanaWeb.getCertTypes(); console.log("Tipos de certificados:", response.data.types); } catch (error) { console.error("Error al obtener los tipos de certificado:", error.message); } ``` ### `getCertRequerimentsByType(params)` Obtiene los requisitos para un tipo de certificado y usuario. #### Parámetros - `params`: Objeto con la propiedad obligatoria: - `type` (Number): El tipo de certificado. #### Comportamiento - Solo disponible para `integrationType: ONBOARDING`. Si se usa con `ONPREMISE`, lanzará un error `NOT_IMPLEMENTED`. - Devuelve una instancia de `ApacuanaSuccess` con los requisitos solicitados. #### Respuesta ```js { success: true, data: { ... } } ``` #### Ejemplo: ```javascript try { const response = await apacuanaWeb.getRequerimentsByTypeUser({ type: 1 }); console.log("Requisitos:", response.data.requirements); } catch (error) { console.error("Error al obtener los requisitos:", error.message); } ``` ### `createApacuanaUser(userData)` Crea un nuevo usuario en la plataforma de Apacuana. Este método puede llamarse varias veces para ir completando la información de forma parcial; no es necesario enviar todos los datos en una sola llamada. Sin embargo, en cada actualización es obligatorio enviar el número de documento de identidad (`kinddoc+doc`). El registro inicial debe incluir el documento de identidad. Los documentos requeridos para el usuario se obtienen previamente usando el método `getRequerimentsByTypeUser` y deben enviarse bajo la estructura `{ file-ID: File }`, donde cada clave corresponde al identificador del documento y el valor es el archivo correspondiente. > **Nota importante:** El objeto retornado en la respuesta tendrá un atributo `id`, el cual corresponde con el `customerId` de Apacuana. Este valor debe ser asociado y almacenado en tu sistema para cada usuario. Cuando tu usuario esté autenticado en tu aplicación y desee conectarse a Apacuana, deberá usar este `id` como `customerId` en la configuración del SDK. Este valor se obtiene luego de solicitar un certificado por primera vez. El objeto completo de usuario que puede acompañar la solicitud es: ```js { email: "usuario@correo.com", typeuser: 1, name: "Nombre", lastname: "Apellido", kinddoc: "V", doc: 12345678, birthdate: "1990-01-01", kindrif: "V", gender: "M", rif: 12345678, phone: 4121234567, kindphone: "0424", state: "Estado", municipality: "Municipio", parish: "Parroquia", postalcode: "1010", address: "Dirección", fiscaladdress: "Dirección fiscal", fiscalkindphone: "0424", fiscalphone: 4121234567, occupation: "Ocupación", degree: "Título", university: "Universidad", graduationyear: "2010", collegiatenumber: "12345", collegiateyear: "2011", companyname: "Empresa", companykindrif: "J", companyrif: "J12345678", companystate: "Estado", companymunicipality: "Municipio", companyparish: "Parroquia", companyaddress: "Dirección empresa", companykindphone: "0212", companyphone: "2121234567", companypostalcode: "1010", companywebpage: "https://empresa.com", companycommercialregister: "Registro comercial", companyregisterdate: "2015-01-01", companyregisternumber: "123456", companyconstitutiondate: "2015-01-01", companypublishdate: "2015-01-01", companyconstitutiondecree: "Decreto", companynumberdecree: "123", positionprivate: "Cargo privado", departmentprivate: "Departamento privado", authorizedprivate: "Autorizado privado", functionsprivate: "Funciones privado", publishprivate: "2015-01-01", issuedateprivate: "2015-01-01", kindphoneprivate: "0424", phoneprivate: 4121234567, positionpublic: "Cargo público", departmentpublic: "Departamento público", authorizedpublic: "Autorizado público", functionspublic: "Funciones público", publishpublic: "2015-01-01", issuedatepublic: "2015-01-01", kindphonepublic: "0424", phonepublic: 4121234567, companyid: "uuid-empresa" } ``` **Ejemplo:** ```javascript try { const userData = { usr: "usuario@correo.com", pwd: "contraseñaSegura123", kinddoc: "V", doc: "12345678", // ...otros campos opcionales files: { "file-1": file1, // Instancia de File "file-2": file2, // ...otros documentos según los requerimientos }, }; const response = await apacuanaWeb.createApacuanaUser(userData); console.log("Usuario creado:", response.data); } catch (error) { console.error("Error al crear el usuario:", error.message); } ``` #### Comportamiento - Permite crear o actualizar usuarios de forma parcial o total. - Los documentos requeridos se obtienen previamente usando `getCertRequerimentsByType`. - Devuelve una instancia de `ApacuanaSuccess` con la información del usuario creado o actualizado. --- ## Métodos privados ### `getCustomer()` Obtiene los datos del cliente autenticado. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Devuelve una instancia de `ApacuanaSuccess` con los datos del usuario y el token de autenticación. **Ejemplo de uso:** ```js const result = await apacuanaWeb.getCustomer(); // result.data contendrá los datos del usuario y el token ``` ### `generateCert(params)` Genera un nuevo certificado digital y lo almacena localmente. #### Parámetros: - `params`: (String) Contrase;a unica para generar y posteriormente utilizar el certificado #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Genera un par de claves, crea una CSR, la envía al servidor y almacena el certificado y la clave privada cifrada en el dispositivo. #### Respuesta ```js { success: true, data: { ... } } ``` --- ### `getCertStatus()` Verifica el estado del certificado del usuario. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Devuelve el estado actual del certificado, incluyendo texto y descripción. #### Respuesta ```js { success: true, data: { status: { text: "...", descriptionText: "..." } } } ``` Los posibles valores de `text` incluyen: - "Por verificar" - "En revisión" - "Por generar" - "Vigente" - "Por revocar" - "Revocado" - "Verificado" - "Certificado expirado" #### Ejemplo: ```javascript try { const response = await apacuanaWeb.getCertStatus(); console.log("Estado del certificado:", response.data.status.text); if (response.data.status.descriptionText) { console.log("Descripción:", response.data.status.descriptionText); } } catch (error) { console.error("Error al obtener el estado del certificado:", error.message); } ``` --- ### `addSigner(params)` Añade un firmante a un documento. El comportamiento y los campos obligatorios dependen del `integrationType` configurado durante la inicialización. #### Parámetros: - **`params`**: Objeto con los datos del firmante y el documento. - `name` (String, **obligatorio**): Nombre del documento. - `document` (File, **opcional**): El archivo del documento a firmar (ej. un PDF). No puede coexistir con `reference`. - `reference` (String, **opcional**): Referencia única para un documento ya existente en la plataforma. No puede coexistir con `document`. - `typedoc` (String, **obligatorio**): Tipo de documento de identidad del firmante. Valores permitidos: "V", "P", "E". - `doc` (String, **obligatorio**): Número de documento de identidad del firmante. - `signature` (Array, **obligatorio**): Un array de objetos que definen la posición de la firma. Debe contener al menos un objeto con: - `page` (Number, **obligatorio**): Página donde se estampará la firma (entero positivo). - `x` (Number, **obligatorio**): Coordenada X (de 0 a 1, porcentual respecto al ancho del PDF). - `y` (Number, **obligatorio**): Coordenada Y (de 0 a 1, porcentual respecto al alto del PDF). **Notas sobre `document` y `reference`:** - Solo uno de estos parámetros debe ser enviado. Si el cliente tiene integración con el gestor documental de Apacuana, se debe usar `reference` para referenciar el documento existente en la plataforma. - Si no existe integración documental, se debe enviar el archivo `document` (File). Este archivo será posteriormente solicitado para la firma del documento luego de ser asignado. **Notas sobre posicionamiento:** - Las coordenadas `x` e `y` son porcentuales y van de 0 a 1. - El origen (0,0) está en la esquina superior izquierda del PDF. - Ejemplos de posicionamiento: - Esquina superior izquierda: `{ x: 0, y: 0 }` - Esquina superior derecha: `{ x: 1, y: 0 }` - Esquina inferior izquierda: `{ x: 0, y: 1 }` - Centro de la página: `{ x: 0.5, y: 0.5 }` #### Ejemplo: ```javascript try { const signer = { name: "Contrato", document: documentFile, // Instancia de File typedoc: "V", doc: "12345678", signature: [ { page: 1, x: 0, y: 0 }, // Esquina superior izquierda { page: 1, x: 1, y: 0 }, // Esquina superior derecha { page: 1, x: 0, y: 1 }, // Esquina inferior izquierda { page: 1, x: 0.5, y: 0.5 }, // Centro de la página ], }; const response = await apacuana.addSigner(signer); console.log("Firmante añadido:", response.data); } catch (error) { console.error("Error al añadir firmante:", error.message); } ``` ### `getDocsByCustomer(params)` Obtiene la lista de documentos asociados al usuario. #### Parámetros - **`params`**: Objeto con parámetros de paginación y filtros. - `page` (Number, **obligatorio**) - `size` (Number, **obligatorio**) - `status` (Number, **opcional**) - (`status`) 0 pendiente, 1 = completado/firmado, -1 rechazado #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Permite filtrar y paginar los documentos asociados al usuario. #### Respuesta ```js { success: true, data: { /* lista de documentos */ } } ``` **Ejemplo:** ```javascript try { const params = { page: 1, size: 10, status: 0, // Estado del documento }; const response = await apacuanaWeb.getDocsByCustomer(params); console.log("Documentos filtrados:", response.data); } catch (error) { console.error("Error al obtener los documentos:", error.message); } ``` **Notas:** - Si no se especifican filtros, se devolverán todos los documentos paginados. --- ### `signDocument(params)` Firma un documento usando el certificado y clave privada local. #### Parámetros El parámetro `params` debe incluir: - `signature` (Object, obligatorio): - `id` (String): ID de la firma. - `positions` (Array): Posiciones de la firma en el documento. - `document` (File, opcional): Archivo del documento a firmar. **Importante:** - El objeto `signature` debe ser obtenido directamente del array de documentos devuelto por el método `getDocsByCustomer`, específicamente del atributo `signaturedata` de dicho documento. - Si en el método `addSigner` se utilizó el parámetro `reference`, no es necesario incluir el archivo `document` al firmar, ya que el documento está referenciado en la plataforma. - Si en `addSigner` se utilizó el parámetro `document` (archivo), será necesario proporcionar nuevamente el archivo en este método para completar la firma. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Recupera el certificado y clave privada, obtiene el digest, firma localmente y envía la firma al servidor. #### Respuesta ```js { success: true, data: { /* información del documento firmado */ } } ``` #### Ejemplo: ```javascript // Caso con documento referenciado const result = await apacuana.signDocument({ signature: { id: "sig-123", positions: [{ page: 1, x: 0.5, y: 0.5 }] }, // No se requiere document }); // Caso con documento por archivo const result = await apacuana.signDocument({ signature: { id: "sig-123", positions: [{ page: 1, x: 0.5, y: 0.5 }] }, document: documentFile, // Instancia de File }); // result.data contendrá la información del documento firmado ``` ### `uploadSignatureVariant(params)` Sube una imagen de variante de firma para el usuario autenticado. #### Parámetros El parámetro `params` debe incluir: - `file` (File, obligatorio): Archivo de imagen en formato PNG (`image/png`). **Notas importantes:** - El archivo debe ser una instancia de `File` y tener el tipo MIME `image/png`. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Sube la imagen de la firma y la asocia al usuario. #### Respuesta ```js { success: true, data: { /* información de la variante subida */ } } ``` **Ejemplo:** ```javascript const imageFile = new File( [ /* datos */ ], "firma.png", { type: "image/png" } ); try { const response = await apacuanaWeb.uploadSignatureVariant({ file: imageFile, }); console.log(response.data); } catch (error) { console.error(error.message); } ``` --- ### `getSignatureVariant()` Obtiene la imagen de la variante de firma registrada. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Devuelve la imagen en Base64 o información asociada. #### Respuesta ```js { success: true, data: { /* imagen de la firma en Base64 */ } } ``` #### Ejemplo ```javascript try { const response = await apacuanaWeb.getSignatureVariant(); console.log(response.data); } catch (error) { console.error(error.message); } ``` --- ### `deleteSignatureVariant()` Elimina la variante de firma almacenada. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Elimina la variante de firma si existe. #### Respuesta ```js { success: true, data: { /* información del estado tras eliminar la variante */ } } ``` #### Ejemplo ```javascript try { const response = await apacuanaWeb.deleteSignatureVariant(); console.log(response.data); } catch (error) { console.error(error.message); } --- ``` ### `startLivenessCheck(container?)` Inicia una prueba de vida (liveness check) para el usuario. #### Parámetros - `container` (opcional): Elemento HTML donde se renderiza la prueba. Si se omite, se muestra en un modal. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Crea una sesión de prueba de vida y muestra la interfaz correspondiente. #### Respuesta ```js { success: true, data: { /* resultado de la prueba de vida */ } } ``` #### Ejemplo: ```javascript try { const response = await apacuanaWeb.startLivenesCheck(); console.log("Resultado de fe de vida:", response.data); } catch (error) { console.error("Error al procesar la fe de vida:", error.message); } ``` --- ### `requestRevocation(params)` Solicita la revocación de un certificado. #### Parámetros - `params`: Objeto con la propiedad obligatoria: - `reasonCode` (Number): ID de la razón de revocación. > **Nota importante:** el atributo reasonCode debe provenir de la lista de razones de revocacion, la cual obtenemos con el metodo: getRevocationReasons() #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Permite enviar la solicitud de revocación y documentos asociados. #### Respuesta ```js { success: true, data: { /* información de la revocación */ } } ``` #### Ejemplo: ```javascript try { const response = await apacuanaWeb.requestRevocation({ reasonCode: 1 }); console.log("Solicitud de revocación enviada:", response.data); } catch (error) { console.error("Error al solicitar la revocación:", error.message); } ``` --- ### `getRevocationReasons()` Obtiene la lista de razones para la revocación de certificados. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Devuelve un array de razones de revocación proporcionadas por la API. #### Respuesta ```js { success: true, data: { reasons: [ /* array de razones de revocación */ ] } } ``` #### Ejemplo: ```javascript try { const response = await apacuanaWeb.getRevocationReasons(); console.log("Razones de revocación:", response.data.reasons); } catch (error) { console.error("Error al obtener las razones de revocación:", error.message); } ``` --- ### `importCertificate(params)` Importa un certificado previamente exportado. #### Parámetros - `params`: Objeto con el archivo y el PIN para importar el certificado. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Permite importar un certificado y clave privada previamente exportados. #### Respuesta ```js { success: true, data: { /* información del proceso de importación */ } } ``` --- ### `exportCertificateInJSON(params)` Exporta el certificado y claves del usuario a un archivo JSON seguro. #### Parámetros - `params`: Objeto con el PIN y nombre de archivo para exportar el certificado. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Exporta el certificado y clave privada cifrada a un archivo JSON con sello de integridad. #### Respuesta ```js { success: true, data: { isExport: true } } ``` --- ### `isCertificateInDevice()` Verifica si existe un certificado almacenado localmente para el usuario. #### Comportamiento - Solo disponible si el SDK fue inicializado con `customerId`. - Realiza una comprobación rápida en el almacenamiento local. #### Respuesta ```js { success: true, data: { isExist: true // o false } } ``` #### Ejemplo: ```javascript try { const response = await apacuanaWeb.isCertificateInDevice(); console.log( "Certificado existente en el dispositivo:", response.data.isExist ); } catch (error) { console.error( "Error al verificar si existe el certificado en el dispositivo:", error.message ); } ``` --- ## 5. Manejo de Errores El SDK utiliza un sistema de errores personalizado para facilitar la depuración. - **`ApacuanaWebError`**: Errores generados por el SDK web. Suelen estar relacionados con el estado de la aplicación (ej. SDK no inicializado), validaciones (ej. PIN vacío) o problemas con IndexedDB. - **`ApacuanaAPIError`**: Errores generados por `apacuana-sdk-core`. Estos errores se relanzan directamente y suelen estar relacionados con problemas de comunicación con la API de Apacuana (ej. `apiKey` inválida, errores del servidor). Todos los errores lanzados por el SDK pueden ser capturados con un bloque `try...catch`. ### `ApacuanaWebErrorCode` Los errores de tipo `ApacuanaWebError` incluyen un código para identificar la causa raíz: - `NOT_INITIALIZED`: Se intentó usar un método antes de llamar a `init()`. - `VALIDATION_ERROR`: Un parámetro de entrada no pasó la validación (ej. `pin` vacío). - `NOT_FOUND`: No se encontró un recurso esperado (ej. la clave privada en IndexedDB). - `UNKNOWN_ERROR`: Un error inesperado ocurrió dentro del SDK. ``` ```