Pix copia e cola (BR Code)
O código do Pix é uma fila de campos, cada um com ID, tamanho e valor. A chave que recebe o dinheiro fica dentro do campo 26.
O texto de um QR code do Pix (o "copia e cola") parece uma sopa de letras:
00020126430014br.gov.bcb.pix0121pedidos@cucadavo.test520400005303986540525.005802BR5910CUCA DA VO6013CERRO MINUANO62120508PEDIDO426304AF8F
Mas ele segue um formato chamado TLV (tipo, tamanho, valor): cada campo é um ID de 2 dígitos, um tamanho de 2 dígitos e um valor com exatamente esse número de caracteres. Para ler, pegue 2 dígitos (ID), mais 2 (tamanho), conte os caracteres do valor e recomece logo depois:
| ID | Tamanho | Valor | O que é |
|---|---|---|---|
00 |
02 |
01 |
versão do formato |
26 |
43 |
[email protected] |
conta que recebe (tem campos dentro) |
52 |
04 |
0000 |
categoria do comerciante |
53 |
03 |
986 |
moeda: real |
54 |
05 |
25.00 |
valor (opcional) |
58 |
02 |
BR |
país |
59 |
10 |
CUCA DA VO |
nome de quem recebe |
60 |
13 |
CERRO MINUANO |
cidade |
62 |
12 |
0508PEDIDO42 |
dados extras (tem campos dentro) |
63 |
04 |
AF8F |
CRC16, a conferência do texto |
O campo 26 é ele mesmo uma fila TLV: 00 14 br.gov.bcb.pix diz que é Pix, e 01 21 [email protected] é a chave, para onde o dinheiro vai. A chave pode ser um e-mail, um telefone, um CPF ou CNPJ, ou uma chave aleatória com cara de 123e4567-e89b-42d3-a456-426614174000. Pode aparecer ainda o campo 01 de fora, que diz se o QR é estático (11) ou de uso único (12).
Em Python:
def tlv(s):
i, campos = 0, {}
while i < len(s):
tam = int(s[i + 2:i + 4])
campos[s[i:i + 2]] = s[i + 4:i + 4 + tam]
i += 4 + tam
return campos
c = tlv(codigo)
print(c["59"], tlv(c["26"])["01"])
O CRC16 do campo 63 (na variante chamada CCITT-FALSE: polinômio 0x1021, começando em 0xFFFF) é calculado sobre todo o texto antes dele, incluindo o 6304:
def crc16(texto):
crc = 0xFFFF
for byte in texto.encode():
crc ^= byte << 8
for _ in range(8):
crc = (crc << 1) ^ 0x1021 if crc & 0x8000 else crc << 1
crc &= 0xFFFF
return f"{crc:04X}"
print(crc16(codigo[:-4]) == codigo[-4:])
Ele pega um código corrompido ou editado à mão. Não pega golpe: quem gera um código novo, com a chave dele, gera também um CRC certo. E o nome do campo 59 é texto livre, escrito por quem gerou o código. Na hora de pagar, o aplicativo consulta a chave no diretório do Pix e mostra o nome do dono da chave e a instituição: é esse nome que você confere, não o do código nem o do cartaz.