Pular para o conteúdo principal

Pagamentos Pix

Ao final desta página

Um checkout que produz um código Pix que o app do banco realmente aceita, e uma visão clara de onde o Pix estático para.

Como ligar​

Dois campos de configuração, e BRL:

<CatalogApp
config={{
currency: 'BRL',
pixKey: 'bloom@example.com',
pixMerchantCity: 'Sao Paulo',
companyName: 'Bloom Cosméticos',
}}
/>

A opção Pix passa a aparecer no checkout, mostrando o QR code e o texto para copiar e colar ("Pix Copia e Cola").

pixKey aceita qualquer tipo de chave: CPF, CNPJ, e-mail, telefone no formato +55…, ou chave aleatória.

É um BR Code de verdade​

Vale dizer isso com todas as letras porque implementações de fachada são comuns. O PlugStore implementa o payload EMV® QRCPS-MPM descrito no Manual de Padrões para Iniciação do Pix do Banco Central do Brasil.

O payload é uma sequência de campos TLV — dois dígitos de id, dois de tamanho, depois o valor:

IdConteúdo
00Indicador de formato do payload, 01
01Ponto de iniciação, 11 (estático, reutilizável)
26Conta do recebedor: br.gov.bcb.pix + sua chave
52Código de categoria do comerciante, 0000
53Moeda, 986 (BRL)
54Valor, omitido quando zero para o pagador digitar
58País, BR
59Nome do recebedor
60Cidade do recebedor
62Dados adicionais: o identificador da transação
63CRC-16

O checksum é CRC-16/CCITT-FALSE — polinômio 0x1021, valor inicial 0xFFFF, sem reflexão de entrada nem de saída — calculado sobre o payload inteiro, incluindo a tag 6304 do próprio campo de CRC. Errar isso é exatamente o que faz um código escanear como inválido, então há testes unitários cobrindo.

Experimente​

Isto roda o buildPixPayload do pacote publicado — a mesma função que o checkout chama — e depois recalcula o checksum do jeito que um app de banco faz. Edite qualquer campo e veja o payload mudar.

CRC-16 válido
00020101021126390014br.gov.bcb.pix0117bloom@example.com5204000053039865406149.905802BR5916BLOOM COSMETICOS6009SAO PAULO62130509DOCS-DEMO6304AC91
IdTamCampoValor
0002Indicador de formato do payload01
0102Ponto de iniciação11
2639Conta do recebedor (Pix)0014br.gov.bcb.pix0117bloom@example.com
5204Código de categoria do comerciante0000
5303Moeda da transação986
5406Valor da transação149.90
5802Código do paísBR
5916Nome do recebedorBLOOM COSMETICOS
6009Cidade do recebedorSAO PAULO
6213Dados adicionais0509DOCS-DEMO
6304CRC-16AC91

Repare que os acentos e as minúsculas somem do nome e da cidade, e que qualquer coisa acima do limite da especificação é truncada — 25 caracteres para o nome, 15 para a cidade.

Limites dos campos​

A especificação restringe nomes e cidades a ASCII imprimível. O PlugStore faz a conversão para você: acentos são decompostos e removidos, o texto vira maiúsculo e é truncado.

CampoOrigemLimiteFallback
Nome do recebedorconfig.companyName25 caracteresRECEBEDOR
Cidade do recebedorconfig.pixMerchantCity15 caracteresBRASIL
Identificador (txid)o id de pedido gerado25 caracteres***

Então São Paulo vira SAO PAULO, e um nome de loja comprido é cortado em 25 caracteres. Escolha um nome fantasia curto se a razão social for longa.

Gerar um código por conta própria​

O gerador é exportado, então você pode montar um código fora do checkout — para uma fatura, um recibo, ou um link de "pague este valor".

import { buildPixPayload } from '@neverleans-labs/plug-store-core';

const codigo = buildPixPayload({
pixKey: 'bloom@example.com',
merchantName: 'Bloom Cosméticos',
merchantCity: 'Sao Paulo',
amount: 149.9, // omita para o pagador definir o valor
txid: 'PEDIDO-1042', // opcional, padrão '***'
});

buildPixPayload lança erro quando falta a pixKey — um código Pix sem chave nunca serve para nada, então falhar alto é melhor que devolver um texto que não faz nada em silêncio.

A função de checksum também é exportada, caso você precise validar um payload vindo de outro lugar:

import { pixCrc16 } from '@neverleans-labs/plug-store-core';

const corpo = codigo.slice(0, -4); // tudo até o valor do CRC
pixCrc16(corpo) === codigo.slice(-4); // true para um código válido

Renderizar o QR code​

O pixGateway devolve pixQrCodeUrl, uma URL de imagem de um serviço público de QR, para que o checksum embutido funcione sem dependência extra.

Para uma loja em produção, gere o QR localmente — assim o payload não sai para um terceiro e funciona offline:

import QRCode from 'qrcode';

const dataUrl = await QRCode.toDataURL(codigo, { width: 300, margin: 1 });

O que o Pix estático não faz​

O fluxo embutido é Pix estático. Ele cria uma cobrança válida. Só isso.

  • Sem confirmação. Seu app nunca fica sabendo que o dinheiro entrou. Alguém precisa conferir no banco.
  • Sem conciliação por pedido do lado do banco. O txid vai no payload, mas casar isso com uma liquidação exige a API do banco.
  • Sem estorno nem cancelamento.

Confirmação automática significa Pix dinâmico: conta em um PSP, endpoint de webhook no seu servidor e verificação de assinatura. Quando você tiver isso, pluga como adaptador customizado — o PlugStore sai do caminho.

Se conferir o banco na mão é o que uma loja sua faz hoje, conte pra gente. O contorno que você usa é justamente a parte que mais queremos ouvir.

Próximos passos​