Credenciais

CredencialOnde vivePara que serve
PUBLISHABLE_KEY (pk_test_…/pk_live_…)Frontend + backendInicializa a SDK e identifica a aplicação.
CLIENT_IDSó backendIdentifica o parceiro na obtenção do token.
CLIENT_SECRETSó backendSegredo para obter o access_token.
WEBHOOK_SECRETSó backendVerifica a assinatura HMAC dos webhooks.
CLIENT_SECRET e WEBHOOK_SECRET nunca podem ir para o bundle do frontend. Mantém-nos em variáveis de ambiente no servidor.

applicationUUID

Várias chamadas à API pedem applicationUUID. É a tua PUBLISHABLE_KEY sem o prefixo:
const applicationUUID = PUBLISHABLE_KEY.replace(/^pk_(test|live)_/, '');

Ambientes

AmbientePrefixo da chaveBase URL
Sandboxpk_test_…https://sandbox.api.faciconnect.com
Produçãopk_live_…https://api.faciconnect.com
Testa sempre todo o fluxo com pk_test_ antes de mudar para pk_live_. Produção exige HTTPS.

Ciclo de vida da ordem

Uma ordem tem três estados. A transição é dirigida pela FaciPay e confirmada pelo webhook.
EstadoSignificadoAção típica
PENPendenteAguardar (Multicaixa Express) ou mostrar referência (EMIS).
CONConfirmado / pagoFulfillment: confirmação, email, libertar produto.
CANCanceladoReabrir carrinho, libertar stock.

A fonte da verdade

O estado autoritativo de um pagamento vem sempre do webhook no teu backend, não dos callbacks do frontend. Os callbacks (onApprove, onPending, onCancel) servem para a experiência do utilizador; a confirmação de negócio (libertar produto, faturar) só acontece quando o webhook confirma CON. O endpoint GET /facipaypartner/paymentByExternalTransaction é apenas uma rede de segurança (fallback) para quando o webhook falha ou atrasa.

Idempotência

O externalTransactionId é a chave de idempotência. Garante que:
  • Cada ordem tem um externalTransactionId único (ex.: order_<UUID>).
  • Se um webhook chegar repetido para uma ordem já em estado final (CON/CAN), respondes 200 sem reprocessar.
function updateOrder(externalTransactionId, paymentStatus) {
  const order = db.orders.find(externalTransactionId);
  if (!order) return;
  if (order.status === 'CON' || order.status === 'CAN') return; // já final → não reprocessa
  db.orders.update(externalTransactionId, { status: paymentStatus });
}

Recebimentos e taxas

Próximo passo: Segurança

Verificação HMAC do webhook, passo a passo por framework.