Bunne Docs

Carteiras no seu checkout

Apple Pay e Google Pay dentro da sua tela de pagamento, sem registrar domínio, emitir certificado nem tratar o token da carteira.

Apple Pay e Google Pay na sua tela de pagamento, sem você registrar domínio na Apple, submeter nada ao Google, emitir certificado ou tirar print de folha de pagamento.

O que torna isso possível é um detalhe das duas carteiras: elas validam a sessão contra o host que a pede. Os botões rodam num componente nosso, servido de um domínio que já está verificado nas duas, então quem a Apple e o Google veem somos nós. Você diz onde quer os botões.

O fluxo em três passos

  1. Seu backend cria a intenção de pagamento.
  2. Sua página monta os botões naquela intenção.
  3. O desfecho chega por callback (para mover a tela) e por webhook (para mover o pedido).

1. A intenção, no seu backend

A intenção crava valor e estabelecimento antes de a folha abrir. Ela existe porque o navegador não pode decidir o valor: a folha mostraria um número e a cobrança cobraria outro, e isso aconteceria no nosso domínio, sob a nossa identidade de comerciante.

curl -X POST "https://bunne.com.br/api/v1/payment-intents" \  -H "Authorization: Bearer $SK" \  -H "Idempotency-Key: pedido-48219" \  -H "Content-Type: application/json" \  -d '{    "amount_cents": 10000,    "metadata": { "pedido": "48219" }  }'# -> { "id": "pi_...", "expires_at": "..." }# O "id" e o handle. Nao ha nada para o comprador abrir: ele paga na sua tela.

Use a sua sk_, sempre no servidor. Ela é de uso único e expira sozinha: crie uma quando a etapa de pagamento renderizar, e não se preocupe com as que o comprador abandonar.

Não existe campo de parcelas. A grade que o comprador vê é herdada do que o estabelecimento configurou, do que a adquirente aceita e do próprio valor — nenhuma parcela é oferecida abaixo de R$ 5,00, então uma venda de R$ 12,00 abre no máximo 2x.

2. Os botões, na sua página

<div id="carteiras"></div><script src="https://bunne.com.br/sdk/v1/checkout.js"></script><script>  const client = CheckoutSDK.create({    baseUrl: "https://bunne.com.br",    apiKey: "pk_live_...",        // publica: pode ficar no HTML  });  client.mountWallets("#carteiras", {    handle: "pi_...",             // o id que seu backend criou    // Quem coleta CPF/CNPJ e pais. Passe false se o SEU checkout ja pede, e    // entao mande o dado por update(): nenhum campo nosso aparece dentro do    // seu layout, nem quando falta.    collectIdentity: false,    document: "12345678909",    country: "BR",    onPaid: ({ charge }) => {      // Avance a TELA. Nao marque o pedido como pago aqui: ver o passo 3.      mostrarObrigado(charge);    },    onFallback: () => {      // O comprador recusou a carteira. Mostre o SEU formulario de cartao.      abrirFormularioDeCartao();    },    onFailed: ({ reason }) => {      // "document_required": o comprador tocou no botao e o documento nao chegou.      // Com collectIdentity: false quem pede e o SEU campo — nada e desenhado      // aqui dentro. Aponte o seu, e depois chame update({ document }).      if (reason === "document_required") return apontarCampoDeCpf();      mostrarErro(reason);    },  });</script>

A pk_ é pública e não cobra, não lê e não tokeniza — por isso pode ficar no HTML. O componente desenha país, documento, parcelas e os botões: a parcela é escolhida antes da carteira, porque é ela que define o valor que a folha vai mostrar.

Uma exigência do navegador que vale saber antes de debugar: a permissão que libera carteira em componente de outra origem é delegada um nível por vez. Se o seu checkout roda dentro de um iframe — motor de reservas faz muito isso —, todo ancestral precisa repassá-la, e isso o nosso código não consegue fazer de dentro.

3. O desfecho

onPaid serve para avançar a tela. Quem marca o pedido como pago é o webhook: ele chega no seu servidor, não depende do navegador do comprador continuar aberto, e não pode ser forjado por quem mexer no front.

POST https://seu-backend.com.br/webhooks/pagamentos{  "type": "charge.paid",  "data": {    "id": "ch_...",    "amount": 10000,    "payment_method": "CREDIT_CARD",    "metadata": { "pedido": "48219" }  }}

O metadata que você enviou na intenção viaja até a cobrança — é por ele que você sabe qual pedido fechou.

onFallback dispara quando o comprador recusa a carteira e quer pagar de outro jeito. O componente não oferece formulário de cartão de propósito: o seu checkout já tem o dele, e é para ele que esse aviso serve.

Se os botões não aparecerem

O componente só desenha em páginas cuja origem está autorizada, e isso é configurado no seu cadastro, não por você. Se o espaço ficar vazio, fale com o time da Bunne com a URL onde você está embutindo.

Ele também não desenha quando a intenção já foi usada ou expirou — o que é o esperado, porque cada intenção paga uma vez.

Precisa do fluxo completo de cartão? Veja Fluxo completo. Se o que você quer é não ter tela de pagamento nenhuma, o link de pagamento já resolve sozinho.