Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validação do CRC 16 e EMV #189

Open
felipecamargo opened this issue Nov 17, 2020 · 54 comments
Open

Validação do CRC 16 e EMV #189

felipecamargo opened this issue Nov 17, 2020 · 54 comments
Assignees
Labels
BR Code issues relativas à especificação do BR Code Dica Uma informação oriunda da comunidade (e não do BACEN) para o benefício da comunidade Erros dos PSPs Os PSPs não estão implementando algo de maneira adequada QR Dinâmico aspectos concernentes ao QR Dinâmico Pix QR Estático Aspectos concernentes ao QR Estático Pix

Comments

@felipecamargo
Copy link

felipecamargo commented Nov 17, 2020

Percebi que muitos QR CODE estão sendo enviados com CRC 16 calculado invalido.
E pouquíssimos PSP's pagadores estão validando tanto o CRC16 quanto o padrão do EMV Merchant Presented Mode como um todo.

Quanto a Estrutura EMV, pelo que eu observei não estão sendo validados:

  • Reference label até 25 caracteres.
  • Merchant Name até 25 caracteres.
  • City Name até 15 caracteres.

A maioria dos PSPs estão aceitando QR CODEs conforme listado abaixo, provavelmente os único bancos que estão tentando realizar as consistências do Padrão EMV e também dos certificados dos sites QR CODE dinâmico são Itaú e Banco do Brasil.

Exemplo:

  1. Iniciado de forma incorreta >>> 0020101021226990014br.gov.bcb.pix2577qrcode.pix.bancobmg.com.br/qrs1/01mWFiCMHqRMdrkzWFWazsiurgfoqpsJFbuXx3IcpRqfj52040000530398654040.015802BR5917JEFFERSON F SOUZA6009SAO PAULO62290525QRS1-F5CMMUTDLOVWF8UBT7Q4630413DF -> calculado errado deveria ser 2E7D

  2. Mal formatado
    000201
    2640
    0014BR.GOV.BCB.PIX
    0114+55149916479660200
    52040000
    5303986
    54030.05
    802BR5921JULIO DE SOUZA RUGOLO6009SAO.PAULO6238050050300017BR.GOV.BCB.BRCODE01051.0.06304BD79

  3. CRC 16 invalido
    00020126360014BR.GOV.BCB.PIX0114+55339999117485204000053039865802BR5924LEANDRO
    ALVES PEREIRA 6009SAO.PAULO623450300017BR.GOV.BCB.BRCODE01051.0.063044867 -> deveria ser C3F4.

  4. Mal formatado
    000201
    010212
    2641
    0005Cielo< deveria ser indicação de BR CODE -> 14br.gov.bcb.pix
    0116001019064975000102087748103252040000530398654120000000031005802BR5921AUTO POSTO BASE AEREA6011CURITIBA PR801010033"https://www.cielo.com.br/qrcode"0116111117082C14677A0212171120183512030420000404000105020106020163043256

  5. Mal formatado
    000201
    2653
    0014BR.GOV.BCB.PIX
    0127takeshinho2001@yahoo.com.br
    0200 tamanho 00 não é permitido pelo padrão EMV.
    52040000530398654030.05802BR5922ANTONIO TAKESHI FUKUDA6009SAO.PAULO6238050050300017BR.GOV.BCB.BRCODE01051.0.063045B1A

  6. Merchant Name
    000201
    2636
    0014br.gov.bcb.pix
    0114+5531998925047
    52040000
    5303986
    54071000.00
    5802BR
    5938SUELI DO CARMO PEREIRA DA SILVA KUSTER -- Limite de 25 caracteres
    6008CONTAGEM
    6241
    0503***
    5030
    0017br.gov.bcb.brcode
    01051.0.0
    63049602

  7. Mal Formatado (nubank)
    000201
    2662
    0014BR.GOV.BCB.PIX
    013639b6c11f-8383-4378-87c1-ce62df204ab8
    0200 <<< NÃO PODE SER TAMANHO 00
    5204000053039865406127.505802BR5925LARISSA JUSTUS RAYMUNDO 36009SAO PAULO61080540900062160512NUomZK5qzGvA630440BB

  8. Mal Formatado (nubank)
    000201
    2672
    0014BR.GOV.BCB.PIX 18
    01366ae8a1ab-8a46-49ef-9a14-6b03df474f6a 40
    0210Toma lim㯵2
    040000

    530398654046.005802BR5924F D C HUMMEL EIRELI - ME6009SAO PAULO61080540900062160512NUNFFQwm3oLJ63040974

@ninrod
Copy link
Member

ninrod commented Nov 18, 2020

Percebi que muitos QR CODE estão sendo enviados com CRC 16 calculado invalido.
E pouquíssimos PSP's pagadores estão validando tanto o CRC16 quanto o padrão do EMV Merchant Presented Mode como um todo.

Quanto a Estrutura EMV, pelo que eu observei não estão sendo validados:

Reference label até 25 caracteres.
Merchant Name até 25 caracteres.
City Name até 15 caracteres.

@felipecamargo , obrigado pelo reporte.

@ninrod ninrod self-assigned this Nov 18, 2020
@ninrod ninrod added QR Dinâmico aspectos concernentes ao QR Dinâmico Pix Erros dos PSPs Os PSPs não estão implementando algo de maneira adequada labels Nov 18, 2020
@dmkamers
Copy link

