Verificar Transações
Chame verify() em momentos sensíveis à segurança. O SDK coleta sinais do dispositivo, executa verificações de integridade do dispositivo e retorna a decisão de risco do backend.
verify() requer um JWT novo que o seu backend gera. O SDK nunca guarda uma chave de API da Surt - o seu backend guarda a chave sp_live_* (somente no lado do servidor) e a troca por um JWT de curta duração.
Uso Básico
Primeiro, obtenha um JWT novo do seu próprio backend e então passe-o para verify():
import { useGuardian } from '@surtai/guardian-rn';
// Seu backend chama o POST /geolocation/preflight da Surt com a
// chave de API sp_live_* e retorna o JWT gerado para o cliente.
async function fetchVerifyJwt(): Promise<string> {
const res = await fetch('https://your-api.com/guardian/jwt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
transaction_type: 'withdrawal',
transaction_name: 'User Payment',
}),
});
const { token } = await res.json();
return token;
}
function PaymentScreen() {
const { verify } = useGuardian();
const handlePayment = async () => {
try {
const jwt = await fetchVerifyJwt();
const result = await verify(jwt);
if (result.allowed) {
// Prosseguir com o pagamento
} else {
// Transação negada - verifique result.riskLevel
}
} catch (error) {
// Tratar erro do SDK (rede, não inicializado, jwt inválido, etc.)
}
};
return <Button onPress={handlePayment} title="Pay" />;
}
Sempre obtenha um JWT novo imediatamente antes de cada chamada verify(). Cada JWT é de uso único - reutilizar um JWT é rejeitado pelo backend.
Diagnóstico do resultado
O resultado de verify() inclui um objeto diagnostics opcional que descreve o que o SDK observou durante a transação. É aditivo - leia-o para mais visibilidade ou ignore-o.
const result = await verify(jwt);
if (result.diagnostics?.location === 'denied') {
// peça ao usuário para ativar a localização
}
diagnostics.location é collected · denied · unavailable · timeout · not_requested; diagnostics.networkIntel é collected · unavailable; diagnostics.warnings é um array de { code, signal }; diagnostics.timings (somente Android, v0.5.2+) traz milissegundos por fase mais total. Veja Códigos de Erro → Diagnóstico do resultado.
De Onde Vem o Contexto de Cliente e Transação
Na v0.3.0 o cliente não chama mais setCustomer() e não passa mais um tipo de transação para verify(). Em vez disso, o seu backend define todo esse contexto quando gera o JWT.
Quando o seu backend chama POST /geolocation/preflight, ele inclui customer_id, transaction_type e, opcionalmente, transaction_name, name e email. Esses valores são embutidos no JWT, então o cliente só precisa passar o token:
const jwt = await fetchVerifyJwt(); // backend definiu o contexto de cliente + transação
const result = await verify(jwt);
Tipos de Transação
Estes valores são enviados pelo seu backend no campo transaction_type do preflight. Eles não são passados para verify() no cliente.
| Tipo | Caso de uso |
|---|---|
login | Login do usuário |
sign_up | Criação de nova conta |
deposit | Adição de fundos |
withdrawal | Saque de fundos |
Substituição de Localização por Chamada
Substitua o padrão collectLocation para uma única chamada:
// Ignorar localização para esta chamada
const result = await verify(jwt, { collectLocation: false });
// Solicitar localização para esta chamada
const result = await verify(jwt, { collectLocation: true });
// Usar padrão de inicialização
const result = await verify(jwt);
A substituição é única. Ela afeta apenas aquela chamada verify().
Como a Coleta de Localização É Decidida
A coleta de localização tem dois níveis de controle, avaliados em conjunto. Ambos devem concordar para que os dados de GPS sejam coletados:
1. Painel Surt: GPS habilitado (maior prioridade)
A coleta de GPS deve estar habilitada no seu painel de cliente Surt. Se o GPS estiver desabilitado no painel, a localização nunca é coletada, independentemente do que você definir no código. Habilite-o em Configurações > Desenvolvedor ou entre em contato com o gerente da sua conta Surt.
2. Configuração do lado do cliente (seu código)
Isso é resolvido como: substituição por chamada > padrão de inicialização.
- Se você passar
{ collectLocation: true }paraverify(), isso prevalece sobre o valor de inicialização. - Se você passar
{ collectLocation: false }paraverify(), o GPS é ignorado mesmo se a inicialização estavatrue. - Se você omiti-lo, o padrão de inicialização do
GuardianProvider/initialize()é usado.
Na prática, isso significa:
| GPS no Painel | Seu código diz | Resultado |
|---|---|---|
| habilitado | true (init ou substituição) | GPS coletado |
| habilitado | false (init ou substituição) | Sem GPS: você optou por sair |
| desabilitado | true (init ou substituição) | Sem GPS: o painel está desativado |
| desabilitado | false (init ou substituição) | Sem GPS |
Sua configuração collectLocation no lado do cliente só pode optar por sair da coleta de localização. Ela não pode forçar a coleta de GPS se o painel a tiver desabilitada. Para habilitar a coleta de GPS, ative-a primeiro no seu painel de cliente Surt e então defina collectLocation: true no seu código.
Resultado da Verificação
interface VerificationResult {
allowed: boolean; // Decisão do backend - true = prosseguir
riskLevel: RiskLevel; // 'low' | 'medium' | 'high' | 'blocked' | 'unknown'
sessionId: string; // ID da transação para referência de suporte
errors?: string[]; // Mensagens de erro do backend, se houver
timestamp: number; // Timestamp da resposta (ms)
metadata?: Record<string, any>; // Metadados adicionais do backend
}
Para detalhes sobre níveis de risco, consulte Níveis de Risco.
Exemplo Completo
import React, { useState } from 'react';
import { View, Button, Text, Alert } from 'react-native';
import {
GuardianProvider,
useGuardian,
type VerificationResult,
} from '@surtai/guardian-rn';
// Seu backend chama o POST /geolocation/preflight da Surt com a
// chave de API sp_live_* e retorna o JWT gerado para o cliente.
async function fetchVerifyJwt(): Promise<string> {
const res = await fetch('https://your-api.com/guardian/jwt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
transaction_type: 'login',
transaction_name: 'User Login',
}),
});
const { token } = await res.json();
return token;
}
function HomeScreen() {
const { verify, collect, isInitialized } = useGuardian();
const [result, setResult] = useState<VerificationResult | null>(null);
const handleLogin = async () => {
try {
const jwt = await fetchVerifyJwt();
const res = await verify(jwt);
setResult(res);
Alert.alert(res.allowed ? 'Approved' : 'Denied', `Risk: ${res.riskLevel}`);
} catch (e: any) {
Alert.alert('Error', e.message);
}
};
return (
<View style={{ padding: 20 }}>
<Text>SDK Ready: {isInitialized ? 'Yes' : 'No'}</Text>
<Button title="Login & Verify" onPress={handleLogin} />
{result && <Text>Allowed: {result.allowed ? 'Yes' : 'No'}</Text>}
</View>
);
}
export default function App() {
return (
<GuardianProvider environment="production" collectLocation={true}>
<HomeScreen />
</GuardianProvider>
);
}