Skip to main content
O SDK da FastPay fornece uma implementacao completa e simplificada de autenticacao 3D Secure (3DS) para transacoes com cartao de credito, garantindo maxima seguranca e reducao de fraudes.

Instalacao

Via NPM

npm install @fastpaybr/security-sdk

Via CDN

<script src="https://js.fastpaybrasil.com/security-sdk.min.js"></script>

Inicializacao

Configuracao Basica

import FastPayClient from '@fastpaybr/security-sdk'

const client = new FastPayClient({
  credentials: {
    publicKey: 'sua_api_key_publica'
  },
  debug: false
})

await client.initialize()

if (client.isThreeDSAvailable()) {
  console.log('3DS disponivel e pronto para uso')
}

Verificacao de Status

// Verificar se o SDK foi inicializado
if (client.isReady()) {
  console.log('SDK inicializado com sucesso')
}

// Verificar se 3DS esta disponivel
if (client.isThreeDSAvailable()) {
  console.log('3DS pronto para uso')
}

Fluxo de Autenticacao 3DS

Visao Geral do Fluxo

Processo Completo (Recomendado)

O metodo process() gerencia todo o fluxo de autenticacao automaticamente:
try {
  const result = await client.threeds.process(
    {
      // Dados da transacao
      amount: 100.00, // Valor na moeda especificada
      currency: 'BRL',
      installments: 1, // Numero de parcelas (1-12)

      // Dados do cartao
      card: {
        number: '4111111111111111',
        holderName: 'Joao Silva',
        expirationMonth: '12',
        expirationYear: '2025'
      },

      // Dados do cliente (necessarios para 3DS)
      customer: {
        name: 'Joao Silva',
        email: '[email protected]',
        phone: '5511987654321'
      },

      // Endereco do cliente
      address: {
        street: 'Rua das Flores',
        number: '123',
        complement: 'Apto 45',
        zipCode: '12345678',
        neighborhood: 'Centro',
        city: 'Sao Paulo',
        state: 'SP',
        country: 'BRA'
      }
    },
    {
      // Opcoes (todas opcionais)
      fingerprintingTimeout: 30000, // Timeout para fingerprinting (recomendado: 30s)
      challengeTimeout: 180000, // Timeout para challenge (recomendado: 3min)
      modal: {
        width: '600px', // Largura do modal
        height: '600px', // Altura do modal
        showCloseButton: true // Mostrar botao de fechar
      }
    }
  )

  // Resultado da autenticacao
  console.log('Autenticacao concluida:', result)

  // Usar dados na criacao da cobranca
  const charge = await createCharge({
    // ... outros dados da cobranca
    threeDS: result
  })
} catch (error) {
  console.error('Erro na autenticacao 3DS:', error)
}

Estrutura do Resultado

interface ChallengeResultResponse {
  type: 'full' | 'partial' | 'none'
  state: 'success' | 'failure' | 'unenrolled' | 'error' | 'unsupported_brand' | 'disabled'

  // Dados da autenticacao (quando state === 'success')
  cryptogram?: string // CAVV/AAV
  directoryServerTransactionId?: string // DS Transaction ID
  threeDsServerTransactionId?: string // 3DS Server Transaction ID
  acsTransactionId?: string // ACS Transaction ID
  eci?: string // Electronic Commerce Indicator
  version?: string // Versao do protocolo 3DS
}

Estados de Autenticacao

EstadoDescricaoAcao Recomendada
successAutenticacao bem-sucedidaProsseguir com a cobranca
failureCliente falhou na autenticacaoRejeitar transacao ou solicitar outro metodo
unenrolledCartao nao inscrito no 3DSAvaliar politica de risco
errorErro no processo de autenticacaoTentar novamente ou usar outro metodo
unsupported_brandBandeira nao suporta 3DSUsar outro metodo de pagamento
disabled3DS desabilitado para este cartaoAvaliar politica de risco

Customizacao do Modal

Container Personalizado

Voce pode fornecer seu proprio container para o iframe do challenge:
// Criar container personalizado
const customContainer = document.getElementById('my-3ds-container')

const result = await client.threeds.process({
  // ... dados da transacao
  challengeContainer: customContainer
})
<div id="my-3ds-container" style="width: 500px; height: 500px;"></div>

Desabilitar Modal Automatico

const result = await client.threeds.process(
  {
    // ... dados
    challengeContainer: document.getElementById('my-container')
  },
  {
    modal: false // Desabilita modal automatico
  }
)

Customizar Aparencia do Modal