dmkamers commented Nov 18, 2020

@felipecamargo
Aproveito a issue, muito bem colocada, para agregar algumas informações pertinentes:

  1. Mal formatado
    2641
    00-05 Cielo **< deveria ser indicação de BR CODE -> 14br.gov.bcb.pix
    01-16 0010190649750001
    02-08 77481032

Isso parece ser um BRCode contendo um 'rail' do tipo "Cielo" (os campos '01 e '02 que seguem nao parecem ter relação com o Pix mesmo). Neste caso, esse formato de GUI EMV Cielo estaria errado de fato (pela especificação EMV).
EDIT3: nao esta errado, se Cielo for um ApplicationId registrado (mas está fora do contexto Pix, nao se validam outros rails; cada um faz a sua parte).

EDIT: não se espera que os campos 01, 02, desse arranjo Cielo sejam Pix-like... um pagador Pix, ao ler este QR, deveria ignorar tudo o que está abaixo desse objeto 26 no exemplo (caso esteja esperando pagar um Pix). Apenas um pagador Cielo vai ler e entender o que vem ali.

EDIT2: um Pix poderia conviver perfeitamente no mesmo BRCode, mas estaria sob um objeto 27..., e etc.

  1. Merchant Name
    ...
    6241
    0503***
    50-30 00-17 br.gov.bcb.brcode 01-05 1.0.0

Neste (e em varios outros casos) aparece esse objeto 50 (sob o template 62).
Isto não existe (gui br.gov.bcb.brcode, versão 1.0.0), não deve ser utilizado (versão obsoleta do manual BRCode).

@ninrod ninrod added QR Estático Aspectos concernentes ao QR Estático Pix BR Code issues relativas à especificação do BR Code labels Nov 18, 2020
@dmkamers dmkamers self-assigned this Nov 18, 2020
@jeansentose
Copy link

Pessoal, boa tarde!

Alguém poderia dar uma idéia de como calcular o CRC16?

Agradeço!

@cryptographix
Copy link

cryptographix commented Nov 23, 2020

Pessoal, boa tarde!

Alguém poderia dar uma idéia de como calcular o CRC16?

Agradeço!

@jeansentose tem várias bibliotecas em linguagens diversas no github.

Tem uma rotina neste link, em typescript (javascript++), fácil de converter para a tua linguagem de estimação.

https://github.com/NascentSecureTech/pix-qrcode-utils/blob/master/packages/emv-merchant-qrcode/src/crc.ts

@cryptographix
Copy link

cryptographix commented Nov 23, 2020

@jeansentose depois se quiser, pode copie e cola a string que gerou aqui neste site para validação.

@jeansentose
Copy link

@jeansentose depois se quiser, pode copie e cola a string que gerou aqui neste site para validação.

Valeu, meu amigo !! Agradeço o apoio !!

@jeansentose
Copy link

Pessoal, boa tarde!
Alguém poderia dar uma idéia de como calcular o CRC16?
Agradeço!

@jeansentose tem várias bibliotecas em linguagens diversas no github.

Tem uma rotina neste link, em typescript (javascript++), fácil de converter para a tua linguagem de estimação.

https://github.com/NascentSecureTech/pix-qrcode-utils/blob/master/packages/emv-merchant-qrcode/src/crc.ts

@seanwykes Só uma dúvida... qual o campo que ele usa para validar? Digo, a posição que ele usa como base...

@cryptographix
Copy link

cryptographix commented Nov 23, 2020

Então, acabei de gerar um QR estático pelo site gerarpix.com.br, assim:
00020126330014BR.GOV.BCB.PIX01112178262481352040000530398654041.005802BR5902me6009somewhere62130509pagamento6304C3A7

Quebrando em tags (incluí espaços, indentação e quebras de linha para melhorar a leitura), tem:
0002 01
2633
.... 0014 BR.GOV.BCB.PIX
.... 0111 21782624813
5204 0000
5303 986
5404 1.00
5802 BR
5902 me
6009 somewhere
6213
.... 0509 pagamento
6304 C3A7

Observe a última tag 63, de tamanho 04. O CRC deve ser calculado do início da string do QR até, e incluindo, o 6304.

Neste exemplo, calcula-se o CRC sobre 00020126330014BR.GOV.BCB.PIX01112178262481352040000530398654041.005802BR5902me6009somewhere62130509pagamento6304

No final, concatena o CRC, que tem 16 bits / 2 bytes, como 4 caracteres HEXA (com padding de "0" em cada byte).

A página que passei tem um botão para recalcular o CRC (mas é preciso que a estrutura de tags seja válida)

@jeansentose
Copy link

Valeu meu querido !! Agradeço muito a ajuda !!

@alexandresanlim
Copy link

Valeu meu querido !! Agradeço muito a ajuda !!

Você conseguiu gerar? se sim para qual linguagem? não estou conseguindo gerar em c# :/

@cryptographix
Copy link

@alexandresanlim pode usar este site para validar a sua geração. A tela também gera QR estático e dinâmico, e pode regerar o CRC correto para um QR.

Em C# tem várias libs no github, como por exemplo https://github.com/juanroman-zz/emvqr

@alexandresanlim
Copy link

@alexandresanlim pode usar este site para validar a sua geração. A tela também gera QR estático e dinâmico, e pode regerar o CRC correto para um QR.

