docs

Test mode

Test keys, MockAcquirerAdapter e cartões 4242 — como simular sucesso, decline, 3DS, chargeback e PIX/boleto sem tocar adquirente real.

Test mode é first-class na Zhex. Cada par de chaves (zk_test_* / zsk_test_*) opera num espaço isolado do ambiente de produção: dados de teste não vazam para reports financeiros, webhooks usam whsec_test_* separado, e a smart routing roteia tudo para o MockAcquirerAdapter em vez de adquirente real.

A regra mental é: test mode toca o mesmo Postgres que live, mas com livemode: false em todas as entidades. Você lista, retrieve, refunde, faz tudo igual — só não há dinheiro real movendo.

Test keys

No dashboard, Developers → API keys mostra os pares:

PrefixoOnde usar
zk_test_*Publishable, frontend (zhex.js em test)
zsk_test_*Secret, server-side em test
whsec_test_*Webhook signing em test (gerado por endpoint criado em test mode)

A Zhex rejeita uso cruzado: chave de um modo tentando acessar entidades do outro retorna 404 (genérico — não confirma existência cross-mode, evita leak).

Cartões de teste

A Zhex implementa o conjunto Stripe de PANs de teste — qualquer dev acostumado já reconhece. CVV pode ser qualquer 3 dígitos (4 para Amex), validade qualquer mês/ano no futuro.

Sucessos

PANComportamento
4242 4242 4242 4242Visa, sucesso direto
5555 5555 5555 4444Mastercard, sucesso

Declines

PANdecline_code
4000 0000 0000 0002card_declined (genérico)
4000 0000 0000 9995insufficient_funds
4000 0000 0000 9987lost_card
4000 0000 0000 9979stolen_card
4000 0000 0000 0069expired_card
4000 0000 0000 0127incorrect_cvc
4000 0000 0000 0119processing_error (retryable)

3DS

PANComportamento
4000 0000 0000 3220Força requires_action (3DS challenge)

Chargeback

PANComportamento
4000 0000 0000 0259Sucesso + simula charge.dispute.created
4000 0000 0000 1976Sucesso + simula chargeback product_not_received

Chargebacks de teste seguem o mesmo modelo de produção: reembolso compulsório, sem direito de resposta. Use para validar seu handler de charge.dispute.created (registro contábil, email para o cliente, revogação de acesso).

PIX em test mode

Não há QR real para escanear — você dispara o pagamento via test helper:

import { randomUUID } from 'node:crypto';

// 1. crie um intent PIX normalmente (com customer já existente)
const intent = await zhex.paymentIntents.create({
  amount: 4990,
  currency: 'brl',
  customer: 'cus_…',
  payment_method_types: ['pix'],
});

// 2. simule pagamento bem-sucedido
await fetch(
  `https://prometheus.zhex.io/v1/test_helpers/payment_intents/${intent.id}/succeed`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.ZHEX_TEST_KEY}`,
      'Idempotency-Key': randomUUID(),
    },
  },
);
// dispara webhook payment_intent.succeeded com livemode: false

Outras transições disponíveis em /v1/test_helpers/payment_intents/:id/:

EndpointResultado
succeedpayment_intent.succeeded
failpayment_intent.payment_failed com decline_code: insufficient_funds
expirepayment_intent.canceled (timeout PIX/boleto)

Test helpers só aceitam zsk_test_*/zrk_test_*. Chaves live retornam 403 test_mode_only.

Boleto em test mode

// 1. customer com document + endereço
const intent = await zhex.paymentIntents.create({
  amount: 4990,
  currency: 'brl',
  customer: 'cus_…',
  payment_method_types: ['boleto'],
});

// 2. simular pagamento via test helper
await fetch(
  `https://prometheus.zhex.io/v1/test_helpers/payment_intents/${intent.id}/succeed`,
  {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.ZHEX_TEST_KEY}` },
  },
);

PDFs reais não são gerados em test mode hoje — a renderização do boleto é função do checkout hosted, e em test mode ele exibe placeholders. O fluxo de webhook (payment_intent.succeeded) é o que importa para validar a integração.

Webhooks em test mode

Endpoints criados via Integrações → Webhooks com a chave zsk_test_* recebem eventos livemode: false. Boa prática:

  • Endpoint A (live): https://api.meusite.com/webhooks/zhexwhsec_live_*
  • Endpoint B (test): https://abc123.ngrok-free.app/webhooks/zhexwhsec_test_*

Ambos recebem o mesmo formato de evento. O campo livemode: false no payload permite seu handler decidir se aciona side effects reais (envio de email com nota fiscal, integração com SAP) ou apenas log.

if (!event.livemode) {
  console.log('[test] event:', event.type);
  return res.status(200).end();
}
// fluxo real de produção

Mode toggle no dashboard

O canto superior do dashboard mostra um toggle TEST / LIVE com banner amarelo no topo da tela em test. Listings (Transações, Customers, Produtos) filtram automaticamente pelo modo selecionado.

Limpeza de dados de teste

Test data nunca expira automaticamente (decisão deliberada — facilita debug de bug intermitente que aconteceu há 2 meses). Para limpar:

  • Manual no dashboard: Developers → Test data → Wipe. Confirma com WIPE digitado.
  • API: roadmap. Quando entrar, vai ficar em POST /v1/test_helpers/wipe com exclusão assíncrona.

Checklist antes de virar live

Antes de trocar zsk_test_* por zsk_live_* em produção:

Endpoints de webhook configurados em ambos os modos

Não esqueça do live. É erro clássico criar só o endpoint de test e mandar produção sem nenhum.

Fluxo 3DS testado

Use 4000 0000 0000 3220 para forçar requires_action e garantir que seu fluxo de retorno (via webhook payment_intent.succeeded) funciona.

Idempotency keys batem com sua estratégia de retry

Reuse a mesma Idempotency-Key em retries — sem isso, network flake duplica cobrança.

Erros declinados são tratados

Cliente vê mensagem útil em PT-BR, não card_declined cru.

Eventos críticos têm logs e alertas

payment_intent.succeeded, payment_intent.payment_failed, charge.dispute.created no mínimo.

Próximos passos

Esta página foi útil?

Atualizado em

Nesta página