const result = await client.threeds.process(
  {
    /* ... dados */
  },
  {
    modal: {
      width: '800px',
      height: '700px',
      closeOnOverlayClick: false, // Impede fechar ao clicar fora
      showCloseButton: false // Oculta botao de fechar
    }
  }
)

Exemplos de Implementacao

React

import { useState } from 'react'
import FastPayClient from '@fastpaybr/security-sdk'

function CheckoutForm() {
  const [loading, setLoading] = useState(false)
  const [result, setResult] = useState(null)

  const handleSubmit = async (formData) => {
    setLoading(true)

    try {
      const client = new FastPayClient({
        credentials: { publicKey: process.env.REACT_APP_FASTPAY_KEY }
      })

      await client.initialize()

      if (!client.isThreeDSAvailable()) {
        throw new Error('3DS nao disponivel')
      }

      const threeDSResult = await client.threeds.process({
        amount: formData.amount,
        currency: 'BRL',
        card: {
          number: formData.cardNumber,
          holderName: formData.cardHolder,
          expirationMonth: formData.expMonth,
          expirationYear: formData.expYear
        },
        customer: {
          name: formData.customerName,
          email: formData.customerEmail,
          phone: formData.customerPhone
        },
        address: formData.address
      })

      if (threeDSResult.state === 'success') {
        // Criar cobranca com dados 3DS
        const charge = await createCharge({
          ...formData,
          threeDS: threeDSResult
        })

        setResult(charge)
      } else {
        throw new Error(`Autenticacao falhou: ${threeDSResult.state}`)
      }
    } catch (error) {
      console.error('Erro:', error)
      alert(error.message)
    } finally {
      setLoading(false)
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      {/* Campos do formulario */}
      <button type='submit' disabled={loading}>
        {loading ? 'Processando...' : 'Finalizar Pagamento'}
      </button>
    </form>
  )
}

Vanilla JavaScript

<!DOCTYPE html>
<html>
  <head>
    <title>Checkout com 3DS</title>
  </head>
  <body>
    <form id="checkout-form">
      <!-- Campos do formulario -->
      <button type="submit">Pagar</button>
    </form>

    <script src="https://js.fastpaybrasil.com/security-sdk.min.js"></script>
    <script>
      let client = null

      async function initializeSDK() {
        client = new FastPay.FastPayClient({
          credentials: {
            publicKey: 'sua_chave_publica'
          }
        })

        await client.initialize()

        if (!client.isThreeDSAvailable()) {
          alert('3DS nao disponivel no momento')
        }
      }

      document.getElementById('checkout-form').addEventListener('submit', async (e) => {
        e.preventDefault()

        try {
          const result = await client.threeds.process({
            amount: 100.00,
            currency: 'BRL',
            card: {
              number: document.getElementById('card-number').value,
              holderName: document.getElementById('card-holder').value,
              expirationMonth: document.getElementById('exp-month').value,
              expirationYear: document.getElementById('exp-year').value
            },
            customer: {
              name: document.getElementById('name').value,
              email: document.getElementById('email').value,
              phone: document.getElementById('phone').value
            },
            address: {
              // ... dados do endereco
            }
          })

          if (result.state === 'success') {
            // Criar cobranca
            console.log('3DS completo:', result)
          }
        } catch (error) {
          console.error('Erro:', error)
        }
      })

      // Inicializar ao carregar a pagina
      initializeSDK()
    </script>
  </body>
</html>

Vue.js

<template>
  <form @submit.prevent="handleSubmit">
    <!-- Campos do formulario -->
    <button type="submit" :disabled="loading">
      {{ loading ? 'Processando...' : 'Pagar' }}
    </button>
  </form>
</template>

<script>
import FastPayClient from '@fastpaybr/security-sdk'

export default {
  data() {
    return {
      loading: false,
      client: null
    }
  },

  async mounted() {
    this.client = new FastPayClient({
      credentials: {
        publicKey: process.env.VUE_APP_FASTPAY_KEY
      }
    })

    await this.client.initialize()
  },

  methods: {
    async handleSubmit() {
      if (!this.client.isThreeDSAvailable()) {
        alert('3DS nao disponivel')
        return
      }

      this.loading = true

      try {
        const result = await this.client.threeds.process({
          // ... dados da transacao
        })

        if (result.state === 'success') {
          // Criar cobranca
          await this.createCharge(result)
        }
      } catch (error) {
        console.error('Erro:', error)
      } finally {
        this.loading = false
      }
    }
  }
}
</script>

Metodos Disponiveis

client.initialize()

Inicializa o SDK e carrega os provedores de 3DS disponiveis.
await client.initialize()
Retorno: Promise<void>

client.isReady()

Verifica se o SDK foi inicializado com sucesso.
const ready = client.isReady()
Retorno: boolean

client.isThreeDSAvailable()

Verifica se o 3DS esta disponivel e pronto para uso.
const available = client.isThreeDSAvailable()
Retorno: boolean

client.threeds.process(request, options)

Executa o fluxo completo de autenticacao 3DS. Parametros:
interface ThreeDSProcessRequest {
  amount: number // Valor na moeda especificada
  currency: string // Codigo da moeda (ex: BRL, USD)
  installments?: number // Numero de parcelas (1-12)
  card: {
    number: string // Numero do cartao
    holderName?: string // Nome do titular
    expirationMonth: string // Mes de expiracao (1-12)
    expirationYear: string // Ano de expiracao (4 digitos)
  }
  customer: {
    name: string // Nome completo
    email: string // Email do cliente
    phone: string // Telefone com codigo do pais
  }
  address: {
    street: string // Logradouro
    number: string // Numero
    complement?: string // Complemento (opcional)
    zipCode: string // CEP
    neighborhood: string // Bairro
    city: string // Cidade
    state: string // Estado
    country: string // Pais (codigo ISO 3166-1 alpha-3)
  }
  challengeContainer?: HTMLElement // Container customizado para o challenge
}

interface ThreeDSProcessOptions {
  fingerprintingTimeout?: number // Timeout para fingerprinting em ms (padrao: 30000)
  challengeTimeout?: number // Timeout para challenge em ms (padrao: 180000)
  modal?:
    | {
        width?: string // Largura do modal (padrao: '500px')
        height?: string // Altura do modal (padrao: '600px')
        closeOnOverlayClick?: boolean // Fechar ao clicar fora (padrao: true)
        showCloseButton?: boolean // Mostrar botao X (padrao: true)
      }
    | false // false para desabilitar modal automatico
}
Retorno: Promise<ChallengeResultResponse>

Integracao com API de Cobrancas

Apos obter o resultado do 3DS, use-o na criacao da cobranca:
// 1. Executar autenticacao 3DS
const threeDSResult = await client.threeds.process({
  amount: 100.00,
  currency: 'BRL',
  card: {
    /* ... */
  },
  customer: {
    /* ... */
  },
  address: {
    /* ... */
  }
})

// 2. Criar cobranca incluindo dados 3DS
const charge = await fetch('https://api-global.fastpaybrasil.com/v1/charges', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${credentials}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: 100.00,
    currency: 'BRL',
    customer: {
      name: 'Joao Silva',
      email: '[email protected]',
      document: {
        type: 'cpf',
        id: '12345678900'
      },
      phone: '5511987654321'
    },
    paymentMethod: {
      type: 'credit_card',
      cardNumber: '4111111111111111',
      cardholderName: 'Joao Silva',
      expirationMonth: '12',
      expirationYear: '2025',
      cvv: '123',
      installments: 1,
      // Incluir dados 3DS
      threeDS: threeDSResult
    },
    items: [
      {
        title: 'Produto XYZ',
        type: 'digital',
        description: 'Descricao',
        unit_price: 10000,
        quantity: 1
      }
    ]
  })
})