Em C# tem várias libs no github, como por exemplo https://github.com/juanroman-zz/emvqr

Hoje pela manhã eu finalmente consegui tendo o seu código em TypeScript como base, o resultado esta aqui.
Muito obrigado pela resposta!

@vitorgsoares
Copy link

Pessoal, boa tarde!
Alguém poderia dar uma idéia de como calcular o CRC16?
Agradeço!

@jeansentose tem várias bibliotecas em linguagens diversas no github.

Tem uma rotina neste link, em typescript (javascript++), fácil de converter para a tua linguagem de estimação.

https://github.com/NascentSecureTech/pix-qrcode-utils/blob/master/packages/emv-merchant-qrcode/src/crc.ts

@jeansentose Eu utilizo PHP para gerar o QRCODE.

A funcao que utilizo é:
function crc16($string)
{
$CRC16POLINOMIO = 0x1021;
$result = 0xFFFF;
if (($length = strlen($string)) > 0) {
for ($offset = 0; $offset < $length; $offset++) {
$result ^= (ord($string[$offset]) << 8);
for ($bitwise = 0; $bitwise < 8; $bitwise++) {
if (($result <<= 1) & 0x10000) $result ^= $CRC16POLINOMIO;
$result &= 0xFFFF;
}
}
}
return $result;
}
$CRC16 = crc16($stringPix); //Nessa string deve conter o final "6304"
$CRC16 = dechex($CRC16); //transformo de decimal para hexadecimal
$CRC16 = strtoupper($CRC16); //Transformo para maiusculas

Estou trabalhando em um conversor online. O exemplo está no link
https://showcommerce.com.br/pix

@ghost
Copy link

ghost commented Jan 18, 2021

Pessoal estou enroscado aqui com o CRC16 minha string esta tudo OK mas o calculo do CRC16 não bate de jeito nenhum, uso Delphi, baixei algumas função de calculo de CRC16 mas nada esta dando certo, alguém ai que trabalhe com Delphi e já tenha passado por esse problema, pra me fazer um Freelance aqui. obrigado meu contato WhatsApp (42) 9 8403-0313 - Sergio.

uso essas funções se sucesso:
function Crc16(texto: string; Polynom: WORD = $1021; Seed: WORD = $FFFF): WORD;
var
i, j: Integer;
begin
Result := Seed;
for i := 1 to length(texto) do
begin
Result := Result xor (ord(texto[i]) shl 8);
for j := 0 to 7 do
begin
if (Result and $8000) <> 0 then
Result := (Result shl 1) xor Polynom
else
Result := Result shl 1;
end;
end;
Result := Result and $FFFF;
end;

function Crc16(texto: string): WORD;
const
polynomial = $1021;
var
crc: WORD;
i, j: Integer;
b: Byte;
bit, c15: Boolean;
begin
crc := $FFFF;
for i := 1 to length(texto) do
begin
b := Byte(texto[i]);
for j := 0 to 7 do
begin
bit := (((b shr (7 - j)) and 1) = 1);
c15 := (((crc shr 15) and 1) = 1);
crc := crc shl 1;
if (c15 xor bit) then
crc := crc xor polynomial;
end;
end;
Result := crc and $FFFF;
end;

@ninrod ninrod added the Dica Uma informação oriunda da comunidade (e não do BACEN) para o benefício da comunidade label Feb 2, 2021
@aslsoftware
Copy link

Fala ai blz, em delphi estou gerando desta forma.

function CRC16CCITT(texto: string): WORD;
const
polynomial = $1021;
var
crc: WORD;
i, j: Integer;
b: Byte;
bit, c15: Boolean;
begin
crc := $FFFF;
for i := 1 to length(texto) do
begin
b := Byte(texto[i]);
for j := 0 to 7 do
begin
bit := (((b shr (7 - j)) and 1) = 1);
c15 := (((crc shr 15) and 1) = 1);
crc := crc shl 1;
if (c15 xor bit) then
crc := crc xor polynomial;
end;
end;
Result := crc and $FFFF;
end;

e chamo a função desta forma.

inttohex(CRC16CCITT(minhachave),4);

Testei em diversos bancos só o Itau que estou dependendo do gerente descobrir lá onde libera kkkk.

@renatofrota
Copy link

Testei em diversos bancos só o Itau que estou dependendo do gerente descobrir lá onde libera kkkk.

renatofrota/pix-pendencias#26

@GabrielPaixaoJustino
Copy link

Boa tarde Pessoal, estou tentando gerar meu calculo CRC16 através de uma função criada no SQL.
Mas o calculo não está retornando da maneira esperada, conseguem dar uma força? Ou identificar algo que não estou conseguindo na minha função. Segue a fórmula abaixo:
``
ALTER FUNCTION [dbo].[CRC16]
(
@input varchar(max)
)
RETURNS int
WITH SCHEMABINDING
AS
BEGIN
DECLARE @Crc bigint = 0xffff
, @Result int
;
SELECT @Crc = dbo.CRC16calc(@Crc, Ascii(Substring(@input, v.id, 1)))
FROM dbo.IndexTable(1, LEN(@input)) AS v
ORDER
BY v.Id
;
SET @Result = UPPER(CONVERT(int, CONVERT(VARBINARY(4), ~@Crc))) ;
RETURN @Result ;
END

