Skip to main content

O que é o SDK?

O SDK do Autorizou é a biblioteca oficial para criptografia de dados de cartão de crédito no frontend. Ele garante que informações sensíveis nunca trafeguem em texto puro pela rede, atendendo aos requisitos de segurança PCI DSS.

Principais Funcionalidades

Criptografia de Cartões

  • Criptografia AES-256-CBC no browser
  • Suporte a todas as principais bandeiras
  • Detecção automática de bandeira do cartão
  • Validação de dados antes da criptografia

3D Secure 2.0

  • Suporte completo ao protocolo 3DS2
  • Interface de challenge integrada
  • Callbacks configuráveis para sucesso/falha

Google Pay

  • Integração nativa com Google Pay
  • Criação de botões personalizados
  • Suporte a transações tokenizadas

Instalação

Via CDN

O domínio do script muda conforme o ambiente. Inclua-o na tag <head> ou antes do </body>:
AmbienteScript
Sandboxhttps://sdk.autorizou.dev/embed/gateway.js
Produçãohttps://sdk.autorizou.cloud/embed/gateway.js
<script src="https://sdk.autorizou.dev/embed/gateway.js"></script>

Uso Básico

1. Incluir o Script

<!DOCTYPE html>
<html>
<head>
  <title>Meu E-commerce</title>
  <script src="https://sdk.autorizou.dev/embed/gateway.js"></script>
</head>
<body>
  <!-- Seu conteúdo -->
</body>
</html>

2. Criptografar Dados do Cartão

// Preparar dados do cartão
const cardData = {
  number: '4111111111111111',
  holder: 'JOAO SILVA',
  expMonth: '12',
  expYear: '2030',
  securityCode: '123'
};

// Preparar dados do portador
const cardHolder = {
  name: 'João Silva',
  identification: {
    type: 'CPF',
    number: '12345678900'
  }
};

// Criptografar usando callbacks
await window.Autorizou.encryptCard(
  { cardData, cardHolder },
  {
    onSuccess: (response) => {
      console.log('Token criptografado:', response.token);
      // Enviar response.token para sua API
    },
    onError: (error) => {
      console.error('Erro na criptografia:', error.message);
    }
  }
);

3. Enviar para a API

const response = await fetch('https://zeus-sandbox.autorizou.dev/api/v1/cards', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ...',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    customer_id: 'cus_abc123',
    encrypted: result.token
  })
});

const card = await response.json();
console.log('Cartão salvo:', card);

Integração React/Next.js

Carregar SDK no Layout

// app/layout.js ou pages/_app.js
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html lang="pt-BR">
      <head>
        <Script
          src="https://sdk.autorizou.dev/embed/gateway.js"
          strategy="beforeInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Componente de Formulário

'use client';

import { useState } from 'react';

