Componente OCR (ModelOCR)
El SDK permite la captura guiada y extracción automática de datos mediante reconocimiento óptico de caracteres (OCR) para identificaciones oficiales mexicanas (INE, Pasaporte, etc.) de forma ágil y segura en la plataforma iOS.
Al invocar el módulo OCR, el SDK guía al usuario paso a paso:
- Pantalla de Instrucciones: Recomendaciones visuales y de iluminación para maximizar la calidad de captura.
- Captura Guiada e Inteligente: Detección en tiempo real del anverso (frente) y, de ser requerido, del reverso del documento.
- Extracción y Validación: Envío y verificación automática con los servicios de Dicio, devolviendo el control a la aplicación anfitriona junto con las imágenes en Base64 y los datos extraídos estructurados en JSON.
Compatibilidad y Requisitos
Instalación mediante Swift Package Manager (SPM)
El SDK se distribuye a través de Swift Package Manager.
Sigue estos pasos para agregarlo a tu proyecto en Xcode:
Abre tu proyecto en Xcode.
Ve al menú superior y selecciona File > Add Package Dependencies... (o selecciona el proyecto en el navegador, ve a la pestaña Package Dependencies y presiona el botón
+).En la barra de búsqueda superior derecha, ingresa la URL del repositorio del Package:
Repositorio SPM
https://bitbucket.org/juarezsdco/dicioocr-packageConfigura la regla de versión Up to Next Major Version y presiona Add Package.
En la ventana emergente de selección de productos, marca DicioOCR y asegúrate de asignarlo al target de tu aplicación anfitriona (Host App).
Presiona Add Package para finalizar.
Requisitos Previos y Permisos
1. Permiso de Cámara en Info.plist
El SDK requiere acceso a la cámara del dispositivo para realizar el escaneo de documentos. Agrega la clave NSCameraUsageDescription en el archivo Info.plist de tu aplicación o en la sección Info del target:
Info.plist
<key>NSCameraUsageDescription</key>
<string>Se requiere acceso a la cámara para realizar la captura y validación de tu identificación oficial.</string>
2. Importación del Módulo
En los archivos Swift donde vayas a invocar el flujo OCR, importa el framework:
Import
import SwiftUI
import ModelOCRUI
Personalización de la Apariencia (DicioOCRUIConfig)
Para personalizar los colores de la interfaz, el texto de los botones y los logotipos institucionales, se proporciona la estructura DicioOCRUIConfig:
DicioOCRUIConfig
let ocrConfig = DicioOCRUIConfig(
loadLogo: "logoInstitucional", // Nombre del asset para pantalla de carga
assetLogo: "logoInstitucional", // Nombre del asset para branding en escáner
colorTitulo: "#4D21B2", // Color hexadecimal para títulos principales
colorSubTitulo: "#707070", // Color hexadecimal para subtítulos e instrucciones
colorTextoBtn: "#FFFFFF", // Color hexadecimal para el texto de los botones
colorFondoBtn: "#2B0877" // Color hexadecimal para el fondo de los botones
)
Detalle de Parámetros:
loadLogo(String): Nombre del recurso de imagen ubicado en elAssets.xcassetsde tu aplicación que se mostrará durante la verificación inicial y carga.assetLogo(String): Nombre del recurso de imagen enAssets.xcassetspara branding en la interfaz de escaneo.colorTitulo(String): Código de color hexadecimal (ej.#4D21B2) para los títulos de la interfaz.colorSubTitulo(String): Código de color hexadecimal (ej.#707070) para subtítulos e instrucciones.colorTextoBtn(String): Código de color hexadecimal (ej.#FFFFFF) para el texto dentro de los botones de acción.colorFondoBtn(String): Código de color hexadecimal (ej.#2B0877) para el fondo de los botones interactivos.
- Todos los colores deben especificarse en formato hexadecimal válido (
#RRGGBB). - Las imágenes asignadas a
loadLogoyassetLogodeben existir dentro del catálogo de assets (Assets.xcassets) del proyecto anfitrión.
Invocación de la Vista de Escaneo (DicioOCRVCUI)
La vista principal del componente es DicioOCRVCUI. Para presentarla, se requiere proporcionar el token de autenticación, la URL del servicio de validación de Dicio, la configuración visual y la instancia conformante del delegado DicioScanOCRDelegate.
Parámetros de Inicialización:
DicioOCRVCUI Init
DicioOCRVCUI(
token: "TOKEN_BEARER_PROPORCIONADO_POR_DICIO",
urlVerify: "https://api.devdicio.net:8444/v1/sec_dev_fintech_pagos_middleware",
config: ocrConfig,
delegateDicioOCR: self
)
token: Token Bearer de autorización generado a través del backend de Dicio.urlVerify: Endpoint del servicio Dicio encargado de la verificación de credenciales y provisión de licencias dinámicas.config: Instancia deDicioOCRUIConfigcon el esquema de colores y logos.delegateDicioOCR: Objeto que implementa el protocoloDicioScanOCRDelegatepara recibir callbacks y resultados.
Implementación del Protocolo DicioScanOCRDelegate
El protocolo DicioScanOCRDelegate maneja la recepción de imágenes, la respuesta de datos extraídos y el control de cierre de la pantalla.
Protocolo DicioScanOCRDelegate
public protocol DicioScanOCRDelegate {
func imagesID(userIDPic: String, userIDFront: String, userIDBack: String)
func finishOCRView()
func ocrDicioResults(ocr: String, isSuccessfull: Bool, info: String, tipoID: String)
}
Métodos del Delegado:
1. imagesID
Se ejecuta una vez que la captura de la identificación finaliza exitosamente, entregando las imágenes resultantes en formato Base64.
imagesID
func imagesID(userIDPic: String, userIDFront: String, userIDBack: String) {
// userIDPic: Recorte en Base64 de la fotografía del rostro detectada en el documento
// userIDFront: Imagen en Base64 de la parte frontal del documento
// userIDBack: Imagen en Base64 del reverso del documento
}
2. finishOCRView
Se invoca cuando el flujo de escaneo finaliza (sea exitoso, cancelado o interrumpido) para que la aplicación anfitriona cierre la vista modal o navegue hacia atrás.
finishOCRView
func finishOCRView() {
// En SwiftUI: cambiar el estado de presentación (ej. showOCR = false)
// En UIKit: self.dismiss(animated: true) o popViewController
}
3. ocrDicioResults
Devuelve el estado de la validación y el payload JSON con los campos de datos extraídos del documento.
ocrDicioResults
func ocrDicioResults(ocr: String, isSuccessfull: Bool, info: String, tipoID: String) {
// ocr: Cadena JSON que contiene todos los campos leídos del documento (front y back)
// isSuccessfull: Indica si la verificación y escaneo fueron exitosos
// info: Descripción o mensaje de estado del escaneo
// tipoID: Tipo de documento detectado (INE, Pasaporte, etc.)
}
Estructura de Datos del Resultado (JSON)
El parámetro ocr entregado en ocrDicioResults contiene una estructura JSON con los datos legibles del anverso y reverso:
Ejemplo Estructura JSON
{
"front": {
"nombreCompleto": "JUAN PEREZ LOPEZ",
"curp": "PELJ800101HDFRPR01",
"claveElector": "PELJ80010109H100",
"fechaNacimiento": "01/01/1980",
"sexo": "H",
"ineVigencia": "2030",
"emision": "2020"
},
"back": {
"cicMRZ": "123456789",
"seccionMRZ": "IDMEX1234567897<<1234<<<<<<<<<",
"identificadorCiudadano": "987654321"
}
}
Ejemplo Completo de Integración en SwiftUI
A continuación se muestra un ejemplo integral de implementación en SwiftUI utilizando un contenedor con .fullScreenCover:
Ejemplo de Integración SwiftUI
import SwiftUI
import ModelOCRUI
struct HostScanView: View {
@State private var showOCRScanner = false
@State private var scanStatusMessage: String = "Presiona el botón para iniciar"
var body: some View {
VStack(spacing: 20) {
Text("Escaneo de Identificación")
.font(.title2)
.fontWeight(.bold)
Text(scanStatusMessage)
.font(.body)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
.padding(.horizontal)
Button(action: {
showOCRScanner = true
}) {
Text("Escanear Identificación")
.font(.headline)
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)
.cornerRadius(12)
}
.padding(.horizontal, 30)
}
.fullScreenCover(isPresented: $showOCRScanner) {
let config = DicioOCRUIConfig(
loadLogo: "logoInstitucional",
assetLogo: "logoInstitucional",
colorTitulo: "#4D21B2",
colorSubTitulo: "#707070",
colorTextoBtn: "#FFFFFF",
colorFondoBtn: "#2B0877"
)
DicioOCRContainerView(
config: config,
token: "TOKEN_PROPORCIONADO_POR_DICIO",
urlVerify: "https://api.devdicio.net:8444/v1/sec_dev_fintech_pagos_middleware",
onFinish: { isSuccess, info in
showOCRScanner = false
scanStatusMessage = isSuccess ? "✅ Escaneo exitoso: \(info)" : "❌ Falló el escaneo: \(info)"
}
)
}
}
}
struct DicioOCRContainerView: View, DicioScanOCRDelegate {
let config: DicioOCRUIConfig
let token: String
let urlVerify: String
let onFinish: (_ isSuccess: Bool, _ info: String) -> Void
@State private var scanSuccessful: Bool = false
@State private var resultInfo: String = ""
// MARK: - DicioScanOCRDelegate
func imagesID(userIDPic: String, userIDFront: String, userIDBack: String) {
print("📸 [DicioOCR] Rostro Base64 recibido: \(userIDPic.prefix(30))...")
print("📸 [DicioOCR] Anverso Base64 recibido: \(userIDFront.prefix(30))...")
print("📸 [DicioOCR] Reverso Base64 recibido: \(userIDBack.prefix(30))...")
// Procesar o almacenar imágenes Base64 según sea requerido
}
func finishOCRView() {
print("🏁 [DicioOCR] Finalizando vista OCR")
onFinish(scanSuccessful, resultInfo)
}
func ocrDicioResults(ocr: String, isSuccessfull: Bool, info: String, tipoID: String) {
print("📋 [DicioOCR] Éxito: \(isSuccessfull) | Tipo ID: \(tipoID) | Info: \(info)")
print("📋 [DicioOCR] Payload JSON: \(ocr)")
self.scanSuccessful = isSuccessfull
self.resultInfo = info.isEmpty ? tipoID : info
}
var body: some View {
DicioOCRVCUI(
token: token,
urlVerify: urlVerify,
config: config,
delegateDicioOCR: self
)
.ignoresSafeArea()
}
}
Consideraciones Adicionales y Buenas Prácticas
- Manejo de Conectividad: El SDK cuenta con monitoreo de red reactivo y soporte de reintentos ante fallas temporales de comunicación durante la autenticación de tokens o aprovisionamiento de licencias.
- Gestión de Permisos: Si el usuario no concede el permiso de cámara, el SDK mostrará automáticamente una alerta informando la necesidad de habilitar dicho acceso en la configuración de iOS.
- Presentación en SwiftUI: Se recomienda presentar la vista
DicioOCRVCUIutilizando.fullScreenCover(isPresented:)e.ignoresSafeArea()para garantizar un encuadre óptimo y continuo de la cámara. - Seguridad de Credenciales: El token de verificación debe solicitarse a tu backend en tiempo de ejecución y no guardarse de forma estática o expuesta en el código de producción.