Abaixo estão as informações que estão sendo calculadas:
01
12
0014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b5
0000
986
1.00
BR
SIRICOMERCIOESERVICOSLTDA
SAOPAULO
0515DF06B1AAD182021
A2DA

@renatofrota
Copy link

Abaixo estão as informações que estão sendo calculadas:
01
12
0014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b5
0000
986
1.00
BR
SIRICOMERCIOESERVICOSLTDA
SAOPAULO
0515DF06B1AAD182021
A2DA

Não sei se entendi exatamente o que você está tentando fazer. Você está tentando validar o CRC de um QR Code diretamente no SQL? Esses valores que você mencionou não são um BR Code completo. As informações estão sem os IDs dos "templates" EMV e seus tamanhos.

Por ex: o primeiro valor, 01, provavelmente deveria ser 000201 (template 00, tamanho 02, valor 01). Depois o valor 12, deveria ser 010212 (template 01, tamanho 02, valor 12). E assim por diante.

@GabrielPaixaoJustino
Copy link

Abaixo estão as informações que estão sendo calculadas:
01
12
0014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b5
0000
986
1.00
BR
SIRICOMERCIOESERVICOSLTDA
SAOPAULO
0515DF06B1AAD182021
A2DA

Não sei se entendi exatamente o que você está tentando fazer. Você está tentando validar o CRC de um QR Code diretamente no SQL? Esses valores que você mencionou não são um BR Code completo. As informações estão sem os IDs dos "templates" EMV e seus tamanhos.

Por ex: o primeiro valor, 01, provavelmente deveria ser 000201 (template 00, tamanho 02, valor 01). Depois o valor 12, deveria ser 010212 (template 01, tamanho 02, valor 12). E assim por diante.

Na verdade ele possui os tamanhos de forma correta, esse foi só um exemplo que passei das infos, segue abaixo minha string que está sendo gerada.

00020101021226940014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b552040000530398654041.005802BR5925SIRICOMERCIOESERVICOSLTDA6008SAOPAULO62190515F8F0E7A863120216304461A

Seu jogar essa string no validador ele retorna a seguinte mensagem: ERROR - Invalid CRC, clicando em FIX CRC, ele passa...

@renatofrota
Copy link

renatofrota commented May 17, 2021

O CRC deve ser calculado em cima de:

00020101021226940014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b552040000530398654041.005802BR5925SIRICOMERCIOESERVICOSLTDA6008SAOPAULO62190515F8F0E7A863120216304

que é "tudo menos o próprio CRC" (inclusive o 6304, que é o template ID 63, tamanho 04) e resulta em 8119 (diferente do seu resultado, 461A).

@dmkamers
Copy link

qrCode.ods
Se dá pra fazer em planilha, deve dar pra fazer em sql... :)

@GabrielPaixaoJustino
Copy link

O CRC deve ser calculado em cima de:

00020101021226940014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b552040000530398654041.005802BR5925SIRICOMERCIOESERVICOSLTDA6008SAOPAULO62190515F8F0E7A863120216304

que é "tudo menos o próprio CRC" (inclusive o 6304, que é o template ID 63, tamanho 04) e resulta em 8119 (diferente do seu resultado, 461A).

Sim, já estou fazendo isso. Por isso que estou achando que existe algum problema na minha função, pois já estou contemplando a string exatamente dessa maneira, segue o trecho da minha função em SQL.

ALTER FUNCTION [dbo].[CRC16]
(
@input varchar(max)
)
RETURNS int
WITH SCHEMABINDING
AS
BEGIN
DECLARE @Crc bigint = 0xffff
, @Result int
;
SELECT @Crc = dbo.CRC16calc(@Crc, Ascii(Substring(@input, v.id, 1)))
FROM dbo.IndexTable(1, LEN(@input)) AS v
ORDER
BY v.Id
;
SET @Result = UPPER(CONVERT(int, CONVERT(VARBINARY(4), ~@Crc))) ;
RETURN @Result ;
END

@renatofrota
Copy link

renatofrota commented May 17, 2021

Eu não manjo tanto assim de SQL.

O input que tá sendo passado pra função que calcula o CRC é a string 00020101021226940014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b552040000530398654041.005802BR5925SIRICOMERCIOESERVICOSLTDA6008SAOPAULO62190515F8F0E7A863120216304 ?

@GabrielPaixaoJustino
Copy link

GabrielPaixaoJustino commented May 17, 2021

Eu não manjo tanto assim de SQL.

O input que tá sendo passado pra função que calcula o CRC é a string 00020101021226940014br.gov.bcb.pix2572qrpix.bradesco.com.br/qr/v2/62d42bf-848854-ba0e-f877d54475663e2b52f5-4b552040000530398654041.005802BR5925SIRICOMERCIOESERVICOSLTDA6008SAOPAULO62190515F8F0E7A863120216304 ?

Isso mesmo. De qualquer forma, obrigado pela força.

@renatofrota
Copy link

É MySQL? Ou outro banco?

Achei essa resposta no SO que pode ser útil: https://stackoverflow.com/a/63901938/2847575

@renatofrota
Copy link

renatofrota commented May 17, 2021

E essa pra SQL Server: https://pt.stackoverflow.com/questions/485228/como-converter-uma-fun%C3%A7%C3%A3o-crc16-em-mysql-para-sql-server (a resposta é direcionada ao Pix, inclusive).