export default function CardForm({ customerId, onSuccess, onError }) {
  const [formData, setFormData] = useState({
    number: '',
    holder: '',
    expMonth: '',
    expYear: '',
    securityCode: ''
  });
  const [loading, setLoading] = useState(false);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({ ...prev, [name]: value }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);

    try {
      // 1. Verificar se o SDK está carregado
      if (!window.Autorizou?.encryptCard) {
        throw new Error('SDK não está carregado');
      }

      // 2. Criptografar dados usando callbacks
      await window.Autorizou.encryptCard(
        { cardData: formData },
        {
          onSuccess: async (encryptResult) => {
            try {
              // 3. Enviar para a API
              const response = await fetch('/api/cards', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                  customer_id: customerId,
                  encrypted: encryptResult.token
                })
              });

              if (!response.ok) {
                const error = await response.json();
                throw new Error(error.message || 'Erro ao salvar cartão');
              }

              const card = await response.json();
              onSuccess?.(card);

              // Limpar formulário
              setFormData({
                number: '',
                holder: '',
                expMonth: '',
                expYear: '',
                securityCode: ''
              });
            } catch (err) {
              console.error('Erro ao salvar:', err);
              onError?.(err);
            } finally {
              setLoading(false);
            }
          },
          onError: (error) => {
            console.error('Erro na criptografia:', error);
            onError?.(error);
            setLoading(false);
          }
        }
      );

    } catch (err) {
      console.error('Erro:', err);
      onError?.(err);
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div>
        <label htmlFor="number">Número do Cartão</label>
        <input
          id="number"
          name="number"
          type="text"
          value={formData.number}
          onChange={handleChange}
          placeholder="0000 0000 0000 0000"
          maxLength={19}
          required
        />
      </div>

      <div>
        <label htmlFor="holder">Nome no Cartão</label>
        <input
          id="holder"
          name="holder"
          type="text"
          value={formData.holder}
          onChange={handleChange}
          placeholder="NOME COMPLETO"
          style={{ textTransform: 'uppercase' }}
          required
        />
      </div>

      <div className="grid grid-cols-2 gap-4">
        <div>
          <label htmlFor="expMonth">Mês</label>
          <input
            id="expMonth"
            name="expMonth"
            type="text"
            value={formData.expMonth}
            onChange={handleChange}
            placeholder="MM"
            maxLength={2}
            required
          />
        </div>

        <div>
          <label htmlFor="expYear">Ano</label>
          <input
            id="expYear"
            name="expYear"
            type="text"
            value={formData.expYear}
            onChange={handleChange}
            placeholder="AAAA"
            maxLength={4}
            required
          />
        </div>
      </div>

      <div>
        <label htmlFor="securityCode">CVV</label>
        <input
          id="securityCode"
          name="securityCode"
          type="text"
          value={formData.securityCode}
          onChange={handleChange}
          placeholder="123"
          maxLength={4}
          required
        />
      </div>

      <button
        type="submit"
        disabled={loading}
        className="w-full bg-primary text-white py-2 rounded"
      >
        {loading ? 'Processando...' : 'Salvar Cartão'}
      </button>
    </form>
  );
}

API Route (Next.js)

// app/api/cards/route.js
import { NextResponse } from 'next/server';

export async function POST(request) {
  try {
    const body = await request.json();
    const { customer_id, encrypted } = body;

    // Validar dados
    if (!customer_id || !encrypted) {
      return NextResponse.json(
        { message: 'customer_id e encrypted são obrigatórios' },
        { status: 400 }
      );
    }

    // Enviar para Zeus API
    const response = await fetch('https://zeus-sandbox.autorizou.dev/api/v1/cards', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.AUTORIZOU_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ customer_id, encrypted })
    });

    const data = await response.json();

    if (!response.ok) {
      return NextResponse.json(data, { status: response.status });
    }

    return NextResponse.json(data);

  } catch (error) {
    console.error('Erro na API de cartões:', error);
    return NextResponse.json(
      { message: 'Erro interno do servidor' },
      { status: 500 }
    );
  }
}

Validações e Boas Práticas

Validação de Número de Cartão

function validateCardNumber(number) {
  // Remover espaços e caracteres não numéricos
  const cleaned = number.replace(/\D/g, '');

  // Verificar tamanho (13-19 dígitos)
  if (cleaned.length < 13 || cleaned.length > 19) {
    return false;
  }

  // Algoritmo de Luhn
  let sum = 0;
  let isEven = false;

  for (let i = cleaned.length - 1; i >= 0; i--) {
    let digit = parseInt(cleaned.charAt(i), 10);

    if (isEven) {
      digit *= 2;
      if (digit > 9) {
        digit -= 9;
      }
    }

    sum += digit;
    isEven = !isEven;
  }

  return sum % 10 === 0;
}

Validação de Data de Expiração

function validateExpiration(month, year) {
  const now = new Date();
  const currentYear = now.getFullYear();
  const currentMonth = now.getMonth() + 1;

  const expMonth = parseInt(month, 10);
  const expYear = parseInt(year, 10);

  // Validar mês
  if (expMonth < 1 || expMonth > 12) {
    return false;
  }

  // Validar ano (aceitar 2 ou 4 dígitos)
  const fullYear = expYear < 100 ? 2000 + expYear : expYear;

  // Verificar se não está expirado
  if (fullYear < currentYear) {
    return false;
  }

  if (fullYear === currentYear && expMonth < currentMonth) {
    return false;
  }

  return true;
}

