Integração Fortface SDK no seu app iOS
Como funciona?
Objetivo da nossa SDK é efetuar captura da foto e enviá-la para nossa API Fortface. Para isso, há uma UIViewController que atua de forma independente do seu app, iniciada por uma Engine no momento que for estabelecido e, após processamento, encerra automaticamente.
Nossa SDK não se comunica diretamente com a API Fortface, veja abaixo o fluxo de comunicação:

Abaixo, seguem as instruções de integração da nossa SDK, fluxo de processos para acessar corretamente nosso serviço e passo-a-passo de como construir uma Engine.
Instalação
Requisito
iOS: versão mínima suportada é 13.0
Instalação
Versões a partir da 1.8
1. Importar pasta via SPM local
Faça o download clicando no link a seguir e descompacte o arquivo: Fortface.xcframework-1.9.zip
- No seu projeto, vá em
Package Dependenciese clique no+no final da listagem de Packages. - Em seguida, irá abrir uma nova tela para adicionar pacotes. No canto direito inferior, clique em
+. - Na parte inferior da tela, clique em
Add locale selecione a pasta baixada anteriormente. - Selecione o target do seu projeto e clique em
Add Package. - A nova dependência deve aparece na lateral direita do seu Xcode na parte de Package Dependencies.
Versões anteriores a 1.8
1. Adicionar o arquivo ao seu projeto
Primeiramente é necessário adicionar o Fortface.framework ao seu projeto, faça o download clicando no link a seguir e descompacte o arquivo: Fortface.xcframework-1.9.zip.
Para incluir a dependência da Fortface SDK no seu app, basta adicionar a pasta sdk.framework no seu projeto.
Exemplo:
seu_projeto/Fortface.framework