@admsilva
Copy link

Boa tarde a todos,

Segue solução que estou utilizando em PL/SQL:

CREATE OR REPLACE FUNCTION CRC16(V_STRING VARCHAR2) RETURN VARCHAR2 IS
CURSOR C_BYTES (PIX_STRING VARCHAR2) IS
SELECT TO_NUMBER(COLUMN_VALUE) AS BYTES
FROM XMLTABLE(
SUBSTR(
DUMP(PIX_STRING),
INSTR(
DUMP(PIX_STRING),
':'
)+1
)
);

C NUMBER;
J NUMBER;

V_ANSWER VARCHAR2(4000) := 'FFFF';
V_POLINOMIO VARCHAR2(4) := '1021';

V_VERIFY NUMBER;

V_ID_CRC16 CHAR(2) := '63';
V_QTD_CRC16 CHAR(2) := '04';
BEGIN
FOR R_BYTES IN C_BYTES(V_STRING||V_ID_CRC16||V_QTD_CRC16)
LOOP
C := R_BYTES.BYTES;

  IF (C_BYTES%ROWCOUNT = 1) THEN
    V_ANSWER := TO_NUMBER(V_ANSWER, 'XXXX');
  END IF;

  J := (C * POWER(2,8));
  V_ANSWER := (J + V_ANSWER) - BITAND(J, V_ANSWER) * 2;

  FOR BITWISE IN 0..7 LOOP
    V_ANSWER := V_ANSWER * POWER(2,1);
    V_VERIFY := BITAND(V_ANSWER, TO_NUMBER('10000', 'XXXXX'));

    IF (V_VERIFY <> 0) THEN
      V_ANSWER := (V_ANSWER + TO_NUMBER(V_POLINOMIO, 'XXXX')) - BITAND(V_ANSWER, TO_NUMBER(V_POLINOMIO, 'XXXX')) * 2;
    END IF;

    V_ANSWER := BITAND(V_ANSWER,  TO_NUMBER('FFFF', 'XXXX'));
  END LOOP;
END LOOP;

RETURN V_ID_CRC16||V_QTD_CRC16||TRIM(TO_CHAR(V_ANSWER, 'XXXX'));

END CRC16;

Estou utilizando Oracle Database 11g Release 11.2.0.4.0 - 64bit Production.

Att,

@GabrielPaixaoJustino
Copy link

Boa tarde a todos,

Segue solução que estou utilizando em PL/SQL:

CREATE OR REPLACE FUNCTION CRC16(V_STRING VARCHAR2) RETURN VARCHAR2 IS
CURSOR C_BYTES (PIX_STRING VARCHAR2) IS
SELECT TO_NUMBER(COLUMN_VALUE) AS BYTES
FROM XMLTABLE(
SUBSTR(
DUMP(PIX_STRING),
INSTR(
DUMP(PIX_STRING),
':'
)+1
)
);

C NUMBER;
J NUMBER;

V_ANSWER VARCHAR2(4000) := 'FFFF';
V_POLINOMIO VARCHAR2(4) := '1021';

V_VERIFY NUMBER;

V_ID_CRC16 CHAR(2) := '63';
V_QTD_CRC16 CHAR(2) := '04';
BEGIN
FOR R_BYTES IN C_BYTES(V_STRING||V_ID_CRC16||V_QTD_CRC16)
LOOP
C := R_BYTES.BYTES;

  IF (C_BYTES%ROWCOUNT = 1) THEN
    V_ANSWER := TO_NUMBER(V_ANSWER, 'XXXX');
  END IF;

  J := (C * POWER(2,8));
  V_ANSWER := (J + V_ANSWER) - BITAND(J, V_ANSWER) * 2;

  FOR BITWISE IN 0..7 LOOP
    V_ANSWER := V_ANSWER * POWER(2,1);
    V_VERIFY := BITAND(V_ANSWER, TO_NUMBER('10000', 'XXXXX'));

    IF (V_VERIFY <> 0) THEN
      V_ANSWER := (V_ANSWER + TO_NUMBER(V_POLINOMIO, 'XXXX')) - BITAND(V_ANSWER, TO_NUMBER(V_POLINOMIO, 'XXXX')) * 2;
    END IF;

    V_ANSWER := BITAND(V_ANSWER,  TO_NUMBER('FFFF', 'XXXX'));
  END LOOP;
END LOOP;

RETURN V_ID_CRC16||V_QTD_CRC16||TRIM(TO_CHAR(V_ANSWER, 'XXXX'));

END CRC16;

Estou utilizando Oracle Database 11g Release 11.2.0.4.0 - 64bit Production.

Att,

Boa tarde.
Obrigado, vou verificar para converter em SQL.

@reichert-lucas
Copy link

Pessoal, boa tarde!
Alguém poderia dar uma idéia de como calcular o CRC16?
Agradeço!

@jeansentose tem várias bibliotecas em linguagens diversas no github.
Tem uma rotina neste link, em typescript (javascript++), fácil de converter para a tua linguagem de estimação.
https://github.com/NascentSecureTech/pix-qrcode-utils/blob/master/packages/emv-merchant-qrcode/src/crc.ts

@jeansentose Eu utilizo PHP para gerar o QRCODE.