const result = await charge.json()
console.log('Cobranca criada:', result)

Cenarios de Validacao

SituacaoComportamento
3DS nao fornecidoCobranca recusada com erro 3ds_required
state !== 'success'Cobranca recusada com erro especifico do estado
Dados incompletosCobranca recusada com erro 3ds_incomplete
Tudo OKCobranca prossegue normalmente

Exemplos de Erros

{
  "id": "charge_id",
  "status": "refused",
  "reason": "3ds_required: 3D Secure authentication is required for this merchant. Please complete 3DS authentication before creating a charge."
}
{
  "id": "charge_id",
  "status": "refused",
  "reason": "3ds_failed: The cardholder failed to authenticate. Please try again or use a different card."
}

Tratamento de Erros

Erros Comuns

try {
  const result = await client.threeds.process({
    /* ... */
  })
} catch (error) {
  if (error.message.includes('not available')) {
    // 3DS provider nao esta disponivel
    console.error('3DS nao disponivel no momento')
  } else if (error.message.includes('timeout')) {
    // Timeout no processo
    console.error('Timeout na autenticacao')
  } else if (error.message.includes('container')) {
    // Container nao fornecido quando necessario
    console.error('Container para challenge nao fornecido')
  } else {
    // Outros erros
    console.error('Erro desconhecido:', error)
  }
}

Estados de Erro no Resultado

const result = await client.threeds.process({
  /* ... */
})