Detecção de Bandeira

function detectCardBrand(number) {
  const cleaned = number.replace(/\D/g, '');

  const patterns = {
    visa: /^4/,
    mastercard: /^(5[1-5]|2[2-7])/,
    amex: /^3[47]/,
    elo: /^(4011|4312|4389|4514|4576|5041|5066|5067|6277|6362|6363|6504|6505|6516)/,
    diners: /^(36|38|30[0-5])/,
    discover: /^6(?:011|5)/,
    jcb: /^35/,
    hipercard: /^606282/
  };

  for (const [brand, pattern] of Object.entries(patterns)) {
    if (pattern.test(cleaned)) {
      return brand;
    }
  }

  return 'unknown';
}

Tratamento de Erros

Erros Comuns

try {
  const result = await window.Autorizou.encryptCard({ cardData });

  if (result.errors) {
    // Erros de validação do SDK
    switch (result.errors.message[0]) {
      case 'Número de cartão inválido':
        alert('Por favor, verifique o número do cartão');
        break;
      case 'Data de expiração inválida':
        alert('Cartão expirado ou data inválida');
        break;
      case 'CVV inválido':
        alert('CVV deve ter 3 ou 4 dígitos');
        break;
      default:
        alert('Erro na validação do cartão');
    }
    return;
  }

  // Continuar com o envio...

} catch (error) {
  // Erro de rede ou exceção
  console.error('Erro:', error);
  alert('Erro ao processar cartão. Tente novamente.');
}

Segurança

Boas Práticas

  1. Nunca armazene dados de cartão no localStorage ou sessionStorage
  2. Sempre use HTTPS em produção
  3. Valide dados no frontend antes de criptografar
  4. Implemente rate limiting no backend
  5. Use CSP (Content Security Policy) adequado

Content Security Policy

<meta http-equiv="Content-Security-Policy" content="
  default-src 'self';
  script-src 'self' https://sdk.autorizou.cloud https://sdk.autorizou.dev;
  connect-src 'self' https://zeus.autorizou.cloud;
  style-src 'self' 'unsafe-inline';
">

Fluxo Completo de Integração

Passo a Passo

  1. Incluir o SDK no projeto (via CDN)
  2. Coletar dados do cartão no formulário
  3. Validar dados localmente antes de enviar
  4. Criptografar usando window.Autorizou.encryptCard()
  5. Enviar token criptografado para sua API backend
  6. Backend encaminha para Zeus API
  7. Processar resposta e atualizar interface

Diagrama de Fluxo

[Browser] → SDK → [Token Criptografado] → [Seu Backend] → Zeus API

                                              [Cartão Tokenizado]

Troubleshooting

SDK não está carregado

Problema: window.Autorizou is undefined Solução:
// Verificar se o SDK está disponível
if (typeof window.Autorizou === 'undefined') {
  console.error('SDK não foi carregado. Verifique o script.');
  // Tentar recarregar ou mostrar mensagem ao usuário
}

Erro de CORS

Problema: Erro de Cross-Origin ao chamar a API Solução:
  • Sempre envie o token criptografado do seu backend para o Zeus
  • Nunca faça chamadas diretas do browser para zeus.autorizou.cloud

Token inválido

Problema: Backend retorna “invalid_encrypted_card” Possíveis causas:
  • Script do SDK incorreto para o ambiente (sandbox vs produção)
  • Dados do cartão em formato incorreto
  • Token corrompido durante transmissão
Solução:
// Verificar se a criptografia foi bem-sucedida
await window.Autorizou.encryptCard(
  { cardData },
  {
    onSuccess: (response) => {
      console.log('Token válido:', response.token);
      // Verificar se token não está vazio
      if (!response.token) {
        console.error('Token vazio!');
      }
    },
    onError: (error) => {
      console.error('Erro na criptografia:', error);
    }
  }
);

Perguntas Frequentes

