---
agentTools:
  projectIndex: https://docs.ninepay.com.br/llms.txt
  projectSearch: https://docs.ninepay.com.br/agentSearch?query=term1%20term2
---

# Checkout embutido (ninepay.js)

Coloque o pagamento de uma fatura dentro da sua página, com o seu botão de pagar e o iframe da NinePay para cartão, PIX e boleto.

## Crie a fatura no servidor

> Linhas destacadas: 8

No seu servidor, com o token da API, crie a cobrança em aberto com `open: true` e os métodos que o iframe pode oferecer. Nada é cobrado na criação. Mande para a página só o `payment.uuid` da resposta; o token nunca vai para o navegador.

```bash
curl -X POST https://api.sandbox.cefispay.com.br/api/v1/payments \
  -H "Authorization: Bearer $NINEPAY_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "customer": { "id": 123 },
    "method": "credit",
    "open": true,
    "allowed_methods": ["credit", "pix", "billet"],
    "value": 5000,
    "due_date": "2026-11-10"
  }'
```

Antes, cadastre no dashboard (Integrações → Checkout embutido) o endereço do site que vai abrir o checkout; sem ele, o navegador recusa o iframe.

## Carregue o ninepay.js

> Linhas destacadas: 4-6

Carregue o script sempre de `https://checkout.ninepay.com.br/js/v1/ninepay.js`, nunca de uma cópia. Para o sandbox, passe a origem do ambiente em `Ninepay({ origin })`. O CSP da página precisa liberar `https://checkout.ninepay.com.br` em `script-src` e `frame-src`.

## Monte o elemento

> Linhas destacadas: 7-11

`ninepay.elements` recebe o `uuid` da fatura (e, se quiser, `appearance` para combinar com a sua página). `elements.create('payment')` cria o iframe com os métodos da fatura, e `mount` o coloca no lugar.

## Habilite o botão

> Linhas destacadas: 13-16

O botão de pagar é da sua página. O evento `change` avisa quando os campos do método escolhido estão completos.

## Valide e pague

> Linhas destacadas: 18-31

`elements.submit()` valida e mostra os erros no iframe, sem enviar. Depois, `ninepay.confirmPayment({ elements })` paga e sempre resolve, com `{ payment }` ou `{ error }`. No sandbox, teste com os [cartões de teste](/docs/test-cards).

## Acompanhe o pagamento

> Linhas destacadas: 33-35

O evento `paid` chega quando o pagamento é feito nesta tela, inclusive o PIX ou o boleto pagos depois. Use para atualizar a tela; libere o acesso só pelo webhook, confirmando com `GET /payments/{id}`.

## Código

```html HTML
<div id="pagamento"></div>
<button id="pagar" disabled>Pagar</button>

<script src="https://checkout.ninepay.com.br/js/v1/ninepay.js"></script>
<script>
  const ninepay = Ninepay()
  const elements = ninepay.elements({
    payment: '<uuid da fatura>', // payment.uuid, vindo do seu servidor
  })
  const pagamento = elements.create('payment', { layout: 'tabs' })
  pagamento.mount('#pagamento')

  const pagar = document.getElementById('pagar')
  pagamento.on('change', event => {
    pagar.disabled = !event.complete
  })

  pagar.addEventListener('click', async () => {
    pagar.disabled = true
    const { error: invalido } = await elements.submit() // valida, sem enviar
    if (invalido) {
      pagar.disabled = false
      return
    }
    const { error, payment } = await ninepay.confirmPayment({ elements })
    if (error) {
      pagar.disabled = false // a recusa já aparece no iframe
      return
    }
    // payment.status: 'succeeded' (cartão aprovado) ou 'requires_action' (QR do PIX ou boleto na tela)
  })

  pagamento.on('paid', () => {
    // Atualize a tela; o acesso se libera pelo webhook
  })
</script>
```
