Cartão de crédito e 3DS
O número do cartão vai do navegador direto para a operadora; o seu servidor cobra com um token. Todo cartão passa pela confirmação do banco (3DS 2.0).
Fluxo do cartão
- Servidor:
GET /checkout-configcom o valor do carrinho →chave_publica,ambientee as parcelas aceitas. - Navegador:
YuupePay.tokenizarCartao()→token_cartao(vale 5 minutos) edispositivo. - Servidor:
POST /pedidoscom o token, o dispositivo, o comprador completo e o IP. Resposta: sempreaguardando_autenticacao, com o objetoautenticacao. Nada foi cobrado ainda. - Navegador:
YuupePay.autenticar(autenticacao). O pay.js coleta os dados do dispositivo para o banco; o banco aprova direto ou pede confirmação (app ou SMS) numa janela sobre a página. - Yuupe: só com a autenticação concluída a cobrança é feita.
- Resultado: webhook
pedido.aprovadooupedido.recusado, ouGET /pedidos/{id}. Sempre confirme no servidor.
Configuração do checkout
GET/checkout-config?valor_centavos=curl "https://yuupe.me/api/v1/pay/checkout-config?valor_centavos=15980" \
-H "Authorization: Bearer yp_test_SUA_CHAVE"
# → {
# "ambiente": "sandbox",
# "chave_publica": "…",
# "pix_ativo": true,
# "pix_validade_min": 1440,
# "opcoes_parcelamento": [
# { "parcelas": 1, "valor_parcela_centavos": 15980 },
# { "parcelas": 2, "valor_parcela_centavos": 7990 }
# ]
# }Criar o pedido
POST/pedidosAlém dos campos do Pix (comprador com documento e endereço, itens):
| Campo | Descrição |
|---|---|
metodoobrigatório"cartao" | Forma de pagamento. |
token_cartaoobrigatóriostring | Gerado pelo pay.js. Vale 5 minutos e uma cobrança. |
dispositivoobrigatórioDispositivo | Devolvido por tokenizarCartao. Repasse como veio. |
parcelasinteger | 1 a 12, dentro de opcoes_parcelamento. Padrão: 1. |
X-Yuupe-IP-Compradorobrigatóriocabeçalho | IP do navegador do comprador. |
comprador.telefonestring | Recomendado: melhora a aprovação no 3DS e no antifraude. |
curl -X POST https://yuupe.me/api/v1/pay/pedidos \
-H "Authorization: Bearer yp_test_SUA_CHAVE" \
-H "Content-Type: application/json" \
-H "X-Yuupe-IP-Comprador: 203.0.113.10" \
-d '{
"numero_pedido": "NIC-2026-000124",
"metodo": "cartao",
"parcelas": 2,
"token_cartao": "TOKEN_DO_PAY_JS",
"dispositivo": { "user_agent": "Mozilla/5.0 …", "idioma": "pt-BR", "tela_largura": 1440, "tela_altura": 900, "profundidade_cor": 24, "fuso_horas": -3, "java": false },
"comprador": {
"nome": "Maria Souza", "email": "maria@exemplo.com", "documento": "52998224725", "telefone": "+5561999990000",
"endereco": { "logradouro": "Rua das Flores", "numero": "123", "bairro": "Asa Sul", "cidade": "Brasília", "uf": "DF", "cep": "70000-000" }
},
"itens": [{ "descricao": "Passaporte Família", "quantidade": 1, "valor_unitario_centavos": 15980 }]
}'// Todo cartão começa assim (nada foi cobrado ainda):
{ "id": "…", "status": "aguardando_autenticacao",
"autenticacao": {
"pedido_id": "…", "etapa": "coleta",
"url": "https://centinelapi.cardinalcommerce.com/…", "token": "…",
"continuar_url": "https://yuupe.me/api/pay/3ds/…/continuar?n=…",
"expira_em": "2026-10-16T13:38:00-03:00"
} }
// Erro antes de começar (ex.: abaixo do mínimo), nada cobrado:
{ "erro": { "codigo": "valor_abaixo_minimo_3ds", "mensagem": "…",
"motivo": { "codigo": "valor_fora_do_permitido", "mensagem_comprador": "…", "tentar_novamente": "outro_meio" } } }Confirmação do banco (3DS)
Todo pedido no cartão volta aguardando_autenticacao: devolva autenticacao ao navegador, sem mexer nele, e chame:
// no navegador, com o objeto "autenticacao" que o seu servidor devolveu, como veio
try {
const r = await YuupePay.autenticar(pedido.autenticacao)
// 1. coleta os dados do dispositivo (iframe invisível, 1 a 3 s)
// 2. o banco aprova direto OU abre a janela de confirmação (app/SMS)
// 3. a Yuupe cobra e devolve r = { pedido_id, status } → "aprovado" ou "recusado", só para a tela
} catch (e) {
// e.codigo: "autenticacao_cancelada" (fechou a janela) ou "autenticacao_expirada" (5 min)
}
// depois, SEMPRE confirme no servidor: GET /pedidos/{id} (ou espere o webhook)- O comprador tem 5 minutos. Sem confirmação, o pedido vira
expirado(motivoautenticacao_expirou) e nada é cobrado. - Se o banco não confirmar, o pedido vira
recusadocom o motivoautenticacao_falhou, também sem cobrança. verificacao_3ds.responsabilidade_do_emissor = true: numa contestação por fraude, a responsabilidade é do banco do comprador.- Nova tentativa = novo pedido, com outro
numero_pedido.
Parcelamento
Mostre ao comprador só as opções de opcoes_parcelamento do checkout-config, que já respeitam o máximo de parcelas e a parcela mínima da loja para aquele valor. Fora delas, a API responde parcelas_nao_permitidas.
Valor mínimo
O cartão com 3DS vale a partir de R$ 5,00 em produção (R$ 600,00 no sandbox). Abaixo disso, o pedido volta com o erro valor_abaixo_minimo_3ds e o motivo valor_fora_do_permitido, antes de qualquer cobrança. Ofereça o Pix.