Visão geral
A submissão do lado do cliente assenta em três garantias:- Vinculação do sujeito resistente a spoofing. O token fica associado a um único
vendor_data(o identificador do seu utilizador) no momento da emissão. A identidade do sujeito de cada transação submetida com o token é imposta do lado do servidor a partir desta associação, pelo que um cliente adulterado não consegue submeter em nome de outro utilizador, e o o payload nunca precisa de incluir credenciais. - Informação automática sobre o dispositivo. O SDK recolhe uma impressão digital do dispositivo e envia-a com a submissão, e a Didit deriva do lado do servidor o endereço IP e o user agent. O contexto combinado do dispositivo fica associado ao sujeito da transação sem biblioteca adicional, sem token de dispositivo separado e sem trabalho de integração da sua parte. Alimenta as regras baseadas no dispositivo e a correlação de transações e sessões relacionadas pelo dispositivo.
- Prova de controlo da carteira lançada automaticamente. Quando a transação criada exige que o utilizador final prove o controlo de uma carteira, a resposta inclui um bloco
action_requireddo tipowallet_ownershipe o SDK abre esse fluxo de imediato, atualizando depois a transação quando terminar - sem ciclos de polling nem envio de ligações que tenha de construir. Uma açãoverification_sessionobrigatória é diferente: nunca é lançada automaticamente e é devolvida no mesmo bloco para que a sua aplicação a lance com a sua própria integração de verificação da Didit.
A chamada do lado do servidor,
POST /v3/transactions/, continua a ser a escolha certa quando não há nenhum utilizador final presente: transferências de back-office, importações em lote ou eventos reportados pelos seus próprios sistemas.
Ambos os caminhos criam os mesmos registos de transação, executam as mesmas regras e emitem os mesmos webhooks.Fluxo
1
Emitir um token de transação
O seu backend chama
POST /v3/transactions/sdk-token/ com a sua chave de API e o vendor_data do utilizador, e entrega o sdk_token devolvido à sua aplicação.2
Submeter a partir do dispositivo
A aplicação chama
submitTransaction no SDK, que envia o payload para POST /v1/transactions/ com o cabeçalho X-Transaction-Token e o enriquecimento automático do dispositivo.3
Tratar qualquer ação obrigatória
Se
action_required.type for wallet_ownership, o SDK lança automaticamente o widget e depois atualiza a transação através de GET /v1/transactions/{transaction_id}/.
Se for verification_session, o SDK não lança nada - leia action_required e inicie o seu próprio fluxo de verificação com o respetivo session_token (ou url, na web).Emitir um token de transação
Emita os tokens a partir do seu backend comPOST /v3/transactions/sdk-token/ - a mesma autenticação por chave de API que o resto dos endpoints de transação /v3/.
Os aliases em camelCase (
vendorData, ttlSeconds, maxUses) também são aceites, tal como no resto da API /v3/.
Submeter a partir do dispositivo
Os SDK enviam um pedido aPOST /v1/transactions/ com o token no cabeçalho X-Transaction-Token.
O payload enviado na rede usa camelCase. Os métodos submitTransaction montam-no por si, por isso só precisa de trabalhar diretamente com ele ao chamar o endpoint a partir do seu próprio cliente HTTP:
POST /v3/transactions/:
A resposta tem o mesmo detalhe de transação em snake_case dos endpoints
/v3/, acrescido do bloco action_required:
Declarar uma carteira autocustodiada
O exemplo acima declara o destino como a carteira autocustodiada do próprio utilizador: opaymentMethod.type da contraparte é unhosted_wallet.
Esta declaração altera a forma como corre a troca de Travel Rule:
- A Didit não encaminha a transferência através de um VASP contraparte, porque não existe nenhum VASP por trás de uma carteira autocustodiada, e cria a transferência diretamente em
UNCONFIRMED_OWNERSHIP. - Quando
auto_wallet_verificationestá ativo nas suas definições de Travel Rule (o valor por omissão), é criada automaticamente uma sessão do widget de propriedade da carteira e devolvida emaction_required, tal como na resposta acima. - O SDK abre o widget automaticamente. Quando o utilizador prova o controlo da carteira, a transferência faz a comparação de nomes e passa a
COMPLETED, ou aCOUNTERPARTY_MISMATCHED_DATAse o nome não corresponder ao titular do livro de endereços da carteira.
Aplicação das regras ao sujeito
Três aspetos são sempre decididos pelo token, nunca pelo payload:- A aplicação em que a transação é criada.
- A identidade do sujeito: o
subject.externalUserIddo payload é ignorado e substituído pelovendor_datado token. - O contexto do dispositivo do sujeito (ver abaixo); os campos derivados no servidor prevalecem em caso de conflito com o que for enviado em
subject.device.
401 devolvido por este endpoint significa que o token foi rejeitado: em falta, desconhecido, revogado, acima do seu max_uses ou expirado.
As respostas de token expirado contêm sempre a palavra expired no detalhe do erro, e é assim que os SDK distinguem os erros expired_token dos erros invalid_token.
Ler a transação
GET /v1/transactions/{transaction_id}/ devolve o mesmo detalhe, com a mesma autenticação por X-Transaction-Token.
Os SDK chamam-no automaticamente depois de um fluxo de ação lançado terminar ou de a sua janela fechar, para que o estado final nunca dependa de um único evento ou notificação.
Pode usá-lo você próprio para voltar a verificar status e action_required em qualquer momento enquanto o token for válido. A partir do seu backend, GET /v3/transactions/{transaction_id}/ devolve o mesmo registo.
Inteligência de dispositivo automática
Cada submissão inclui inteligência de dispositivo sem qualquer trabalho de integração da sua parte:- O SDK recolhe uma impressão digital do dispositivo que respeita a privacidade (o esquema
didit-fp-v2: sinais de plataforma e do navegador, um identificador persistente do dispositivo, uma pontuação de bot e um hash composto) e envia-a com o pedido. - A Didit deriva o endereço IP, o user agent e o accept-language do lado do servidor, a partir da própria ligação, pelo que não podem ser falsificados através do payload.
/v3/ submetidas pelo servidor podem continuar a enviar objetos device_context explícitos por participante. No caminho do SDK, obtém a mesma informação numa versão mais completa, sem configuração adicional.
Ações necessárias do utilizador
Algumas transações exigem que o utilizador final faça algo antes de poderem ser concluídas: uma regra pode exigir uma sessão de verificação, ou uma transferência da Travel Rule pode exigir prova de que a carteira de destino pertence de facto ao utilizador. Ambos os casos aparecem no mesmo local, no blocoaction_required da resposta de submissão (e em todas as leituras seguintes da transação):
Se ambos puderem aplicar-se à mesma transação,
wallet_ownership tem prioridade, porque a prova de propriedade em falta bloqueia a própria troca da Travel Rule.
action_required passa a null quando a ação pendente estiver resolvida.
O campo remediation existente mantém-se por compatibilidade com versões anteriores; action_required é o bloco canónico.
Contrato de abertura automática
autoLaunchAction (predefinição true) abre automaticamente apenas a ação wallet_ownership:
- Web - aberta no modal sobreposto do próprio SDK, com a conclusão detetada por mensagens com validação de origem e por uma consulta limitada no tempo à transação (nunca dependente de um único evento).
- iOS / Android (e os wrappers React Native e Flutter, que delegam nos SDK nativos) - apresentada como a experiência nativa de propriedade da carteira do SDK (SwiftUI / Jetpack Compose) quando
useNativeWalletOwnershipétrue(o valor predefinido), recorrendo aoSFSafariViewController/ a um Chrome Custom Tab e, por fim, ao navegador predefinido. Depois de o fluxo ser fechado ou de a aplicação voltar ao primeiro plano, o SDK volta a ler a transação automaticamente.
verification_session nunca é aberta automaticamente: aparece sempre em action_required para que a sua aplicação a inicie com a sua própria integração de verificação da Didit.
Depois de o fluxo de propriedade da carteira, aberto automaticamente pelo SDK, terminar ou ser fechado, o SDK volta a ler a transação e entrega o resultado atualizado ao seu callback onActionCompleted.
Uma ação verification_session não faz parte desse ciclo, uma vez que é a sua aplicação que a inicia - veja a secção seguinte.
Iniciar uma sessão de verificação
Quandoaction_required.type for verification_session, leia o bloco a partir de result.actionRequired e entregue-o à sua integração de verificação Didit existente:
GET /v1/transactions/{transaction_id}/ (ou aguarde pelo webhook da transação) para obter o estado atualizado da transação.
Exemplo: verificação biométrica reforçada para um levantamento de valor elevado
Este é o fluxo no seu melhor: sujeitar as transações de risco (montantes elevados, novos beneficiários, novos dispositivos) a uma nova verificação biométrica da mesma pessoa que foi verificada durante o onboarding. A tomada de controlo de uma conta tem exatamente este aspeto: palavra-passe correta, código 2FA correto (obtido por phishing ou com troca de cartão SIM), um levantamento para uma carteira que nunca viu. Nesse ponto, todas as defesas baseadas em credenciais já falharam. Mas o rosto não falha: o atacante não consegue passar uma selfie com prova de vida que tem de corresponder ao rosto capturado durante o onboarding KYC do titular legítimo.1
Crie a regra uma única vez, na consola
Transactions → Rules → Create Rule: condição
amount gte 5000, ação Change status → AWAITING_USER, e selecione o seu fluxo Autenticação biométrica na ação.
Acrescente as outras condições de risco que quiser (primeira vez com uma contraparte, nova impressão digital do dispositivo, alteração do país do IP) como condições ou regras adicionais.2
Submeta o levantamento como habitualmente
Nada muda no seu código de submissão. Quando a regra disparar, a resposta devolve
status: "AWAITING_USER" e um bloco action_required do tipo verification_session:3
Inicie a nova verificação
Entregue o
session_token (ou o url) à sua integração de verificação Didit existente, tal como indicado em Iniciar uma sessão de verificação.
Como a sessão é criada com o mesmo vendor_data do titular da transação, a Didit já tem o rosto de referência verificado do utilizador do onboarding (a selfie aprovada com prova de vida, a fotografia do passaporte armazenada no chip ou o retrato do documento).
O utilizador tira uma única selfie em tempo real; a Didit executa a prova de vida e uma correspondência facial 1:1 com essa referência guardada. Não há nova leitura do documento nem novo onboarding - apenas alguns segundos de fricção, e só nas transações que o justifiquem.4
Conclua conforme o resultado
Quando a sessão terminar, a transação é reavaliada automaticamente:
APPROVED se a nova verificação for aprovada, DECLINED se falhar, com um webhook transaction.status.updated em qualquer dos casos (reason: remediation_completed na cronologia da transação).
A sua aplicação obtém o resultado através de callbacks do tipo onActionCompleted, de GET /v1/transactions/{transaction_id}/ ou do webhook.Web SDK
submitTransaction está disponível atualmente no singleton do Web SDK:
{ transactionId, status, travelRuleStatus?, actionRequired? }.
No payload ao nível do SDK, escreve category, details e customProperties; o SDK mapeia-os por si para os aliases do protocolo (type, info, props).
Os erros são tipados através de DiditTransactionError:
SDKs nativos
A API nativa
submitTransaction é disponibilizada com os SDKs iOS e Android 4.1.0 (e com as versões React Native e Flutter que a fixam).
Ao contrário do Web SDK, os payloads nativos usam diretamente os nomes dos campos do protocolo: type, info e props.getTransaction(transactionToken, transactionId) para reler a transação com o mesmo token - os SDKs chamam-no por si após um fluxo de ação iniciado, e pode chamá-lo diretamente em qualquer momento.
Em dispositivos móveis, o transporte da impressão digital do dispositivo já é aplicado a todas as chamadas de rede dos SDKs, pelo que as submissões de transações transportam automaticamente a mesma inteligência de dispositivo.
Sem os SDKs
Tudo o que os SDKs fazem é HTTPS simples - nada aqui exige os SDKs. Duas formas de integração equivalentes: Apenas do lado do servidor (sem tokens). Submeta comPOST /v3/transactions/ a partir do seu backend, usando a sua chave de API. A resposta (e cada GET /v3/transactions/{transaction_id}/ seguinte) inclui o mesmo bloco action_required. Também pode enviar o contexto device explícito por participante, uma vez que não existe SDK que o recolha por si.
Do lado do cliente, com a sua própria infraestrutura HTTP. Gere um token com POST /v3/transactions/sdk-token/ e, depois, chame POST /v1/transactions/ e GET /v1/transactions/{transaction_id}/ a partir do dispositivo com o cabeçalho X-Transaction-Token - aplicam-se as mesmas regras de vinculação ao sujeito e de derivação de IP e agente do utilizador no servidor.
Depois, trate o action_required por conta própria:
E detete a conclusão sem qualquer callback do cliente:
- Webhooks (recomendados).
transaction.status.updateddispara quando a ação pendente resolve a transação, etravel_rule.status.updateddispara em cada transição do intercâmbio - ambos incluem informação suficiente para atualizar os seus registos sem necessidade de polling. - Polling. Releia a transação (
/v3/a partir do seu backend, ou/v1/com o token enquanto este for válido):action_requiredvolta anullquando for resolvido, estatus/travel_rule.statuscontêm o resultado.
Webhooks
O seu backend não precisa que a aplicação lhe comunique o resultado. Quando uma transação submetida exige ação do utilizador, o webhook de transação -transaction.created ou transaction.status.updated - inclui o mesmo bloco action_required, para que os seus sistemas saibam da ação pendente mesmo que a aplicação seja fechada antes de o fluxo terminar.
Uma ação verification_session vem com o estado AWAITING_USER, mas uma ação wallet_ownership não altera por si só o estado da transação, pelo que deve ler o action_required em vez do estado.
As transições do Travel Rule emitem adicionalmente travel_rule.status.updated.
Próximos passos
Submissão de transações
A API Create Transaction do lado do servidor e a referência completa do payload.
Travel Rule
O intercâmbio gerido entre ordenante e beneficiário, as definições e o ciclo de vida.
Widget de propriedade da carteira
O fluxo alojado de prova de controlo por trás das ações wallet_ownership.
Webhooks
transaction.created, transaction.status.updated e verificação de assinatura.
Regras
Ações de regras, incluindo as que criam sessões de verificação.
Estados
O que AWAITING_USER significa no ciclo de vida da transação.