@oiti/rn-sdk
v1.2.0
Published
Oiti SDK
Downloads
220
Readme
@oiti/rn-sdk
SDK React Native oficial da Oiti para verificação biométrica de liveness (prova de vida). Integre detecção facial avançada com FaceTec e iProov em aplicações Android e iOS com suporte completo a personalização de temas e interface nativa de alta performance.
📦 Instalação
npm install @oiti/rn-sdkou
yarn add @oiti/rn-sdk⚙️ Configuração
Android
- Configure os repositórios necessários no
android/build.gradle:
allprojects {
repositories {
google()
mavenCentral()
maven {
url 'https://raw.githubusercontent.com/oititec/android-oiti-sdk-versions/master'
}
}
}- Adicione as permissões no
android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />iOS
- Configure as fontes do CocoaPods no
ios/Podfile:
source 'https://github.com/oititec/ios-artifactory.git'
source 'https://github.com/CocoaPods/Specs.git'- Adicione as permissões no
ios/YourApp/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Precisamos acessar sua câmera para verificação de identidade</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Precisamos acessar suas fotos para verificação de identidade</string>- Execute a instalação dos pods:
cd ios && pod install🚀 Uso Básico
Importação
import {
startJourney,
checkCameraPermission,
requestCameraPermission,
LivenessProvider,
Environment,
type OitiTheme,
type LivenessResult,
} from '@oiti/rn-sdk';Exemplo Simples
import React from 'react';
import { Button, Alert } from 'react-native';
import { startJourney, Environment, LivenessProvider } from '@oiti/rn-sdk';
export default function App() {
const handleVerification = async () => {
try {
const appKey = 'your-app-key-here';
const result = await startJourney(
appKey,
Environment.HML,
LivenessProvider.FACETEC,
false
);
Alert.alert('Sucesso!', `Verificação concluída: ${result.codID}`);
} catch (error) {
Alert.alert('Erro', `Falha: ${error.message}`);
}
};
return <Button title="Iniciar Verificação" onPress={handleVerification} />;
}Resultado Esperado
Quando bem-sucedido, o método startJourney retorna um objeto LivenessResult:
{
valid: true,
codID: "abc123def456",
protocol: "20231105-001"
}📚 API
startJourney(appKey, environment, provider, isCustomEnabled?, theme?)
Inicia o processo de verificação de liveness.
Parâmetros:
| Nome | Tipo | Obrigatório | Descrição |
| ----------------- | ------------------ | ----------- | ---------------------------------------------- |
| appKey | string | ✅ | Chave de aplicação fornecida pela Oiti |
| environment | Environment | ✅ | Ambiente de execução (HML ou PRD) |
| provider | LivenessProvider | ✅ | Provedor de liveness (FACETEC ou IPROOV) |
| isCustomEnabled | boolean | ❌ | Habilita tema personalizado (padrão: false) |
| theme | OitiTheme | ❌ | Objeto com configurações de tema personalizado |
Retorna: Promise<LivenessResult> com o resultado da verificação
Exemplo:
const result = await startJourney(
'your-app-key',
Environment.HML,
LivenessProvider.FACETEC,
false
);
const resultWithTheme = await startJourney(
'your-app-key',
Environment.PRD,
LivenessProvider.IPROOV,
true,
customTheme
);LivenessResult
Tipo de retorno da função startJourney:
interface LivenessResult {
valid: boolean;
codID: string | null;
protocol: string | null;
}Propriedades:
| Nome | Tipo | Descrição |
| ---------- | ---------------- | ---------------------------------------- |
| valid | boolean | Indica se a verificação foi bem-sucedida |
| codID | string \| null | Código de identificação da verificação |
| protocol | string \| null | Protocolo da sessão de verificação |
checkCameraPermission()
Verifica se a permissão da câmera foi concedida.
Retorna: Promise<boolean>
Exemplo:
const hasPermission = await checkCameraPermission();
if (!hasPermission) {
console.log('Permissão não concedida');
}Resultado:
true- Permissão concedidafalse- Permissão negada
requestCameraPermission()
Solicita permissão da câmera ao usuário.
Retorna: Promise<boolean>
Exemplo:
const granted = await requestCameraPermission();
if (granted) {
console.log('Usuário concedeu permissão');
}Resultado:
true- Usuário concedeu permissãofalse- Usuário negou permissão
🎨 Personalização de Tema
O SDK oferece suporte a temas personalizados para os provedores FaceTec e iProov.
Estrutura do Tema
import { LivenessProvider, Environment, type OitiTheme } from '@oiti/rn-sdk';
const customTheme: OitiTheme = {
facetec: {
colors: {
frameBackground: '#1A1A1A',
frameBorder: '#FF6B35',
ovalStroke: '#FF6B35',
ovalProgressFirst: '#FF6B35',
ovalProgressSecond: '#FFD700',
},
texts: {
readyHeader1: 'Prepare-se',
readyHeader2: 'para verificação',
readyButton: 'Iniciar',
},
fonts: {
readyScreenHeader: 'CustomFont',
},
},
};
await startJourney(
appKey,
Environment.HML,
LivenessProvider.FACETEC,
true,
customTheme
);Opções de Provider
enum LivenessProvider {
FACETEC = 'FACETEC',
IPROOV = 'IPROOV',
}Opções de Environment
enum Environment {
HML = 'HML',
PRD = 'PRD',
}💡 Exemplos
Exemplo com Gerenciamento de Permissões
import React, { useState } from 'react';
import { View, Button, Alert, ActivityIndicator } from 'react-native';
import {
startJourney,
checkCameraPermission,
requestCameraPermission,
Environment,
LivenessProvider,
type LivenessResult,
} from '@oiti/rn-sdk';
export default function LivenessScreen() {
const [loading, setLoading] = useState(false);
const handleVerification = async () => {
setLoading(true);
try {
const hasPermission = await checkCameraPermission();
if (!hasPermission) {
const granted = await requestCameraPermission();
if (!granted) {
Alert.alert('Erro', 'Permissão da câmera é necessária');
setLoading(false);
return;
}
}
const appKey = 'your-app-key-here';
const result: LivenessResult = await startJourney(
appKey,
Environment.HML,
LivenessProvider.FACETEC,
false
);
if (result.valid) {
Alert.alert(
'Verificação Aprovada!',
`Protocolo: ${result.protocol}\nCódigo: ${result.codID}`
);
} else {
Alert.alert('Verificação Recusada');
}
} catch (error) {
Alert.alert('Erro', error.message);
} finally {
setLoading(false);
}
};
return (
<View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
{loading ? (
<ActivityIndicator size="large" color="#007AFF" />
) : (
<Button title="Iniciar Verificação" onPress={handleVerification} />
)}
</View>
);
}Resultado de Sucesso:
{
valid: true,
codID: "abc123def456",
protocol: "20231105-001"
}Resultado de Erro:
{
valid: false,
codID: null,
protocol: null
}Exemplo com Tema Customizado Completo
import React from 'react';
import { Button, Alert } from 'react-native';
import {
startJourney,
LivenessProvider,
Environment,
type OitiTheme,
type LivenessResult,
} from '@oiti/rn-sdk';
const customTheme: OitiTheme = {
facetec: {
colors: {
frameBackground: '#1A1A1A',
frameBorder: '#FF6B35',
ovalStroke: '#FF6B35',
ovalProgressFirst: '#FF6B35',
ovalProgressSecond: '#FFD700',
guidanceButtonBackgroundNormal: '#FF6B35',
guidanceButtonTextNormal: '#FFFFFF',
},
texts: {
readyHeader1: 'Prepare-se',
readyHeader2: 'para a verificação',
readyMessage1: 'Posicione seu rosto',
readyMessage2: 'dentro do círculo',
readyButton: 'Começar',
feedbackCenterFace: 'Centralize seu rosto',
feedbackHoldSteady: 'Mantenha-se parado',
},
},
instructions: {
colors: {
background: '#2E2E2E',
title: '#FFFFFF',
continueButtonBackground: '#FF6B35',
},
texts: {
title: 'Verificação de Identidade',
caption: 'Siga as instruções',
continueButton: 'Continuar',
},
},
result: {
colors: {
successBackground: '#E8F5E8',
successText: '#2E7D32',
errorBackground: '#FFEBEE',
errorText: '#C62828',
},
texts: {
success: 'Verificação concluída com sucesso!',
error: 'Erro na verificação. Tente novamente.',
},
},
};
export default function ThemedVerification() {
const handleStart = async () => {
try {
const appKey = 'your-app-key-here';
const result: LivenessResult = await startJourney(
appKey,
Environment.PRD,
LivenessProvider.FACETEC,
true,
customTheme
);
if (result.valid) {
Alert.alert('Sucesso!', `Protocolo: ${result.protocol}`);
}
} catch (error) {
Alert.alert('Erro', error.message);
}
};
return <Button title="Iniciar com Tema Custom" onPress={handleStart} />;
}Exemplo com TypeScript e Tratamento de Erros
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, Alert } from 'react-native';
import {
startJourney,
Environment,
LivenessProvider,
type LivenessResult,
} from '@oiti/rn-sdk';
export default function VerificationComponent() {
const [result, setResult] = useState<LivenessResult | null>(null);
const [loading, setLoading] = useState(false);
const handleVerification = async () => {
setLoading(true);
setResult(null);
try {
const appKey = process.env.OITI_APP_KEY || 'your-app-key';
const data: LivenessResult = await startJourney(
appKey,
Environment.HML,
LivenessProvider.FACETEC,
false
);
setResult(data);
if (data.valid) {
Alert.alert('Sucesso', 'Identidade verificada!');
} else {
Alert.alert('Falha', 'Verificação não aprovada');
}
} catch (error) {
Alert.alert('Erro', `Não foi possível completar: ${error.message}`);
} finally {
setLoading(false);
}
};
return (
<View style={styles.container}>
<TouchableOpacity
style={[styles.button, loading && styles.buttonDisabled]}
onPress={handleVerification}
disabled={loading}
>
<Text style={styles.buttonText}>
{loading ? 'Verificando...' : 'Iniciar Verificação'}
</Text>
</TouchableOpacity>
{result && (
<View style={styles.resultContainer}>
<Text style={styles.resultTitle}>Resultado:</Text>
<Text>Status: {result.valid ? 'Aprovado' : 'Reprovado'}</Text>
{result.protocol && <Text>Protocolo: {result.protocol}</Text>}
{result.codID && <Text>Código: {result.codID}</Text>}
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
button: {
backgroundColor: '#007AFF',
padding: 15,
borderRadius: 8,
alignItems: 'center',
},
buttonDisabled: {
backgroundColor: '#cccccc',
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
resultContainer: {
marginTop: 20,
padding: 15,
backgroundColor: '#f5f5f5',
borderRadius: 8,
},
resultTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 10,
},
});Possíveis Resultados:
Sucesso:
{
valid: true,
codID: "abc123def456",
protocol: "20231105-001"
}Falha:
{
valid: false,
codID: null,
protocol: null
}🎭 Tema Completo
Exemplo de Tema Personalizado Completo
const customTheme: OitiTheme = {
facetec: {
colors: {
readyScreenHeader: '#FFFFFF',
readyScreenSubtext: '#CCCCCC',
readyScreenOvalFill: '#FF6B35',
readyScreenTextBackground: '#444444',
resultScreenForeground: '#FF6B35',
resultScreenBackground: '#F0F8FF',
ovalStroke: '#FF6B35',
ovalProgressFirst: '#FF6B35',
ovalProgressSecond: '#FFD700',
overlayBackground: '#80000000',
frameBorder: '#FF6B35',
frameBackground: '#1A1A1A',
feedbackBarBackground: '#FFF8DC',
feedbackMessage: '#333333',
guidanceBackground: '#2E2E2E',
guidanceForeground: '#FFFFFF',
guidanceButtonTextNormal: '#FFFFFF',
guidanceButtonTextHighlight: '#FFFFFF',
guidanceButtonTextDisabled: '#AAAAAA',
guidanceButtonBackgroundNormal: '#FF6B35',
guidanceButtonBackgroundHighlight: '#FF6B35',
guidanceButtonBackgroundDisabled: '#666666',
guidanceButtonBorder: '#FF6B35',
},
texts: {
readyHeader1: 'Prepare-se',
readyHeader2: 'para verificação',
readyMessage1: 'Posicione seu rosto',
readyMessage2: 'dentro do círculo',
readyButton: 'Iniciar',
retryHeader: 'Vamos tentar novamente',
retrySubheader: 'Ajustes necessários',
retryButton: 'Tentar Novamente',
resultSuccessMessage: 'Verificação concluída!',
feedbackCenterFace: 'Centralize seu rosto',
feedbackHoldSteady: 'Mantenha-se parado',
feedbackMovePhoneCloser: 'Aproxime o dispositivo',
feedbackMovePhoneAway: 'Afaste o dispositivo',
},
assets: {
overlayBrandImage: 'overlayBrandImage',
cancelButtonIcon: 'cancelButtonIcon',
resultScreenCustomActivityIndicatorImage:
'resultScreenCustomActivityIndicatorImage',
},
fonts: {
readyScreenHeader: 'sixty',
readyScreenSubtext: 'sixty',
resultScreenMessage: 'sixty',
retryScreenHeader: 'sixty',
retryScreenSubtext: 'sixty',
feedbackMessage: 'sixty',
guidanceHeader: 'sixty',
guidanceSubtext: 'sixty',
guidanceButton: 'sixty',
},
},
iproov: {
colors: {
title: '#FFFFFF',
titleBackground: '#2E2E2E',
promptText: '#FFFFFF',
promptBackground: '#1A1A1A',
background: '#FF6B35',
ovalReady: '#FF6B35',
ovalNotReady: '#FF3030',
ovalCapturing: '#FFFFFF',
ovalCompleted: '#FF6B35',
},
texts: {
title: 'Verificação Biométrica',
},
assets: {
closeButtonIcon: 'closeButtonIcon',
logoImage: 'logoImage',
},
fonts: {
instructionsTitleFont: 'sixty',
instructionsCaptionFont: 'sixty',
instructionsDocumentTypesInstructionsFont: 'sixty',
instructionsDocumentTipsInstructionsFont: 'sixty',
instructionsButtonFont: 'sixty',
permissionTitleFont: 'sixty',
permissionCaptionFont: 'sixty',
permissionButtonFont: 'sixty',
resultMessageFont: 'sixty',
resultRetryButtonFont: 'sixty',
},
},
instructions: {
colors: {
statusBar: '#2E2E2E',
background: '#2E2E2E',
backButtonIcon: '#2E2E2E',
backButtonBackground: '#2E2E2E',
backButtonBorder: '#2E2E2E',
bottomSheet: '#1A1A1A',
title: '#FFFFFF',
caption: '#CCCCCC',
firstInstructionTitle: '#FFFFFF',
secondInstructionTitle: '#FFFFFF',
continueButtonText: '#FFFFFF',
continueButtonBackground: '#FF6B35',
continueButtonBorder: '#FF6B35',
},
texts: {
title: 'Verificação de Identidade',
caption: 'Siga as instruções para completar o processo',
firstInstruction: 'Mantenha o documento bem iluminado',
secondInstruction: 'Use um documento oficial com foto',
continueButton: 'Continuar',
},
assets: {
backButtonIcon: 'backButtonIcon',
contextImage: 'contextImage',
firstInstructionIcon: 'firstInstructionIcon',
secondInstructionIcon: 'secondInstructionIcon',
},
fonts: {
title: 'sixty',
caption: 'sixty',
firstInstructionTitle: 'sixty',
secondInstructionTitle: 'sixty',
continueButton: 'sixty',
},
},
permission: {
colors: {
statusBar: '#2E2E2E',
background: '#2E2E2E',
backButtonIcon: '#2E2E2E',
backButtonBackground: '#2E2E2E',
backButtonBorder: '#2E2E2E',
cameraImage: '#FFFFFF',
title: '#FFFFFF',
caption: '#FFFFFF',
checkPermissionButtonText: '#FFFFFF',
checkPermissionButtonBackground: '#FF6B35',
checkPermissionButtonBorder: '#FF6B35',
bottomSheet: '#FF6B35',
bottomSheetTitle: '#FF6B35',
bottomSheetCaption: '#FF6B35',
openSettingsButtonText: '#FF6B35',
openSettingsButtonBackground: '#FF6B35',
openSettingsButtonBorder: '#FF6B35',
closeButtonText: '#FF6B35',
closeButtonBackground: '#FF6B35',
closeButtonBorder: '#FF6B35',
},
texts: {
title: 'Permissões Necessárias',
caption: 'Permissões Necessárias',
checkPermissionButton: 'Permitir Acesso',
bottomSheetTitle: 'Permitir Acesso',
bottomSheetCaption: 'Permitir Acesso',
openSettingsButton: 'Permitir Acesso',
closeButton: 'Permitir Acesso',
},
assets: {
backButtonIcon: 'backButtonIcon',
cameraImage: 'cameraImage',
},
fonts: {
title: 'sixty',
caption: 'sixty',
checkPermissionButton: 'sixty',
bottomSheetTitle: 'sixty',
bottomSheetCaption: 'sixty',
opentSettingsButton: 'sixty',
closeButton: 'sixty',
},
},
processing: {
colors: {
statusBar: '#1A1A1A',
background: '#1A1A1A',
loading: '#FFFFFF',
},
},
result: {
colors: {
successStatusBar: '#E8F5E8',
successBackground: '#E8F5E8',
successText: '#2E7D32',
errorStatusBar: '#FFEBEE',
errorBackground: '#FFEBEE',
errorText: '#C62828',
retryBackground: '#C62828',
retryText: '#FFEBEE',
retryButtonText: '#FF6B35',
retryButtonBackground: '#FFFFFF',
retryButtonBorder: '#FFFFFF',
},
texts: {
success: 'Verificação concluída com sucesso!',
error: 'Houve um erro na verificação. Tente novamente.',
retryButton: 'Tentar Novamente',
},
assets: {
successImage: 'successImage',
errorImage: 'errorImage',
retryImage: 'retryImage',
},
fonts: {
text: 'sixty',
retryButton: 'sixty',
},
},
};Configuração de Assets e Fonts
Os assets e fonts referenciados no tema precisam ser cadastrados nativamente em cada plataforma:
Android - Drawable Resources
Os assets devem ser adicionados em android/app/src/main/res/drawable/:
android/app/src/main/res/
└── drawable/
├── shell.png
└── outros_assets.pngFormatos aceitos: .png, .jpg, .xml (vector drawables)
Android - Fonts
As fontes devem ser adicionadas em android/app/src/main/res/font/:
android/app/src/main/res/
└── font/
├── sixty.ttf
└── outras_fontes.ttfFormatos aceitos: .ttf, .otf
iOS - Assets
Os assets devem ser adicionados em um Asset Catalog (.xcassets):
ios/YourApp/
└── Images.xcassets/
├── shell.imageset/
│ ├── Contents.json
│ ├── shell.png
│ ├── [email protected]
│ └── [email protected]
└── Contents.jsonEstrutura do Contents.json para cada imageset:
{
"images": [
{
"filename": "shell.png",
"idiom": "universal",
"scale": "1x"
},
{
"filename": "[email protected]",
"idiom": "universal",
"scale": "2x"
},
{
"filename": "[email protected]",
"idiom": "universal",
"scale": "3x"
}
],
"info": {
"author": "xcode",
"version": 1
}
}iOS - Fonts
As fontes devem ser adicionadas ao projeto e registradas no Info.plist:
- Adicione os arquivos de fonte ao projeto:
ios/YourApp/
└── Fonts/
├── sixty.ttf
└── outras_fontes.ttf- Registre no
Info.plist:
<key>UIAppFonts</key>
<array>
<string>sixty.ttf</string>
<string>outras_fontes.ttf</string>
</array>- Adicione no Xcode: arraste os arquivos
.ttfpara o projeto no Xcode e marque "Copy items if needed" e o target correto.
Referenciando no Tema
Use apenas o nome base do asset/font (sem extensão):
assets: {
overlayBrandImage: 'shell',
},
fonts: {
readyScreenHeader: 'sixty',
}✨ Funcionalidades
- ✅ Verificação de liveness com FaceTec e iProov
- ✅ Gerenciamento automático de permissões
- ✅ Suporte completo a temas personalizados
- ✅ Interface TypeScript com tipagem completa
- ✅ Suporte para Android e iOS
- ✅ Integração com TurboModules para performance otimizada
- ✅ Callbacks de sucesso e erro
- ✅ Compatível com React Native 0.60+
📋 Requisitos
- React Native ≥ 0.79
- Android API ≥ 26
- iOS ≥ 12.0
- TypeScript ≥ 4.0 (recomendado)
🔗 Links Úteis
📄 Licença
MIT © Oiti
Feito com ❤️ pela equipe Oiti