Não. Basta incluir o script do SDK no ambiente correto. A criptografia acontece no browser e a descriptografia apenas no backend seguro do Zeus.
Sim, o SDK é compatível com:
  • React / Next.js
  • Vue / Nuxt.js
  • Angular
  • Svelte
  • Vanilla JavaScript
Basta incluir o script via CDN e usar window.Autorizou.
Sim. Use o script correspondente a cada ambiente:
  • Sandbox: https://sdk.autorizou.dev/embed/gateway.js
  • Produção: https://sdk.autorizou.cloud/embed/gateway.js
Recomendado mas não obrigatório. Validar localmente melhora a UX:
  • Algoritmo de Luhn para número do cartão
  • Validação de data de expiração
  • Formato do CVV (3-4 dígitos)
O SDK e o Zeus também fazem validações, mas feedback imediato é melhor.
Sem JavaScript, o SDK não funcionará. Considere:
  • Mostrar mensagem informativa
  • Oferecer método de pagamento alternativo
  • A maioria dos usuários tem JS habilitado

Boas Práticas de Segurança

✅ Faça

  • Use HTTPS em produção sempre
  • Implemente rate limiting no backend
  • Valide dados no frontend E backend
  • Use CSP (Content Security Policy)
  • Limpe o formulário após sucesso
  • Implemente timeout nas requisições

❌ Não Faça

  • Armazenar dados de cartão em localStorage/sessionStorage
  • Enviar dados de cartão em texto puro
  • Logar dados sensíveis no console em produção
  • Reutilizar tokens criptografados
  • Fazer chamadas diretas do browser para Zeus API

Exemplos Avançados

Formulário com Máscara

// Aplicar máscara no número do cartão
function formatCardNumber(value) {
  return value
    .replace(/\s/g, '')
    .replace(/(\d{4})/g, '$1 ')
    .trim();
}

<input
  type="text"
  value={cardNumber}
  onChange={(e) => {
    const formatted = formatCardNumber(e.target.value);
    setCardNumber(formatted);
  }}
  maxLength={19}
  placeholder="0000 0000 0000 0000"
/>

Detecção Automática de Bandeira

function detectBrand(number) {
  const cleaned = number.replace(/\s/g, '');

  if (/^4/.test(cleaned)) return 'visa';
  if (/^5[1-5]/.test(cleaned)) return 'mastercard';
  if (/^3[47]/.test(cleaned)) return 'amex';
  if (/^6(?:011|5)/.test(cleaned)) return 'discover';
  if (/^3(?:0[0-5]|[68])/.test(cleaned)) return 'diners';
  if (/^35/.test(cleaned)) return 'jcb';
  if (/^(4011|4312|4389|4514|4576|5041|5066|5067|636368)/.test(cleaned)) return 'elo';
  if (/^606282/.test(cleaned)) return 'hipercard';

  return 'unknown';
}

// Uso
const [brand, setBrand] = useState('');

useEffect(() => {
  if (cardNumber.length >= 4) {
    setBrand(detectBrand(cardNumber));
  }
}, [cardNumber]);

Loading States

const [loadingStates, setLoadingStates] = useState({
  encrypting: false,
  saving: false
});

const handleSubmit = async (e) => {
  e.preventDefault();

  setLoadingStates({ encrypting: true, saving: false });

  await window.Autorizou.encryptCard(
    { cardData },
    {
      onSuccess: async (encryptResult) => {
        setLoadingStates({ encrypting: false, saving: true });

        try {
          const response = await fetch('/api/cards', {
            method: 'POST',
            body: JSON.stringify({
              customer_id: customerId,
              encrypted: encryptResult.token
            })
          });

          if (!response.ok) throw new Error('Erro ao salvar');

          // Sucesso!
          setLoadingStates({ encrypting: false, saving: false });
        } catch (err) {
          setLoadingStates({ encrypting: false, saving: false });
          console.error(err);
        }
      },
      onError: () => {
        setLoadingStates({ encrypting: false, saving: false });
      }
    }
  );
};

Suporte e Recursos

Dúvidas? Entre em contato com nosso time de suporte técnico. Estamos aqui para ajudar!