A funcao que utilizo é: function crc16($string) { $CRC16POLINOMIO = 0x1021; $result = 0xFFFF; if (($length = strlen($string)) > 0) { for ($offset = 0; $offset < $length; $offset++) { $result ^= (ord($string[$offset]) << 8); for ($bitwise = 0; $bitwise < 8; $bitwise++) { if (($result <<= 1) & 0x10000) $result ^= $CRC16POLINOMIO; $result &= 0xFFFF; } } } return $result; } $CRC16 = crc16($stringPix); //Nessa string deve conter o final "6304" $CRC16 = dechex($CRC16); //transformo de decimal para hexadecimal $CRC16 = strtoupper($CRC16); //Transformo para maiusculas

Estou trabalhando em um conversor online. O exemplo está no link https://showcommerce.com.br/pix

Bom dia, pessoal.

Eu estou usando uma solução semelhante a esta em PHP, porém notei que para resultados menores que 4095 (Hexadecimal: FFF), o tamanho não seria o 4, que é o padrão do PIX, seria 3. Para solucionar esse problema, eu adicionei um padding com zeros no início do hexadecimal, que não altera o valor final.

$resultadoCrc16 = strtoupper(dechex($resultadoCrc16));
$resultadoCrc16 = str_pad($resultadoCrc16, 4, '0', STR_PAD_LEFT);

@sibelius
Copy link

sibelius commented Dec 8, 2021

temos um validador online para QRCode EMV ?

@cryptographix
Copy link

tente https://pix.nascent.com.br/tools/pix-qr-decoder/.
Tem opção de verificar e corrigir o CRC.

@thiagosabino-prog
Copy link

Fala ai blz, em delphi estou gerando desta forma.

function CRC16CCITT(texto: string): WORD; const polynomial = $1021; var crc: WORD; i, j: Integer; b: Byte; bit, c15: Boolean; begin crc := $FFFF; for i := 1 to length(texto) do begin b := Byte(texto[i]); for j := 0 to 7 do begin bit := (((b shr (7 - j)) and 1) = 1); c15 := (((crc shr 15) and 1) = 1); crc := crc shl 1; if (c15 xor bit) then crc := crc xor polynomial; end; end; Result := crc and $FFFF; end;

e chamo a função desta forma.

inttohex(CRC16CCITT(minhachave),4);

Testei em diversos bancos só o Itau que estou dependendo do gerente descobrir lá onde libera kkkk.

Estou gerando dessa forma também e em alguns bancos lê de boa e no Itaú, banco do brasil e bradesco não funciona. Teve algum retorno do Itau?

@renatofrota
Copy link

Estou gerando dessa forma também e em alguns bancos lê de boa e no Itaú, banco do brasil e bradesco não funciona. Teve algum retorno do Itau?

Compartilhe um exemplo de QR Code que você gerou. Somente assim poderemos apontar os erros.

@thiagosabino-prog
Copy link

Pessoal consegui agora que funcione em todos os banco que testei. As correções que tive que fazer foram:
1 - Valores terminados e 0, tipo 1,20 estava passando para string 1.2 e no caso do itaú especificamente não aceita tem que ser formatado assim: 1.20
2 - Cidades com mais de 15 caracteres e acento também não aceita te que ser no máximo 15 e sem acento.

Feito essas correções até agora está tudo funcionando.

@inklys
Copy link

inklys commented Apr 10, 2022

Olá, tenho esse payload do pix dinamico e não faço a minima ideia de por que não está sendo aceito pelo aplicativo do banco do brasil:

000201
2683
0014br.gov.bcb.pix
2561api.pagseguro.com/pix/v2/916CED9B-C6EE-4C8B-A6B2-C0D652B63BBB
52048999
5303986
5802BR
5921Pagseguro Internet SA
6009SAO PAULO
6230
0526riz8aOMtu5m6YURewDFpsEBpjy
6304A5C6

Quem puder me ajudar fico grato.

@reichert-lucas
Copy link

reichert-lucas commented Apr 10, 2022

Olá, tenho esse payload do pix dinamico e não faço a minima ideia de por que não está sendo aceito pelo aplicativo do banco do brasil:

000201 2683 0014br.gov.bcb.pix 2561api.pagseguro.com/pix/v2/916CED9B-C6EE-4C8B-A6B2-C0D652B63BBB 52048999 5303986 5802BR 5921Pagseguro Internet SA 6009SAO PAULO 6230 0526riz8aOMtu5m6YURewDFpsEBpjy 6304A5C6

Quem puder me ajudar fico grato.

Bom dia. Aparentemente o seu elemento 62 (Additional Data Field Template) > 05 (Reference Label) ultrapassou o tamanho máximo de 25 caracteres, ele tem 26. Você pode fazer esse tipo de verificação da string do Qrcode nesse endereço: https://pix.nascent.com.br/tools/pix-qr-decoder/. Além disso, esse campo deve conter o valor ***, sem passar o txid.

@rubenskuhl
Copy link

Olá, tenho esse payload do pix dinamico e não faço a minima ideia de por que não está sendo aceito pelo aplicativo do banco do brasil:

000201 2683 0014br.gov.bcb.pix 2561api.pagseguro.com/pix/v2/916CED9B-C6EE-4C8B-A6B2-C0D652B63BBB 52048999 5303986 5802BR 5921Pagseguro Internet SA 6009SAO PAULO 6230 0526riz8aOMtu5m6YURewDFpsEBpjy 6304A5C6

