PIX e a tela do QR
O PIX no Payment Fragment, da Parte PIX à tela do QR do PIX em tela cheia, com os estados, a leitura do pagamento, o prazo e o teste.
O PIX não tem campo no fragment. O Comprador escolhe a aba PIX (ou "Cartão + PIX" no Combinar), o seu servidor cria e confirma o pagamento, e o handleNextAction abre a tela do QR do PIX em tela cheia sobre a sua página até o pagamento terminar.
O fluxo
createPaymentMethoddevolve a Parte{ method: 'pix', amount, payment_method }.- O seu servidor cria e confirma o pagamento (Integrar o Payment Fragment); o confirm responde
status: 'requires_action'(ou'processing') e oclient_secret. - A página chama
assiny.handleNextAction({ clientSecret }). - O SDK lê o pagamento e, com o QR pronto, abre a tela do QR do PIX.
- Pago o PIX, a tela mostra o pagamento confirmado e fecha 4 s depois; a promessa resolve
{ paymentIntent }comstatus: 'succeeded'.
const { paymentIntent, error } = await assiny.handleNextAction({
clientSecret: pagamento.client_secret,
});
if (paymentIntent?.status === 'succeeded') mostrarConfirmacao();O handleNextAction funciona só com a instância de Assiny(): não precisa do fragment montado.
A tela do QR do PIX
A tela cobre a janela inteira. A página atrás fica inerte e o foco fica preso na tela: Tab e Shift+Tab circulam entre Fechar, o código e Copiar. Tocar fora não fecha. Ao fechar, o foco volta ao elemento que o tinha na sua página.
O que a tela mostra, de cima para baixo:
- o título "Pague com PIX" e o botão Fechar;
- o valor da Parte PIX (no Combinar, só a Parte PIX);
- o QR code;
- o código copia e cola, com o início e o fim à mostra (o código inteiro vai no Copiar e na seleção);
- o botão "Copiar código";
- o prazo, como "Pague até 27/10/2026 às 15:30", no fuso do aparelho;
- a instrução "Abra o app do seu banco, escolha pagar com QR code e aponte a câmera, ou copie o código."
No celular (até 639px de largura, ou em tela de toque), a tela vira uma folha presa ao rodapé e o código copia e cola e o botão "Copiar código" vêm antes do QR, porque quem está no celular paga no app do banco do mesmo aparelho.
A tela tem a cara fixa do Assiny Gateway: a appearance do fragment não muda nada nela. Os textos seguem o locale da instância.
Estados
| Estado | Quando | O que muda |
|---|---|---|
| aberto | o QR chegou | QR, código, "Copiar código" e o prazo |
| copiado | o Comprador tocou em "Copiar código" | o botão mostra "Copiado" por 1,6 s; se o navegador não deixar copiar, o código fica selecionado e aparece "Não foi possível copiar. Selecione o código e copie." |
| vencido | o prazo passou no relógio do aparelho | "Este QR code venceu. Feche e tente de novo." no lugar do prazo, o QR esmaecido e o Copiar desligado |
| recebido | o pagamento da Parte PIX foi confirmado | o QR sai e entram "Pagamento recebido", "Tudo certo! Seu pagamento foi confirmado com sucesso.", "Total pago via PIX" com o valor e o status "Pago · confirmação recebida"; o título vira "Pagamento confirmado" |
| sem conexão | três leituras seguidas falharam | a faixa "Sem conexão. Tentando de novo." no alto; some quando a leitura volta |
O vencido pelo relógio do aparelho só muda a tela: quem encerra é a leitura do pagamento. Com prefers-reduced-motion, a passagem para o recebido acontece sem animação.
A leitura do pagamento
- O SDK lê o pagamento a cada 3 s enquanto a tela está aberta.
- Com a aba do navegador oculta, a leitura pausa; ao voltar, lê na hora.
- Uma resposta 429 não é erro: o SDK espera o
Retry-After(em segundos ou data, no mínimo 1 s; sem ele, 3 s) e lê de novo. - Cada leitura tem 8 s. Depois da primeira, uma leitura que falha não fecha a tela: o SDK tenta na volta seguinte.
- A primeira leitura tem até 20 s; se ela falhar, a promessa resolve
{ error }e a tela não abre.
Como termina
| O que aconteceu | A tela | A promessa |
|---|---|---|
succeeded com a tela aberta | mostra o recebido e fecha 4 s depois | { paymentIntent } com succeeded |
succeeded sem a tela aberta, requires_payment_method (o PIX venceu ou falhou), canceled ou requires_confirmation | fecha, se estava aberta | { paymentIntent } com o status |
| o Comprador apertou Esc ou Fechar | fecha e a leitura para | { paymentIntent } com o estado da última leitura, em geral requires_action |
| uma ação que o SDK não conhece | fecha | { error } com next_action_unsupported |
| a tela não abriu em 10 s | não aparece | { error } com overlay_not_ready |
Depois de Esc ou Fechar, chamar handleNextAction de novo reabre o QR atual, sem criar outro pagamento.
O que a página recebe:
{
"paymentIntent": {
"id": "pi_...",
"object": "payment_intent",
"livemode": false,
"status": "succeeded",
"amount": 12990,
"currency": "brl",
"parts": [
{ "id": "pip_...", "position": 1, "method": "pix", "amount": 12990, "status": "succeeded" }
],
"last_payment_error": null
}
}last_payment_error é { type, code, message } ou null. A verdade do pagamento continua sendo o seu servidor, pelo webhook ou lendo o pagamento com a sk_.
O prazo
O prazo do PIX vem do create, em payment_method_options.pix.expires_after_seconds (segundos, inteiro maior que zero):
{
"payment_method_options": { "pix": { "expires_after_seconds": 3600 } }
}Sem o campo, vale o padrão da política da sua Conta. No Combinar (cartão + PIX), vale o prazo da política da Conta para o Combinar, não o enviado. Um prazo acima do máximo da política é recusado no create com expires_after_too_large. Vencido o prazo sem pagamento, o pagamento volta a requires_payment_method, com o last_payment_error do vencimento.
A Content-Security-Policy
A tela do QR é um iframe do host https://sdk-gateway-overlay.assiny.com.br. Se a sua página tem Content-Security-Policy, ele precisa estar em frame-src, com os outros três hosts do SDK (Integrar o Payment Fragment).
Testar no Modo de teste
- Na faixa de valor que a política da sua Conta aceita (na política padrão, a partir de R$ 3,50), a Parte PIX de teste é sempre paga sozinha em cerca de 5 s: a tela passa ao recebido e fecha.