switch (result.state) {
  case 'success':
    // Autenticacao bem-sucedida
    break

  case 'failure':
    // Cliente falhou na autenticacao
    alert('Autenticacao falhou. Tente novamente ou use outro cartao.')
    break

  case 'unenrolled':
    // Cartao nao inscrito no 3DS
    // Decisao de negocio: aceitar ou recusar
    break

  case 'error':
    // Erro no processo
    alert('Erro na autenticacao. Tente novamente.')
    break

  case 'unsupported_brand':
    // Bandeira nao suporta 3DS
    alert('Este cartao nao suporta 3D Secure.')
    break

  case 'disabled':
    // 3DS desabilitado
    alert('3D Secure esta desabilitado para este cartao.')
    break
}

Boas Praticas

1. Sempre Inicializar Antes de Usar

// Errado
const result = await client.threeds.process({
  /* ... */
})

// Correto
await client.initialize()
if (client.isThreeDSAvailable()) {
  const result = await client.threeds.process({
    /* ... */
  })
}

2. Tratar Todos os Estados

const result = await client.threeds.process({
  /* ... */
})

// Sempre trate todos os estados possiveis
if (result.state === 'success') {
  // Prosseguir com cobranca
} else {
  // Lidar com falha de acordo com sua politica de negocio
  handleAuthenticationFailure(result.state)
}

3. Usar Variaveis de Ambiente

// Errado - chave exposta
const client = new FastPayClient({
  credentials: { publicKey: 'pk_abc123' }
})

// Correto - usar variaveis de ambiente
const client = new FastPayClient({
  credentials: { publicKey: process.env.FASTPAY_PUBLIC_KEY }
})

4. Implementar Loading States

// Mostrar feedback visual ao usuario
setLoading(true)
try {
  const result = await client.threeds.process({
    /* ... */
  })
  // Processar resultado
} finally {
  setLoading(false)
}

5. Log de Debug em Desenvolvimento

const client = new FastPayClient({
  credentials: { publicKey: 'your_key' },
  debug: process.env.NODE_ENV === 'development' // Apenas em dev
})

6. Configuracao de Timeouts

Os valores padrao sao otimizados para producao. Ajuste apenas se necessario:
const result = await client.threeds.process(
  {
    /* ... */
  },
  {
    fingerprintingTimeout: 30000, // Recomendado: 30s (nao aumente alem de 45s)
    challengeTimeout: 180000 // Recomendado: 3min (nao aumente alem de 5min)
  }
)
Importante:
  • Fingerprinting: 30s e suficiente. Valores maiores podem indicar problemas de rede
  • Challenge: 3min e o ideal. Timeouts muito longos prejudicam a conversao
  • Em caso de timeout frequente, investigue a causa raiz ao inves de aumentar o valor

Troubleshooting

Possiveis causas:
  • O fluxo foi frictionless (sem challenge necessario)
  • O modal foi bloqueado por pop-up blocker
  • Container customizado com display:none
Solucao:
// Verificar se challenge foi necessario
console.log('Resultado:', result)

// Garantir que container esta visivel
const container = document.getElementById('container')
container.style.display = 'block'

Timeout no fingerprinting

Possiveis causas:
  • Conexao de internet lenta do cliente
  • Problemas no provedor 3DS
  • Bloqueio de scripts no navegador
Solucao:
// Apenas se necessario, aumente moderadamente (max. 45s)
const result = await client.threeds.process(
  {
    /* ... */
  },
  { fingerprintingTimeout: 45000 } // 45s (nao recomendado acima disso)
)
Importante: Timeouts frequentes indicam problemas que devem ser investigados, nao apenas contornados

Erro “3DS provider not available”

Possiveis causas:
  • SDK nao foi inicializado
  • Nenhum provider 3DS configurado no backend
  • Erro na inicializacao do provider
Solucao:
await client.initialize()

if (!client.isThreeDSAvailable()) {
  console.error('3DS nao disponivel. Verifique a configuracao no backend.')
  // Implementar fallback ou notificar usuario
}

Erro “container is required”

Causa: Modal desabilitado sem fornecer container customizado Solucao:
// Opcao 1: Usar modal automatico (padrao)
const result = await client.threeds.process({
  /* ... */
})

// Opcao 2: Fornecer container se modal desabilitado
const result = await client.threeds.process(
  {
    /* ... */
    challengeContainer: document.getElementById('my-container')
  },
  { modal: false }
)

Dados do cartao invalidos

Solucao:
// Validar dados antes de chamar o SDK
if (!isValidCardNumber(cardNumber)) {
  alert('Numero do cartao invalido')
  return
}

if (!isValidExpiration(month, year)) {
  alert('Data de validade invalida')
  return
}