Quem puder me ajudar fico grato.

No QR-Code dinâmico, o campo 62:05 deve conter apenas *** (três asteriscos), e não o txid.

@inklys
Copy link

inklys commented Apr 11, 2022

Obrigado ao reichert-lucas e rubenskuhl, final mente funcionou. Não sei se faz parte do assunto desse tópico, mas se tiver alguém para me dar uma orientação sobre notificações (PagSeguro) fico grato.

@rubenskuhl
Copy link

Obrigado ao reichert-lucas e rubenskuhl, final mente funcionou. Não sei se faz parte do assunto desse tópico, mas se tiver alguém para me dar uma orientação sobre notificações (PagSeguro) fico grato.

Na última vez que olhei a API do PagSeguro, eles me parecem seguir (finalmente) a API padrão do Banco Central... então se isso for verdade para a parte de notificações, podemos tentar nessa linha. Até onde você chegou e o que não funcionou ?

@inklys
Copy link

inklys commented Apr 11, 2022

Na verdade eu nem comecei, não ficou muito claro pra mim o conceito de webhook, e como preparar o sistema para receber a notificação

@reichert-lucas
Copy link

Na verdade eu nem comecei, não ficou muito claro pra mim o conceito de webhook, e como preparar o sistema para receber a notificação

A webhook é uma forma de tu ter um retorno sobre as atualizações de um pagamento (por exemplo), basicamente, tu vai ter uma rota no teu sistema que vai estar preparada para atualizar o pagamento quando o gateway de pagamento te informar que houve um pagamento. Um exemplo pode ser do próprio pix, se tu gerar uma cobrança do pix é muito menos trabalhoso o gateway de pagamento te avisar quando o pagamento for realizado, caso contrário tu teria que ficar consultando se o pagamento foi realizado (de tempos em tempos, por exemplo de 30 em 30 segundos), e isso acaba gastando mais recursos da sua aplicação e do gateway de pagamento.

@rubenskuhl
Copy link

Na verdade eu nem comecei, não ficou muito claro pra mim o conceito de webhook, e como preparar o sistema para receber a notificação

Na API Pix tem 3 jeitos de saber que uma cobrança foi paga:

  • GET /cob/:txid ; se houver um objeto Pix, foi paga.
  • GET /pix com filtro por inicio, termino e txid; se houver algum objeto, foi paga.
  • Webhook, onde o servidor do PSP te avisa que foi pago. Diferente das outras requisições da API, aqui o servidor é seu e o client é o seu banco(PSP).

Como mesmo com o webhook é bom ter um "recuperador", comece implementando um dos outros dois. Aí parta para implementar o webhook, que normalmente requer mais traquejo de configuração de webserver do que os devs usuais tem.

@inklys
Copy link

inklys commented Apr 12, 2022

Obrigado pelas dicas rubenskuhl, eu gostaria mesmo é da Webhook, tem que implementar algum certificado, curl, ou é só pegar os dados da request mesmo? Sabe se vem em Json?

@rubenskuhl
Copy link

Obrigado pelas dicas rubenskuhl, eu gostaria mesmo é da Webhook, tem que implementar algum certificado, curl, ou é só pegar os dados da request mesmo? Sabe se vem em Json?