Permissão
Para efetuar captura da foto, nossa SDK precisa ter acesso à câmera do dispositivo. Por isso, é solicitada permissão já no primeiro acesso.
Seguem os passos:
- No Xcode, guia do navegador de projetos (à esquerda), clique no ícone do projeto (azul) para selecioná-lo;
- Na guia principal do projeto, na seção "TARGETS" (ALVOS), selecione seu aplicativo;
- Guia "Info" (Informações), seção "Custom iOS Target Properties" (Propriedades Personalizadas do Alvo iOS), na última Key (Chave) clique no sinal de adição (+) para acrescentar uma nova propriedade;
- Selecione "Privacy - Camera Usage Description" (Privacidade - Descrição do Uso da Câmera);
- No campo "Value" (Valor), insira uma mensagem explicando porquê o app precisa acessar câmera. Por exemplo: "É necessário autorizar acesso à câmera para capturar fotos e vídeos."
Exemplo:
Pré-inicialização
Antes de iniciar o processo de captura, é necessário estabelecer a integridade do dispositivo para garantir uma comunicação segura com a API Fortface. Sendo assim, é preciso:
- Importar nossa SDK no seu app;
- Instanciar
FortfaceSDK.
Estabelecer a integridade do dispositivo
Inicie a SDK e obtenha o deviceRequestInfo.
- Swift
import Fortface
let deviceRequestInfo = FortfaceSDK.start(isDebugMode: true)
print(deviceRequestInfo)
// ztdTVLuGyQegvUnEtwAzcHbK8RoA9CXTuNRpCi9YXcwlzWpzOff+iOvUMkdprLk1E3npSKmk868x4pdJELztvRwu0auBrQdVFTu4wUI8ne35blqq1fds0ZHkOx8pfZGD4SIIPEVTEg2+uXQ8k6lxg7xoSnGzIPQJBZJmQWyDECXKDlXt+AAzMGN4lIWB2uM3ncwQLHPGDcGx52EgXBt3yQV7xZrCdinlwlDb21GK1kjygkRixqCvcB3LudlD8bYKKZq1PO5+faL0gFp6cTWpU9Fqkf7l9kbMc/5n+RGE83QzcQuLBzphDmIX2EUsqIdKFk/eg8WqAA9iC9YX4271/gt6RXqy2oQVJ4cyqD6bpLcRZtk/kLcW1lbo1h4bWyTyjC3XXnRPZVComA51s3Ouzxm4IxKX/EaTMd88n/ABiuE2s2DDKKKYc+WbqrDJo1btFHuXDA+O66mjrNKP+VE/CgtOrWF6W4x2cnpTNBJALmX23tion0caYxzbYpC18i3U
No FortfaceSDK, será usado método start que possui 1 parâmetro e retorna 1 string:
- Parâmetro
isDebugMode: booleano que habilita/desabilita modo de depuração. Valor defaultfalse;- Use
truepara habilitar o modo de depuração; - Use
falseem produção, assim é verificada a integridade do dispositivo e, caso não seja adequado para transações, será lançada uma excepetion do tipoFortfaceExceptioncom a mensagem There is something wrong!.
- Use
- Retorno armazenado em
deviceRequestInfo: string usado para validar integridade do dispositivo conectado à nossa SDK. Uma nova é gerada cada vez que o método é chamado (no código acima está um exemplo).
Com deviceRequestInfo em mãos, agora é possível fazer uma chamada de handshake entre seu back-end e API Fortface.
handshakeé uma medida de segurança importante para estabelecer uma comunicação confiável entre seu back-end e a API Fortface, possibilitando verificar a autenticidade do dispositivo, compartilhar informações sensíveis (chaves de criptografia e sessões) e estabelecer um canal seguro para troca de dados.
Com o sucesso do handshake, haverá a garantia de que o dispositivo está íntegro e seu app tem as informações necessárias para prosseguir.
Captura
Sabendo que a integridade do dispositivo foi estabelecida, vamos entender como iniciar a sessão e utilizar a interface IFortfaceEngine para realizar a captura.
Estabelecer a sessão do dispositivo
Implemente uma classe que extenda IFortfaceEngine.
- Swift
class Engine: IFortfaceEngine {
init(sessionId: String, sessionKey: String) {
FortfaceManagerSession.start(
engine: self,
sessionId: sessionId,
sessionKey: sessionKey,
orientationManager: FortfaceOrientationManager()
)
}
func finishedSessionEngine(sessionEngineResult: SessionEngineResult) {
switch sessionEngineResult {
case .capture:
captured(data: sessionEngineResult.data ?? Data())
case .cancel:
canceled()
case .timeout:
timeout()
case .deniedCamera:
cameraNotAuthorized()
case .error:
handleErrorAction(sessionDetails: sessionEngineResult.sessionDetails ?? Data())
default: return
}
}
private func captured(data: Data) {
let sdkData = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: String]
// Aqui encerra o fluxo e esses são os dados para enviar à API Fortface
}
private func canceled() {
// Aqui a pessoa usuária cancelou a captura. Você deve seguir com seu fluxo de cancelamento
}
private func timeout() {
// Aqui a captura foi cancelada pois o tempo esgotou. Você deve seguir com fluxo de tempo limite esgotado
}
private func cameraNotAuthorized() {
// Aqui a permissão de câmera não foi concedida pelo usuário. Você deve seguir com fluxo de permissão de câmera
}
private func handleErrorAction(sessionDetails: Data) {
// Aqui recebemos um JSON com o tipo de erro que aconteceu.
}
}
Nesta classe, inicialize FortfaceManagerSession e seu método start que possui 3 parâmetros:
sessionId: id da sessão, gerado na API Fortface;sessionKey: chave de criptografia gerado na API Fortface;orientationManager: é a classe responsável por saber a orientação do dispositivo;getGeolocation: define se o SDK deve coletar coordenadas de localização para reforço antifraude. (opcional)
- Swift
class FortfaceOrientationManager: IFortfaceOrientationManager {
private func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
if let delegate = UIApplication.shared.delegate as? AppDelegate {
delegate.orientationLock = orientation
}
}
func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation: UIInterfaceOrientation) {
self.lockOrientation(orientation)
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
}
}
Dados mockados para exemplo:
sessionId = "nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2k"
sessionKey = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2k+o81Oiti4TDezZYD8Q\nzj2RjO5f/YQHGmC1v7CWC4AJpD9+FOXBBO1pImaSg1gb8kOobRFGWbVdiHm35+PF\nTJceH31r+jKnvfc1TshsQVGtYLm7x5E/GFcjpGx9LdSxiXC6cHdCJf3o02/lytBa\nu8NCoH9FpPjyKrdGdSRb2haviAuEV4N1UBd5uZIsacVqZj52i1z+I94gLVKBZ/UV\npaxjLPWWngmaxbyKE0sEbt9JGleiCb2P1kZA9sU4L4Po7WBNk0+QOsvW9QjvS1+6\ntcZwwIDll2LyUceiFgxF6GkuFcHlBZDDtzymDDC2IYrf9/FNBOPeV1JHXON8T6DY\nAwIDAQAB\n-----END PUBLIC KEY-----\n"
A string que representa a sessionKey contém caracteres especiais (como a quebra de linha \n) que devem ser preservados exatamente como recebidos da API Fortface. Tenha cuidado com manipulações acidentais que possam ocorrer em:
- Inputs de formulários
- Logs e sistemas de monitoramento
- Processamento de strings no seu backend
- Transferência entre serviços
- Armazenamento em bancos de dados
Qualquer alteração nesses caracteres pode fazer com que a validação da chave falhe. Certifique-se de que a chave seja passada para o SDK exatamente como recebida da API Fortface.
Para desenvolvimento local do frontend exclusivamente, você pode reutilizar uma mesma sessionKey válida como mock quantas vezes forem necessárias. A restrição de uso único só é aplicada no contexto do desenvolvimento do backend, quando a API Fortface valida a chave.
Entendendo o trecho de código:
initvai fazer a chamada paraFortfaceManagerSession.start;- A sessão é criada e a câmera é renderizada na tela para captura da face da pessoa usuária;
- Os dados são criptografados e enviados junto com a foto capturada para API Fortface;
- O retorno ocorre na função
finishedSessionEngineque é callback; sessionEngineResulté o objeto que possui 3 propriedades:data,actionesessionDetails- Se
sessionEngineResult.actiontrouxer o valor decapturefoi porque o fluxo seguiu como esperado, tendo retornado os dados da captura; datacontém dado criptografado e pode ser convertido em JSON para facilitar sua manipulação. As 4 chaves são geradas pela SDK, enviadas ao seu back-end e então à API Fortface.
{
key: String,
data: String,
imgData: String,
imgPreview: String
}
-
Se
sessionEngineResult.actiontrouxer o valor decancelfoi porque pessoa usuária cancelou a captura ao tocar no botão Voltar, dessa forma deve-se seguir fluxo de cancelamento;- É possível esconder botão Voltar e, por consequência, não ter
action cancel, mais detalhes no tópico Customização.
- É possível esconder botão Voltar e, por consequência, não ter
-
Se
sessionEngineResult.actiontrouxer o valor detimeoutsignifica que o tempo estabelecido para captura foi esgotado, dessa forma deve-se seguir fluxo de tempo limite esgotado.- Essa
actionrepresenta o tempo que a SDK fica aberta, realizando captura ou não. Quando esgotar, a SDK é encerrada e câmera fechada; - O tempo padrão é de 30 segundos:
- Caso deseje manter, não precisa fazer nada;
- Caso deseje alterar, basta customizar o valor em segundos, mais detalhes no tópico Customização.
- Essa
-
Se
sessionEngineResult.actiontrouxer o valor dedeniedCamerasignifica que o usuário não permitiu o acesso a câmera quando o alerta de permissão apareceu. Dessa forma deve-se seguir fluxo de permissão de câmera. -
Se
sessionEngineResult.actiontrouxer o valor deerrorsignifica que ocorreu algum erro durante a captura ou upload de documento. Dessa forma deve-se seguir fluxo de erro.- O tipo de erro é retornado no JSON
sessionDetailsque pode ser decodificado usando o modeloSessionDetailsModel. Hoje os erros recebidos podem ser:- documentNotFound: código retornado quando o arquivo selecionado(PDF/Imagem) não consegue de ser encontrado.
- fileSizeTooBig: código retornado quando o arquivo selecionado(PDF/Imagem) é maior que o limite permitido de 4MB.
- fileCorrupted: código retornado quando o arquivo selecionado(PDF/Imagem) está corrompido.
- O tipo de erro é retornado no JSON
Versionamento
Para saber qual versão da nossa SDK está sendo utilizada, basta chamar a função FortfaceSDK.getVersion() que retornará uma String com seu valor. Exemplo:
let sdkVersion = FortfaceSDK.getVersion()
print(sdkVersion)
// 1.5.2
Modo Tela cheia
Por padrão, nossa SDK é exibida em modo tela cheia na orientação vertical (portrait). Essa configuração é válida para todos os dispositivos suportados. No entanto, em tablets, é possível configurar a orientação para horizontal (landscape) ou automática, permitindo que a SDK siga a orientação do dispositivo em uso.
No iOS, é necessário adicionar esta configuração no AppDelegate do aplicativo integrador para que o orientationManager consiga se adequar nos casos de rotacionamento de tela.
- Swift
import UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
(...)
var orientationLock = UIInterfaceOrientationMask.all
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return self.orientationLock
}
}
Caso a SDK seja configurada para uma orientação diferente de portrait e executada em um smartphone, ela será exibida automaticamente em portrait, ignorando a personalização realizada. Os possíveis valores de configuração são:
- Swift
customizer.screenOrientation.mode = .automatic
customizer.screenOrientation.mode = .portrait
customizer.screenOrientation.mode = .landscape
customizer.screenMode.mode = .fullscreen
Modo Modal
Oferecemos a opção de personalizar a exibição do fluxo de captura da SDK em uma modal que sobrepõe a tela do aplicativo cliente. Essa funcionalidade está disponível apenas para tablets. Quando configurada e executada em smartphones, a SDK adotará o comportamento de exibição em tela cheia na orientação portrait. No modo modal, é possível customizar a cor de fundo.
- Kotlin
customizer.screenMode.mode = .modal
customizer.cameraBackground.color = .red // modal da tela de câmera
customizer.instructionsBackground.color = .white // modal da tela de instruções
Callback de cancelamento e timeout
Quando uma tentativa de captura do rosto do usuário não é completada com sucesso, por exemplo quando o usuário cancela a captura ou quando a captura não acontece durante o tempo determinado, é importante que o acontecimento deste evento seja enviado ao backend para termos corretas métricas de sucesso ou falhas das capturas.
Para permitir que tenhamos os dados da captura cancelada ou que sofreu timeout, nossa SDK possui callbacks na ação de cancelar captura e na ação de timeout de captura.
O SessionEngineResult recebido na função finishedSessionEngine é um objeto no formato Data() que possui 2 propriedades: data e action (ação realizada na SDK). Anteriormente, o campo data era somente preenchido ao finalizar a captura de face.
Como visto anteriormente no tópico Captura, o data contém dados criptografados e pode ser convertidos em JSON. Entretanto, diferentemente da captura, neste cenário após a conversão para JSON, teremos somente os seguintes campos:
{
key: String,
data: String
}
Lembrete: As chaves key e data são geradas pela SDK, enviadas ao seu back-end e então à API Fortface.
Exemplo de implementação
-
Identificamos na SDK que houve um cancelamento de captura.
-
Criamos o objeto criptografado.
-
Terminamos a SDK e enviamos o payload gerado e a ação realizada.
-
No app de implementação, dentro da classe que extende o
IFortfaceEngine, é detectado que houve uma ação.
- Swift
class Engine: IFortfaceEngine {
...
func finishedSessionEngine(sessionEngineResult: SessionEngineResult) {
switch sessionEngineResult {
case .capture:
captured(data: sessionEngineResult.data ?? Data())
// ao detectar a ação de cancelar, é chamada a função canceled
// que recebe a data gerada na SDK.
case .cancel:
canceled(data: sessionEngineResult.data ?? Data())
case .timeout:
timeout(data: sessionEngineResult.data ?? Data())
default: return
}
}
private func canceled(data: Data) {
// envio do payload de cancelamento para uma API de métricas
metricService(data: Data)
}
private func metricService(data: Data) {
// pegamos o objeto do tipo Data e serializamos em JSON
if let metricRequest = try? JSONSerialization.jsonObject(with: self.actionServiceData, options: [])
as? [String: String] {
// transforma em um objeto do tipo Metric
let request = getMetricRequest(sdkJsonDataRequest: metricRequest)
// chama a camada de Service, enviando o Metric para a API
serviceAPI.postSessionMetric(metricRequest: request){ response, error in }
}
}
private func getMetricRequest(sdkJsonDataRequest: [String: String]) -> Metric {
let sdkData = SdkData(
key: sdkJsonDataRequest["key"], data: sdkJsonDataRequest["data"], imgData: nil)
return Metric(sdkData: sdkData)
}
...
}
- Objeto Metric enviado para a API
- Swift
import Foundation
struct Metric: Codable {
let sdkData: SdkData?
}
- Objeto SdkData
- Swift
import Foundation
struct SdkData: Codable {
let key: String?
let data: String?
let imgData: String?
}
Resumo
- Verificiar requisitos mínimos, acrescentar pasta e autorizar acesso à câmera;
- Capturar
deviceRequestInfo; - Fazer
handshake; - Iniciar Engine;
- Receber dados no callback;
- Enviar para API Fortface;
- Receber resposta da API Fortface e seguir com sua regra de negócio.