CredFace - Venda com Biometria Facial
O CredFace é uma solução de venda com autenticação biométrica facial que adiciona uma camada extra de segurança às transações. Pode ser integrado em qualquer aplicação com câmera: PDV, site, totem de pagamento, aplicativo ou qualquer plataforma que o parceiro deseje utilizar — garantindo que apenas o titular do cartão possa realizar compras.
🎯 Visão Geral
O CredFace combina a tecnologia de biometria facial com o processo de venda, proporcionando:
- 🔒 Segurança Avançada: Validação biométrica do cliente antes de aprovar a transação
- ⚡ Processo Rápido: Autenticação em poucos segundos
- 🛡️ Prevenção de Fraudes: Redução significativa de transações fraudulentas
- ✅ Experiência do Usuário: Processo simples e intuitivo para o cliente
🏗️ Arquitetura da Solução
Componentes Necessários
A solução CredFace é composta por três elementos principais:
1. Hardware
- Webcam: Câmera com as mesmas configurações utilizadas no Credline
- Dispositivo de acesso: Computador, totem, tablet ou qualquer dispositivo com sistema operacional que suporte navegador Chrome 85 ou superior (versão atual: 124)
2. Integração de Software
- APIs de Pagamento: Integração da aplicação com as APIs Credsystem
- Motor de Biometria: Sistema de captura e validação biométrica facial
- Navegador: Chrome 85+ para execução da WebView de biometria
3. Conectividade
- Internet: Conexão estável para comunicação com as APIs
- Certificados SSL: Comunicação segura com os servidores
🔄 Fluxo de Venda com Biometria
Passo a Passo
1. Solicitar Pré-autorização Biométrica
Antes de abrir o Motor de Biometria, a aplicação deve chamar o endpoint POST /pre-autorizacoes/biometria da API de Venda Loja. A resposta retorna os seguintes campos:
| Campo | Descrição |
|---|---|
biometria.url | URL para abrir o Motor de Biometria na aplicação (popup / WebView) |
biometria.urlLinkExterno | URL para gerar QR Code — o cliente escaneia com o celular |
biometria.acess_token | Token de acesso para enviar no authorization do OnInit |
biometria.token | Token da sessão para enviar no token do OnInit |
Consulte o endpoint de Pré-autorização Biométrica para o payload completo e os campos obrigatórios.
2. Abrir o Motor de Biometria
O Motor de Biometria é um serviço web da Credsystem que gerencia a captura e validação facial. A aplicação abre a biometria.url (retornada no passo anterior) em uma janela do navegador e se comunica com ela via eventos postMessage:
| Evento | Direção | Descrição |
|---|---|---|
"loaded" (string) | Motor → Aplicação | Motor carregou e aguarda inicialização |
OnInit | Aplicação → Motor | Aplicação inicializa o Motor com authorization, token e tema |
OnFinished | Motor → Aplicação | Captura concluída — retorna decision, jwt (imagem criptografada) e base64 (imagem em base64) |
OnError | Motor → Aplicação | Erro durante a captura — retorna code e message |
URL do Motor de Biometria: url retornada pelo POST /pre-autorizacoes/biometria
Payload do OnInit
Após receber o evento "loaded", a aplicação deve enviar o OnInit com os seguintes campos:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
authorization | string | ✅ | Token retornado em biometria.acess_token |
token | string | ✅ | Token retornado em biometria.token |
theme.primaryColor | string | ❌ | Cor primária dos botões (ex: #0066CC) |
theme.buttonTextColor | string | ❌ | Cor do texto dos botões |
allowedOrigin | string | ❌ | Origem permitida para postMessage — use location.origin em web; URL do Motor em apps nativos |
isOperador | boolean | ❌ | Quando true, altera os textos da tela inicial do Motor |
Consulte os Acordos WebView para a especificação completa dos eventos.
- JavaScript
- C# (.NET)
- Java (JavaFX)
- Python
- PHP
- Go
// biometria.url = preAuthResponse.biometria.url
function abrirMotorBiometria({ urlBiometria, authorization, token, theme = {}, isOperador = false }) {
const popup = window.open(
urlBiometria,
'MotorBiometria',
`width=${window.innerWidth - 14},height=${window.innerHeight},` +
`top=${window.screenTop + 10},left=${window.screenLeft + 7}`
);
return new Promise((resolve, reject) => {
const handler = (event) => {
// Motor sinalizou que carregou — enviar OnInit
if (event.data === 'loaded') {
popup.postMessage({
type: 'OnInit',
detail: {
authorization,
token,
theme,
allowedOrigin: location.origin,
isOperador
}
}, '*');
return;
}
const { type, detail } = event.data ?? {};
if (type === 'OnFinished') {
window.removeEventListener('message', handler);
resolve(detail); // { decision: 'APPROVED'|'DENIED'|'CLOSE', jwt, base64 }
}
if (type === 'OnError') {
window.removeEventListener('message', handler);
reject(new Error(detail.message));
}
};
window.addEventListener('message', handler);
});
}
// Uso
// 1. Chamar POST /pre-autorizacoes/biometria e obter os campos de biometria da resposta
const { url: urlBiometria, acess_token, token: tokenBiometria } = preAuthResponse.biometria;
const resultado = await abrirMotorBiometria({
urlBiometria,
authorization: acess_token,
token: tokenBiometria,
theme: { primaryColor: '#0066CC', buttonTextColor: '#FFFFFF' }
});
// Requer: Microsoft.Web.WebView2 (NuGet)
// dotnet add package Microsoft.Web.WebView2
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
using System.Text.Json;
public class MotorBiometriaWindow : Window
{
private WebView2 webView = new WebView2();
private readonly TaskCompletionSource<BiometriaResultado> _tcs = new();
private readonly string _motorUrl;
private readonly string _authorization;
private readonly string _token;
private readonly string _primaryColor;
// motorUrl = preAuthResponse.Biometria.Url
public MotorBiometriaWindow(string motorUrl, string authorization, string token, string primaryColor = "#0066CC")
{
_motorUrl = motorUrl;
_authorization = authorization;
_token = token;
_primaryColor = primaryColor;
Title = "Validação Biométrica";
Width = 900; Height = 700;
Content = webView;
Loaded += async (_, _) =>
{
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.WebMessageReceived += OnWebMessageReceived;
webView.CoreWebView2.Navigate(_motorUrl);
};
}
private void OnWebMessageReceived(object? sender, CoreWebView2WebMessageReceivedEventArgs e)
{
var msg = e.TryGetWebMessageAsString();
if (msg == "loaded")
{
var initPayload = JsonSerializer.Serialize(new
{
type = "OnInit",
detail = new
{
authorization = _authorization,
token = _token,
theme = new { primaryColor = _primaryColor },
allowedOrigin = "https://credsystem-biometria-webview-hml.credsystem.com.br/"
}
});
webView.CoreWebView2.PostWebMessageAsJson(initPayload);
return;
}
using var doc = JsonDocument.Parse(msg);
var tipo = doc.RootElement.GetProperty("type").GetString();
var detail = doc.RootElement.GetProperty("detail");
if (tipo == "OnFinished")
{
_tcs.SetResult(new BiometriaResultado(
Decision: detail.GetProperty("decision").GetString()!,
Jwt: detail.TryGetProperty("jwt", out var jwt) ? jwt.GetString() : null
));
Dispatcher.Invoke(Close);
}
else if (tipo == "OnError")
{
_tcs.SetException(new Exception(
detail.GetProperty("message").GetString()!
));
Dispatcher.Invoke(Close);
}
}
public Task<BiometriaResultado> AguardarResultadoAsync() => _tcs.Task;
}
public record BiometriaResultado(string Decision, string? Jwt);
// Uso
// motorUrl = preAuthResponse.Biometria.Url
var janela = new MotorBiometriaWindow(preAuthContent.Biometria.Url, preAuthContent.Biometria.AcessToken, preAuthContent.Biometria.Token);
janela.Show();
var resultado = await janela.AguardarResultadoAsync();
// resultado.Decision == "APPROVED" → usar resultado.Jwt para capturar a venda
// Requer: JavaFX SDK + Gson (Maven: com.google.code.gson:gson)
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
public class MotorBiometria {
// motorUrl = preAuthResponse.getBiometria().getUrl()
public static CompletableFuture<Map<String, String>> abrir(
String motorUrl, String authorization, String token, String primaryColor) {
var future = new CompletableFuture<Map<String, String>>();
Platform.runLater(() -> {
var stage = new Stage();
var webView = new WebView();
var engine = webView.getEngine();
engine.getLoadWorker().stateProperty().addListener((obs, old, newState) -> {
if (newState == javafx.concurrent.Worker.State.SUCCEEDED) {
JSObject window = (JSObject) engine.executeScript("window");
window.setMember("javaHandler",
new MessageHandler(engine, authorization, token, primaryColor, future, stage));
engine.executeScript("""
window.addEventListener('message', function(e) {
var data = typeof e.data === 'string'
? e.data : JSON.stringify(e.data);
window.javaHandler.onMessage(data);
});
""");
}
});
engine.load(motorUrl);
stage.setScene(new Scene(webView, 900, 700));
stage.setTitle("Validação Biométrica");
stage.show();
});
return future;
}
public static class MessageHandler {
private final WebEngine engine;
private final String authorization, token, primaryColor;
private final CompletableFuture<Map<String, String>> future;
private final Stage stage;
public MessageHandler(WebEngine engine, String auth, String token,
String color, CompletableFuture<Map<String, String>> future, Stage stage) {
this.engine = engine; this.authorization = auth; this.token = token;
this.primaryColor = color; this.future = future; this.stage = stage;
}
public void onMessage(String data) {
if ("\"loaded\"".equals(data) || "loaded".equals(data)) {
String payload = String.format(
"{\"type\":\"OnInit\",\"detail\":{" +
"\"authorization\":\"%s\",\"token\":\"%s\"," +
"\"theme\":{\"primaryColor\":\"%s\"}," +
"\"allowedOrigin\":\"https://credsystem-biometria-webview-hml.credsystem.com.br/\"}}",
authorization, token, primaryColor
);
Platform.runLater(() ->
engine.executeScript("window.postMessage(" + payload + ", '*')")
);
return;
}
JsonObject obj = JsonParser.parseString(data).getAsJsonObject();
String type = obj.get("type").getAsString();
JsonObject detail = obj.getAsJsonObject("detail");
if ("OnFinished".equals(type)) {
Map<String, String> result = new HashMap<>();
result.put("decision", detail.get("decision").getAsString());
if (detail.has("jwt")) result.put("jwt", detail.get("jwt").getAsString());
future.complete(result);
Platform.runLater(stage::close);
} else if ("OnError".equals(type)) {
future.completeExceptionally(
new RuntimeException(detail.get("message").getAsString())
);
Platform.runLater(stage::close);
}
}
}
}
// Uso (dentro do contexto JavaFX Application)
// motorUrl = preAuthResponse.getBiometria().getUrl()
var resultado = MotorBiometria.abrir(preAuthResponse.getBiometria().getUrl(), preAuthResponse.getBiometria().getAcessToken(), preAuthResponse.getBiometria().getToken(), "#0066CC").get();
if ("APPROVED".equals(resultado.get("decision"))) {
String jwt = resultado.get("jwt");
// Prosseguir com a captura da venda usando jwt
}
# Requer: pywebview
# pip install pywebview
import webview
import json
import threading
from typing import Optional
class _MotorBiometriaAPI:
"""Ponte JavaScript ↔ Python usada pelo pywebview."""
def __init__(self, authorization: str, token: str, primary_color: str):
self.authorization = authorization
self.token = token
self.primary_color = primary_color
self.resultado: Optional[dict] = None
self._concluido = threading.Event()
self._window = None
def set_window(self, w):
self._window = w
def on_message(self, data: str):
parsed = json.loads(data) if isinstance(data, str) else data
if parsed == "loaded":
payload = json.dumps({
"type": "OnInit",
"detail": {
"authorization": self.authorization,
"token": self.token,
"theme": {"primaryColor": self.primary_color},
"allowedOrigin": "https://credsystem-biometria-webview-hml.credsystem.com.br/"
}
})
self._window.evaluate_js(f"window.postMessage({payload}, '*')")
return
if isinstance(parsed, dict):
tipo = parsed.get("type")
if tipo == "OnFinished":
self.resultado = parsed["detail"]
self._concluido.set()
self._window.destroy()
elif tipo == "OnError":
self.resultado = {"error": parsed["detail"]["message"]}
self._concluido.set()
self._window.destroy()
def aguardar(self, timeout: int = 120) -> Optional[dict]:
self._concluido.wait(timeout=timeout)
return self.resultado
def abrir_motor_biometria(
url_biometria: str, authorization: str, token: str, primary_color: str = "#0066CC") -> Optional[dict]:
api = _MotorBiometriaAPI(authorization, token, primary_color)
window = webview.create_window(
"Validação Biométrica", url_biometria,
width=900, height=700, js_api=api
)
api.set_window(window)
def on_loaded():
window.evaluate_js("""
window.addEventListener('message', function(e) {
var data = typeof e.data === 'string'
? e.data : JSON.stringify(e.data);
pywebview.api.on_message(data);
});
""")
window.events.loaded += on_loaded
webview.start()
return api.aguardar()
# Uso
# url_biometria = pre_auth_response["biometria"]["url"]
resultado = abrir_motor_biometria(
url_biometria=pre_auth_response["biometria"]["url"],
authorization=pre_auth_response["biometria"]["acess_token"],
token=pre_auth_response["biometria"]["token"]
)
if resultado and resultado.get("decision") == "APPROVED":
jwt = resultado["jwt"]
# Prosseguir com a captura da venda usando jwt
<?php
// PHP gera a página HTML que abre o Motor de Biometria via JavaScript popup.
// O token vem da chamada à API de pré-autorização biométrica.
$authorization = 'Bearer ' . ($_SESSION['access_token'] ?? '');
$token = htmlspecialchars($_POST['token_biometria'] ?? '', ENT_QUOTES, 'UTF-8');
// biometria.url vem da resposta do POST /pre-autorizacoes/biometria
$url_biometria = htmlspecialchars($_POST['url_biometria'] ?? '', ENT_QUOTES, 'UTF-8');
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Validação Biométrica</title>
</head>
<body>
<p id="status">Abrindo validação biométrica...</p>
<button id="btn-abrir" style="display:none" onclick="abrirMotor()">
Abrir Validação Biométrica
</button>
<script>
const CONFIG = {
urlBiometria: <?= json_encode($url_biometria) ?>,
authorization: <?= json_encode($authorization) ?>,
token: <?= json_encode($token) ?>,
theme: { primaryColor: '#0066CC', buttonTextColor: '#FFFFFF' }
};
let popup;
function abrirMotor() {
popup = window.open(
CONFIG.urlBiometria, 'MotorBiometria',
`width=${window.innerWidth - 14},height=${window.innerHeight},` +
`top=${window.screenTop + 10},left=${window.screenLeft + 7}`
);
window.addEventListener('message', handleMessage);
}
function handleMessage(event) {
if (event.data === 'loaded') {
popup.postMessage({
type: 'OnInit',
detail: {
authorization: CONFIG.authorization,
token: CONFIG.token,
theme: CONFIG.theme,
allowedOrigin: location.origin
}
}, '*');
return;
}
const { type, detail } = event.data ?? {};
if (type === 'OnFinished') {
window.removeEventListener('message', handleMessage);
// Enviar resultado ao servidor para capturar a venda
fetch('/venda/processar-biometria', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ decision: detail.decision, jwt: detail.jwt })
}).then(r => r.json()).then(data => {
document.getElementById('status').textContent =
data.aprovado ? 'Venda aprovada!' : 'Biometria não aprovada.';
});
}
if (type === 'OnError') {
window.removeEventListener('message', handleMessage);
document.getElementById('status').textContent = 'Erro: ' + detail.message;
}
}
try {
abrirMotor();
} catch (e) {
document.getElementById('btn-abrir').style.display = 'inline-block';
}
</script>
</body>
</html>
// Requer: github.com/webview/webview_go
// go get github.com/webview/webview_go
package biometria
import (
"encoding/json"
"fmt"
webview "github.com/webview/webview_go"
)
// BiometriaResultado representa o retorno do Motor após a captura.
type BiometriaResultado struct {
Decision string `json:"decision"` // "APPROVED", "DENIED" ou "CLOSE"
JWT string `json:"jwt"`
Base64 string `json:"base64"`
}
// AbrirMotorBiometria abre o Motor de Biometria em uma janela nativa
// motorURL = preAuthResponse.Biometria.Url retornada pelo POST /pre-autorizacoes/biometria
func AbrirMotorBiometria(motorURL, authorization, token, primaryColor string) (*BiometriaResultado, error) {
var resultado *BiometriaResultado
var errResult error
w := webview.New(false)
defer w.Destroy()
w.SetTitle("Validação Biométrica")
w.SetSize(900, 700, webview.HintNone)
w.Bind("goOnMessage", func(data string) {
if data == "loaded" || data == `"loaded"` {
initPayload, _ := json.Marshal(map[string]any{
"type": "OnInit",
"detail": map[string]any{
"authorization": authorization,
"token": token,
"theme": map[string]string{"primaryColor": primaryColor},
"allowedOrigin": "https://credsystem-biometria-webview-hml.credsystem.com.br/",
},
})
w.Eval(fmt.Sprintf("window.postMessage(%s, '*')", string(initPayload)))
return
}
var msg struct {
Type string `json:"type"`
Detail BiometriaResultado `json:"detail"`
}
if err := json.Unmarshal([]byte(data), &msg); err != nil {
return
}
switch msg.Type {
case "OnFinished":
resultado = &msg.Detail
w.Dispatch(func() { w.Terminate() })
case "OnError":
var errMsg struct {
Type string `json:"type"`
Detail struct {
Code int `json:"code"`
Message string `json:"message"`
} `json:"detail"`
}
if e := json.Unmarshal([]byte(data), &errMsg); e == nil {
errResult = fmt.Errorf("motor biometria error %d: %s", errMsg.Detail.Code, errMsg.Detail.Message)
} else {
errResult = fmt.Errorf("motor biometria: erro desconhecido")
}
w.Dispatch(func() { w.Terminate() })
}
})
w.Init(`
window.addEventListener('message', function(e) {
var data = typeof e.data === 'string' ? e.data : JSON.stringify(e.data);
goOnMessage(data);
});
`)
w.Navigate(motorURL)
w.Run()
return resultado, errResult
}
3. Alternativa: QR Code para Celular
Quando o cliente preferir usar o próprio celular — ou a aplicação não dispuser de câmera — exiba um QR Code gerado a partir da biometria.urlLinkExterno retornada pelo POST /pre-autorizacoes/biometria. O cliente escaneia o código com a câmera do celular, completa a captura no dispositivo móvel e o resultado retorna à aplicação normalmente.
// Exemplo: gerar QR Code no browser
// <script src="https://cdn.jsdelivr.net/npm/qrcode/build/qrcode.min.js"></script>
// <canvas id="qrcode-canvas"></canvas>
const urlQrCode = preAuthResponse.biometria.urlLinkExterno;
QRCode.toCanvas(
document.getElementById('qrcode-canvas'),
urlQrCode,
{ width: 256, errorCorrectionLevel: 'M' },
(err) => { if (err) console.error('Erro ao gerar QR Code:', err); }
);
- Aplicação ou dispositivo sem câmera, ou com câmera de difícil posicionamento para o cliente
- Cliente prefere usar o celular pessoal para a biometria
- Ambiente com alta demanda (o cliente avança enquanto o caixa prepara a venda)
4. Processar o Resultado
Após o encerramento do Motor, o campo decision indica o resultado da captura biométrica:
decision | Significado | Próximo passo |
|---|---|---|
APPROVED | Biometria validada com sucesso | Usar jwt para capturar a venda |
DENIED | Rosto não reconhecido | Cancelar pré-autorização, oferecer nova tentativa |
CLOSE | Usuário fechou a janela | Cancelar pré-autorização |
switch (resultado.decision) {
case 'APPROVED':
await capturarVenda({ preAutorizacaoId, biometriaJWT: resultado.jwt });
exibirMensagem('Venda aprovada com sucesso!');
break;
case 'DENIED':
await cancelarPreAutorizacao(preAutorizacaoId);
exibirErro('Biometria não reconhecida. Tente novamente.');
break;
case 'CLOSE':
await cancelarPreAutorizacao(preAutorizacaoId);
exibirErro('Processo cancelado pelo cliente.');
break;
}
📋 Requisitos Técnicos
Hardware Mínimo
| Componente | Especificação |
|---|---|
| Webcam | Resolução mínima 720p (1280x720) |
| Processador | Intel Core i3 ou equivalente |
| Memória RAM | 4 GB |
| Conexão Internet | Mínimo 5 Mbps (download/upload) |
Software
| Componente | Versão |
|---|---|
| Sistema Operacional | Windows 10+, Linux (Ubuntu 18.04+), macOS 10.14+ |
| Navegador | Google Chrome 85+ (recomendado: versão 124+) |
| Certificados SSL | TLS 1.2 ou superior |
APIs Necessárias
Para implementar o CredFace, você precisará integrar com:
- API de Venda: Para criar pré-autorizações e capturar vendas
- API de Biometria: Para validação facial
- API de Autenticação: Para obter tokens de acesso
🔧 Configuração da Aplicação
1. Instalação da Câmera
Certifique-se de que a câmera está:
- Corretamente instalada e reconhecida pelo sistema operacional
- Posicionada em altura adequada para captura facial (nível dos olhos do cliente), independente de ser PDV, totem ou outro dispositivo
- Com boa iluminação frontal (evitar contraluz)
2. Configuração do Navegador
O Motor de Biometria gerencia o acesso à câmera por conta própria — a aplicação não precisa solicitar permissão de câmera diretamente. Porém, o Chrome precisa ter permissão de câmera liberada para o domínio do Motor. Oriente o responsável pela integração a:
- Acessar
chrome://settings/content/camera - Garantir que
biometria.credsystem.com.brnão está bloqueado - Ou simplesmente aprovar o pop-up de permissão que o Chrome exibe na primeira vez que o Motor abre
🛡️ Segurança e Privacidade
Proteção de Dados
- Criptografia: Todas as imagens são criptografadas antes da transmissão
- Tokens JWT: Biometrias validadas retornam tokens assinados
- Não Armazenamento: Imagens biométricas não são armazenadas permanentemente
- LGPD Compliance: Conformidade com a Lei Geral de Proteção de Dados
Boas Práticas
// ✅ Correto: Usar HTTPS em todas as chamadas à API
const API_URL = 'https://app-bff-venda-hml.credsystem.com.br';
// ✅ Correto: Remover event listener após receber o resultado
window.addEventListener('message', function handler(event) {
const { type } = event.data ?? {};
if (type === 'OnFinished' || type === 'OnError') {
window.removeEventListener('message', handler); // Limpar listener
}
});
// ✅ Correto: Nunca logar o JWT da biometria em produção
// logEvent('BIOMETRIA_APROVADA', { vendaId, jwt }); // ❌ não faça isso
logEvent('BIOMETRIA_APROVADA', { vendaId, tempo: tempoMs }); // ✅ sem dados sensíveis
📊 Monitoramento e Logs
Eventos para Registrar
Registre os seguintes eventos para análise e troubleshooting:
const logEvent = (evento, detalhes) => {
console.log({
timestamp: new Date().toISOString(),
evento: evento,
detalhes: detalhes,
aplicacao: aplicacaoId,
estabelecimento: estabelecimentoId
});
};
// Exemplos de uso
logEvent('BIOMETRIA_INICIADA', { vendaId, valor });
logEvent('BIOMETRIA_APROVADA', { vendaId, tempo: tempoMs });
logEvent('BIOMETRIA_NEGADA', { vendaId, motivo });
logEvent('BIOMETRIA_ERRO', { vendaId, erro });
⚠️ Tratamento de Erros
Erros Comuns
| Erro | Causa | Solução |
|---|---|---|
| Câmera não encontrada | Webcam desconectada ou sem permissão | Verificar conexão e permissões do navegador |
| Timeout na captura | Cliente demorou muito para posicionar | Reiniciar processo de captura |
| Biometria negada | Face não reconhecida | Permitir nova tentativa ou método alternativo |
| Erro de conexão | Falha na comunicação com API | Verificar internet e tentar novamente |
Implementação de Retry
const capturarBiometriaComRetry = async ({ urlBiometria, authorization, token, theme }, maxTentativas = 3) => {
for (let tentativa = 1; tentativa <= maxTentativas; tentativa++) {
try {
const resultado = await capturarBiometria({ urlBiometria, authorization, token, theme });
return resultado;
} catch (error) {
console.error(`Tentativa ${tentativa} falhou:`, error);
if (tentativa === maxTentativas) {
throw new Error('Número máximo de tentativas excedido');
}
// Aguardar antes de tentar novamente
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
};
📚 Documentação Relacionada
Para implementar completamente o CredFace, consulte também:
- Motor de Biometria - Documentação técnica do motor de biometria
- Acordos WebView - Padrões de comunicação e eventos
- API de Venda Loja - Endpoints de pré-autorização e captura
- Autenticação - Como obter tokens de acesso
🆘 Suporte
Para dúvidas ou problemas com o CredFace, entre em contato com a equipe de suporte técnico: suporte.tecnico@credsystem.com.br