Tem que implementar certificado, o Banco Central exige que haja mTLS na transação.
Os dados vem sim em JSON, um exemplo:

  "pix": [
    {
      "endToEndId": "E1803615022211340s08793XPJ",
      "txid": "fc9a43k6ff384ryP5f41719",
      "chave": "2c3c7441-b91e-4982-3c25-6105581e18ae",     
      "valor": "0.01",
      "horario": "2020-12-21T13:40:34.000Z",
      "infoPagador": "pagando o pix"
    }
  ]
}```

@matias-prog
Copy link

Segue solução que estou utilizando em PL/SQL:

CREATE OR REPLACE FUNCTION CRC16(V_STRING VARCHAR2) RETURN VARCHAR2 IS
CURSOR C_BYTES (PIX_STRING VARCHAR2) IS
SELECT TO_NUMBER(COLUMN_VALUE) AS BYTES
FROM XMLTABLE(
SUBSTR(
DUMP(PIX_STRING),
INSTR(
DUMP(PIX_STRING),
':'
)+1
)
);

C NUMBER;
J NUMBER;

V_ANSWER VARCHAR2(4000) := 'FFFF';
V_POLINOMIO VARCHAR2(4) := '1021';

V_VERIFY NUMBER;

V_ID_CRC16 CHAR(2) := '63';
V_QTD_CRC16 CHAR(2) := '04';
BEGIN
FOR R_BYTES IN C_BYTES(V_STRING||V_ID_CRC16||V_QTD_CRC16)
LOOP
C := R_BYTES.BYTES;

IF (C_BYTES%ROWCOUNT = 1) THEN
V_ANSWER := TO_NUMBER(V_ANSWER, 'XXXX');
END IF;

J := (C * POWER(2,8));
V_ANSWER := (J + V_ANSWER) - BITAND(J, V_ANSWER) * 2;

FOR BITWISE IN 0..7 LOOP
V_ANSWER := V_ANSWER * POWER(2,1);
V_VERIFY := BITAND(V_ANSWER, TO_NUMBER('10000', 'XXXXX'));

IF (V_VERIFY <> 0) THEN
  V_ANSWER := (V_ANSWER + TO_NUMBER(V_POLINOMIO, 'XXXX')) - BITAND(V_ANSWER, TO_NUMBER(V_POLINOMIO, 'XXXX')) * 2;
END IF;

V_ANSWER := BITAND(V_ANSWER,  TO_NUMBER('FFFF', 'XXXX'));

END LOOP;
END LOOP;

RETURN V_ID_CRC16||V_QTD_CRC16||TRIM(TO_CHAR(V_ANSWER, 'XXXX'));

END CRC16;

Estou utilizando Oracle Database 11g Release 11.2.0.4.0 - 64bit Production.

Att,

No entiendo, ¿qué hay en la tabla XMLTABLE?, ¿de dónde sale?.

@inklys
Copy link

inklys commented May 16, 2022

Olá,
Estou tentando implementar o webhook, do pagseguro, mas não faço a menor ideia de como implementar a autenticação mTSL, quem puder me passar alguma dica ou material em PHP fico muito grato.

@rubenskuhl
Copy link

Olá, Estou tentando implementar o webhook, do pagseguro, mas não faço a menor ideia de como implementar a autenticação mTSL, quem puder me passar alguma dica ou material em PHP fico muito grato.

Apesar de ser de outro PSP, esta documentação provavelmente resolva suas questões dada a padronização da API Pix:
https://dev.gerencianet.com.br/docs/api-pix-endpoints#section-entendendo-o-padr-o-mtls

A questão é muito mais o web server que você utiliza (na seção seguinte a acima há exemplos de configuração para Apache, nginx e outros servidores), do que a linguagem que você utiliza.

@Robertodevinomazzarolo
Copy link

Senhores, tem alguém que desenvolveu o calculo do CRC16 em VBA?? peguei um que o Professor Rebson Mendes liberou mas não esta funcionando sera que alguem tem outro pra eu comparar onde estou errando??

@prjosemaria
Copy link

Boa tarde a todos,

Segue solução que estou utilizando em PL/SQL:

CREATE OR REPLACE FUNCTION CRC16(V_STRING VARCHAR2) RETURN VARCHAR2 IS CURSOR C_BYTES (PIX_STRING VARCHAR2) IS SELECT TO_NUMBER(COLUMN_VALUE) AS BYTES FROM XMLTABLE( SUBSTR( DUMP(PIX_STRING), INSTR( DUMP(PIX_STRING), ':' )+1 ) );

C NUMBER; J NUMBER;

V_ANSWER VARCHAR2(4000) := 'FFFF'; V_POLINOMIO VARCHAR2(4) := '1021';

V_VERIFY NUMBER;

V_ID_CRC16 CHAR(2) := '63'; V_QTD_CRC16 CHAR(2) := '04'; BEGIN FOR R_BYTES IN C_BYTES(V_STRING||V_ID_CRC16||V_QTD_CRC16) LOOP C := R_BYTES.BYTES;

  IF (C_BYTES%ROWCOUNT = 1) THEN
    V_ANSWER := TO_NUMBER(V_ANSWER, 'XXXX');
  END IF;

  J := (C * POWER(2,8));
  V_ANSWER := (J + V_ANSWER) - BITAND(J, V_ANSWER) * 2;

  FOR BITWISE IN 0..7 LOOP
    V_ANSWER := V_ANSWER * POWER(2,1);
    V_VERIFY := BITAND(V_ANSWER, TO_NUMBER('10000', 'XXXXX'));

    IF (V_VERIFY <> 0) THEN
      V_ANSWER := (V_ANSWER + TO_NUMBER(V_POLINOMIO, 'XXXX')) - BITAND(V_ANSWER, TO_NUMBER(V_POLINOMIO, 'XXXX')) * 2;
    END IF;

    V_ANSWER := BITAND(V_ANSWER,  TO_NUMBER('FFFF', 'XXXX'));
  END LOOP;
END LOOP;

RETURN V_ID_CRC16||V_QTD_CRC16||TRIM(TO_CHAR(V_ANSWER, 'XXXX'));

END CRC16;

Estou utilizando Oracle Database 11g Release 11.2.0.4.0 - 64bit Production.

Att,

Olá seria possivel converter essa função para postgresql 9?

Alguém teria ela para postgresql 9+

@derzu
Copy link

derzu commented Oct 18, 2022

Segue um exemplo de geração do PIX qr code estático todo em javascript:
https://github.com/derzu/pix-qrcode

@maicon451
Copy link

Boa tarde!

Alguém já fez essa função para DataFlex?

@baldinifabio
Copy link

Valeu meu querido !! Agradeço muito a ajuda !!

Você conseguiu gerar? se sim para qual linguagem? não estou conseguindo gerar em c# :/

Neste Repositorio tem de várias linguagens - https://gist.github.com/tijnkooijmans/10981093

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BR Code issues relativas à especificação do BR Code Dica Uma informação oriunda da comunidade (e não do BACEN) para o benefício da comunidade Erros dos PSPs Os PSPs não estão implementando algo de maneira adequada QR Dinâmico aspectos concernentes ao QR Dinâmico Pix QR Estático Aspectos concernentes ao QR Estático Pix
Projects
None yet
Development

No branches or pull requests