Jump to content
Fivewin Brasil

PIX - QR CODE


Theotokos

Recommended Posts

Amiguinhos,

A string do QRCode para PIX não tem muito problema de geração já que é concatenação de palavras. O problema reside na geração do verificador de 4 digitos que vai no final da string principal para completar e gerar o QRCode.

Fontes de Teste:

Gerar PIX Online

Gerador QRCode PIX

Gerador de QRCode do PIX

Gerador de QRCode PIX Estático

Gerador QRCode PIX CIGAM

Teste de CRC e outros:

Testes variados

Explicaç~pes sobre CRC:

Manual do cálculo de redundância

 

 

 

 

Link to comment
Share on other sites

Apanhei muito nessa questão de CRC no xHarbour, então busquei as funcoes em C de diversos algoritmos e adaptei a minha necessidade. Segue ai 4 algoritmos de CRC, sendo que o Kermit tem uma variante para inverter os bytes. Veja qual algoritmo é o que você precisa e bom trabalho.

 

Function u_Teste()
Local cTexto := "teste crc"

? "EMTCRC_CCITT_FFFF", cTexto, EMTCRC_CCITT_FFFF(cTexto)
? "EMTCRC_CRC_16", cTexto, EMTCRC_CRC_16(cTexto)
? "EMTCRC_CRC_MODBUS", cTexto, EMTCRC_CRC_MODBUS(cTexto)
? "EMTCRC_CRC_KERMIT (invert=.t.)", cTexto, EMTCRC_CRC_KERMIT(cTexto)
? "EMTCRC_CRC_KERMIT (invert=.f.)", cTexto, EMTCRC_CRC_KERMIT(cTexto, .f.)

Return



Function EMTCRC_CCITT_FFFF(cTexto)
Local cCrc,nCrc
nCrc := C_EMTCRC_CCITT_FFFF(cTexto)
cCrc := NumToHex(nCrc)
cCrc := PadL(NumToHex(nCrc), 4, "0")
Return cCrc

Function EMTCRC_CRC_16(cTexto)
Local cCrc,nCrc
nCrc := C_EMTCRC_CRC_16(cTexto)
cCrc := NumToHex(nCrc)
cCrc := PadL(NumToHex(nCrc), 4, "0")
Return cCrc

Function EMTCRC_CRC_MODBUS(cTexto)
Local cCrc,nCrc
nCrc := C_EMTCRC_CRC_MODBUS(cTexto)
cCrc := NumToHex(nCrc)
cCrc := PadL(NumToHex(nCrc), 4, "0")
Return cCrc


Function EMTCRC_CRC_KERMIT(cTexto, lInvert)
Local cCrc, nCrc, nI
If lInvert == nil
    lInvert := .t.
EndIf

nCrc := C_EMTCRC_CRC_KERMIT(cTexto)
cCrc := PadL(NumToHex(nCrc), 4, "0")

If lInvert
    cCrc_Str := HexTostr(cCrc)
    cCrc := ""
    For nI := Len(cCrc_Str) to 1 Step -1
        cCrc+=cCrc_Str[nI]
    Next
    cCrc := StrToHex(cCrc)
EndIf

Return cCrc
    

#pragma BEGINDUMP
#include "windows.h"
#include "hbapi.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#ifndef DEF_LIBCRC_CHECKSUM_H
#define DEF_LIBCRC_CHECKSUM_H


#define		CRC_POLY_16		0xA001
#define		CRC_POLY_32		0xEDB88320L
#define		CRC_POLY_CCITT		0x1021
#define		CRC_POLY_DNP		0xA6BC
#define		CRC_POLY_KERMIT		0x8408
#define		CRC_POLY_SICK		0x8005

#define		CRC_START_8		0x00
#define		CRC_START_16		0x0000
#define		CRC_START_MODBUS	0xFFFF
#define		CRC_START_XMODEM	0x0000
#define		CRC_START_CCITT_1D0F	0x1D0F
#define		CRC_START_CCITT_FFFF	0xFFFF
#define		CRC_START_KERMIT	0x0000
#define		CRC_START_SICK		0x0000
#define		CRC_START_DNP		0x0000
#define		CRC_START_32		0xFFFFFFFFL

unsigned char *		checksum_NMEA(     const unsigned char *input_str, unsigned char *result  );
uint8_t			crc_8(             const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_16(            const unsigned char *input_str, size_t num_bytes       );
uint32_t		crc_32(            const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_ccitt_1d0f(    const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_ccitt_ffff(    const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_dnp(           const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_kermit(        const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_modbus(        const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_sick(          const unsigned char *input_str, size_t num_bytes       );
uint16_t		crc_xmodem(        const unsigned char *input_str, size_t num_bytes       );
uint8_t			update_crc_8(      uint8_t  crc, unsigned char c                          );
uint16_t		update_crc_16(     uint16_t crc, unsigned char c                          );
uint32_t		update_crc_32(     uint32_t crc, unsigned char c                          );
uint16_t		update_crc_ccitt(  uint16_t crc, unsigned char c                          );
uint16_t		update_crc_dnp(    uint16_t crc, unsigned char c                          );
uint16_t		update_crc_kermit( uint16_t crc, unsigned char c                          );
uint16_t		update_crc_sick(   uint16_t crc, unsigned char c, unsigned char prev_byte );

#endif  // DEF_LIBCRC_CHECKSUM_H


static uint16_t		crc_ccitt_generic( const unsigned char *input_str, size_t num_bytes, uint16_t start_value );
static void             init_crcccitt_tab( void );

static bool             crc_tabccitt_init       = false;
static uint16_t         crc_tabccitt[256];

static void		init_crc_tab( void );

static bool		crc_tab_init		= false;
static uint16_t		crc_tab[256];

/*
 * uint16_t crc_xmodem( const unsigned char *input_str, size_t num_bytes );
 *
 * The function crc_xmodem() performs a one-pass calculation of an X-Modem CRC
 * for a byte string that has been passed as a parameter.
 */

uint16_t crc_xmodem( const unsigned char *input_str, size_t num_bytes ) {

	return crc_ccitt_generic( input_str, num_bytes, CRC_START_XMODEM );

}  /* crc_xmodem */

/*
 * uint16_t crc_ccitt_1d0f( const unsigned char *input_str, size_t num_bytes );
 *
 * The function crc_ccitt_1d0f() performs a one-pass calculation of the CCITT
 * CRC for a byte string that has been passed as a parameter. The initial value
 * 0x1d0f is used for the CRC.
 */

uint16_t crc_ccitt_1d0f( const unsigned char *input_str, size_t num_bytes ) {

	return crc_ccitt_generic( input_str, num_bytes, CRC_START_CCITT_1D0F );

}  /* crc_ccitt_1d0f */

/*
 * uint16_t crc_ccitt_ffff( const unsigned char *input_str, size_t num_bytes );
 *
 * The function crc_ccitt_ffff() performs a one-pass calculation of the CCITT
 * CRC for a byte string that has been passed as a parameter. The initial value
 * 0xffff is used for the CRC.
 */

uint16_t crc_ccitt_ffff( const unsigned char *input_str, size_t num_bytes ) {

	return crc_ccitt_generic( input_str, num_bytes, CRC_START_CCITT_FFFF );

}  /* crc_ccitt_ffff */

/*
 * static uint16_t crc_ccitt_generic( const unsigned char *input_str, size_t num_bytes, uint16_t start_value );
 *
 * The function crc_ccitt_generic() is a generic implementation of the CCITT
 * algorithm for a one-pass calculation of the CRC for a byte string. The
 * function accepts an initial start value for the crc.
 */

static uint16_t crc_ccitt_generic( const unsigned char *input_str, size_t num_bytes, uint16_t start_value ) {

	uint16_t crc;
	uint16_t tmp;
	uint16_t short_c;
	const unsigned char *ptr;
	size_t a;

	if ( ! crc_tabccitt_init ) init_crcccitt_tab();

	crc = start_value;
	ptr = input_str;

	if ( ptr != NULL ) for (a=0; a<num_bytes; a++) {

		short_c = 0x00ff & (unsigned short) *ptr;
		tmp     = (crc >> 8) ^ short_c;
		crc     = (crc << 8) ^ crc_tabccitt[tmp];

		ptr++;
	}

	return crc;

}  /* crc_ccitt_generic */

/*
 * uint16_t update_crc_ccitt( uint16_t crc, unsigned char c );
 *
 * The function update_crc_ccitt() calculates a new CRC-CCITT value based on
 * the previous value of the CRC and the next byte of the data to be checked.
 */

uint16_t update_crc_ccitt( uint16_t crc, unsigned char c ) {

	int16_t tmp;
	int16_t short_c;

	short_c  = 0x00ff & (uint16_t) c;

	if ( ! crc_tabccitt_init ) init_crcccitt_tab();

	tmp = (crc >> 8) ^ short_c;
	crc = (crc << 8) ^ crc_tabccitt[tmp];

	return crc;

}  /* update_crc_ccitt */

/*
 * static void init_crcccitt_tab( void );
 *
 * For optimal performance, the routine to calculate the CRC-CCITT uses a
 * lookup table with pre-compiled values that can be directly applied in the
 * XOR action. This table is created at the first call of the function by the
 * init_crcccitt_tab() routine.
 */

static void init_crcccitt_tab( void ) {

	uint16_t i;
	uint16_t j;
	uint16_t crc;
	uint16_t c;

	for (i=0; i<256; i++) {

		crc = 0;
		c   = i << 8;

		for (j=0; j<8; j++) {

			if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ CRC_POLY_CCITT;
			else                      crc =   crc << 1;

			c = c << 1;
		}

		crc_tabccitt[i] = crc;
	}

	crc_tabccitt_init = true;

}
// ========================================================================

static void             init_crc16_tab( void );

static bool             crc_tab16_init          = false;
static uint16_t         crc_tab16[256];

/*
 * uint16_t crc_16( const unsigned char *input_str, size_t num_bytes );
 *
 * The function crc_16() calculates the 16 bits CRC16 in one pass for a byte
 * string of which the beginning has been passed to the function. The number of
 * bytes to check is also a parameter. The number of the bytes in the string is
 * limited by the constant SIZE_MAX.
 */

uint16_t crc_16( const unsigned char *input_str, size_t num_bytes ) {

	uint16_t crc;
	uint16_t tmp;
	uint16_t short_c;
	const unsigned char *ptr;
	size_t a;

	if ( ! crc_tab16_init ) init_crc16_tab();

	crc = CRC_START_16;
	ptr = input_str;

	if ( ptr != NULL ) for (a=0; a<num_bytes; a++) {

		short_c = 0x00ff & (uint16_t) *ptr;
		tmp     =  crc       ^ short_c;
		crc     = (crc >> 8) ^ crc_tab16[ tmp & 0xff ];

		ptr++;
	}

	return crc;

}  /* crc_16 */

/*
 * uint16_t crc_modbus( const unsigned char *input_str, size_t num_bytes );
 *
 * The function crc_modbus() calculates the 16 bits Modbus CRC in one pass for
 * a byte string of which the beginning has been passed to the function. The
 * number of bytes to check is also a parameter.
 */

uint16_t crc_modbus( const unsigned char *input_str, size_t num_bytes ) {

	uint16_t crc;
	uint16_t tmp;
	uint16_t short_c;
	const unsigned char *ptr;
	size_t a;

	if ( ! crc_tab16_init ) init_crc16_tab();

	crc = CRC_START_MODBUS;
	ptr = input_str;

	if ( ptr != NULL ) for (a=0; a<num_bytes; a++) {

		short_c = 0x00ff & (uint16_t) *ptr;
		tmp     =  crc       ^ short_c;
		crc     = (crc >> 8) ^ crc_tab16[ tmp & 0xff ];

		ptr++;
	}

	return crc;

}  /* crc_modbus */


/*
 * uint16_t crc_kermit( const unsigned char *input_str, size_t num_bytes );
 *
 * The function crc_kermit() calculates the 16 bits Kermit CRC in one pass for
 * a byte string of which the beginning has been passed to the function. The
 * number of bytes to check is also a parameter.
 */

 uint16_t crc_kermit( const unsigned char *input_str, size_t num_bytes ) {

uint16_t crc;
uint16_t low_byte;
uint16_t high_byte;
const unsigned char *ptr;
size_t a;

if ( ! crc_tab_init ) init_crc_tab();

crc = CRC_START_KERMIT;
ptr = input_str;

if ( ptr != NULL ) for (a=0; a<num_bytes; a++) {

   crc = (crc >> 8) ^ crc_tab[ (crc ^ (uint16_t) *ptr++) & 0x00FF ];
}

low_byte  = (crc & 0xff00) >> 8;
high_byte = (crc & 0x00ff) << 8;
crc       = low_byte | high_byte;

return crc;

}  /* crc_kermit */

/*
* static void init_crc_tab( void );
*
* For optimal performance, the  CRC Kermit routine uses a lookup table with
* values that can be used directly in the XOR arithmetic in the algorithm.
* This lookup table is calculated by the init_crc_tab() routine, the first
* time the CRC function is called.
*/

static void init_crc_tab( void ) {

uint16_t i;
uint16_t j;
uint16_t crc;
uint16_t c;

for (i=0; i<256; i++) {

   crc = 0;
   c   = i;

   for (j=0; j<8; j++) {

      if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ CRC_POLY_KERMIT;
      else                      crc =   crc >> 1;

      c = c >> 1;
   }

   crc_tab[i] = crc;
}

crc_tab_init = true;

}  /* init_crc_tab */


/*
 * uint16_t update_crc_16( uint16_t crc, unsigned char c );
 *
 * The function update_crc_16() calculates a new CRC-16 value based on the
 * previous value of the CRC and the next byte of data to be checked.
 */

uint16_t update_crc_16( uint16_t crc, unsigned char c ) {

	uint16_t tmp;
	uint16_t short_c;

	short_c = 0x00ff & (uint16_t) c;

	if ( ! crc_tab16_init ) init_crc16_tab();

	tmp =  crc       ^ short_c;
	crc = (crc >> 8) ^ crc_tab16[ tmp & 0xff ];

	return crc;

}  /* update_crc_16 */

/*
 * static void init_crc16_tab( void );
 *
 * For optimal performance uses the CRC16 routine a lookup table with values
 * that can be used directly in the XOR arithmetic in the algorithm. This
 * lookup table is calculated by the init_crc16_tab() routine, the first time
 * the CRC function is called.
 */

static void init_crc16_tab( void ) {

	uint16_t i;
	uint16_t j;
	uint16_t crc;
	uint16_t c;

	for (i=0; i<256; i++) {

		crc = 0;
		c   = i;

		for (j=0; j<8; j++) {

			if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ CRC_POLY_16;
			else                      crc =   crc >> 1;

			c = c >> 1;
		}

		crc_tab16[i] = crc;
	}

	crc_tab16_init = true;

}  /* init_crc16_tab */


// ========================================================================
HB_FUNC( C_EMTCRC_CCITT_FFFF ) // cText --> nTextCRC
{
   hb_retnl( crc_ccitt_ffff( ( unsigned char *  ) hb_parc( 1 ), hb_parclen( 1 ) ) );

}

HB_FUNC( C_EMTCRC_CRC_16 ) // cText --> nTextCRC
{
   hb_retnl( crc_16( ( unsigned char *  ) hb_parc( 1 ), hb_parclen( 1 ) ) );

}

HB_FUNC( C_EMTCRC_CRC_MODBUS ) // cText --> nTextCRC
{
   hb_retnl( crc_modbus( ( unsigned char *  ) hb_parc( 1 ), hb_parclen( 1 ) ) );
}

HB_FUNC( C_EMTCRC_CRC_KERMIT ) // cText --> nTextCRC - codigo fonte obtido em https://github.com/lammertb/libcrc/tree/master/src
{
   hb_retnl( crc_kermit( ( unsigned char *  ) hb_parc( 1 ), hb_parclen( 1 ) ) );
}

#pragma ENDDUMP
Link to comment
Share on other sites

Em 01/04/2022 at 20:08, Ladinilson disse:

"Funcionando Legal" !!??
Lá no tópico disse que não estava gerando e apresentando o QR Code!

SIM!!! Nas depois entrei em contato com ele pelo whats que ele forneceu lá, atendeu prontamente e gerou uma LIB (nova) para gerar apenas o dados concatena e faz o crc16, ai eu mesmo gero o QR-Code com hbZebra ou inves do QrCodeLib que ele utiliza... 

 

             cTextoQrCode  :=   Pag_Pix( "+55TELEFONE", "NOME IDENTIFICAÇÃO", "CIDADE", VALOR )     // Essa a Função da Lib do gunafe
             
             QrCodeMain(cTextoQrCode,"PIX\QRPIX"+StrZero(np1,2)+strzero(nnumero,8)+".PNG")   // Essa Funão criei para gerar QR Code com HBZebra

 

 

 

Link to comment
Share on other sites

Exemplo funcional gerando QRCODE para PIX.

Usei o fonte que o João postou neste mesmo tópico, um exemplo antigo que postei para gerar qrcode e uma função para gerar o CRC exigido no PIX que não existe em xHarbour

façam os devidos testes e a responsabilidade de uso é de cada um (MIT License)

Segue tudo no GITHUB em um repositório publico

https://github.com/eduardomotta-emottasistemas/pix_qrcode.git

 

Link to comment
Share on other sites

30 minutos atrás, emotta disse:

Exemplo funcional gerando QRCODE para PIX.

Usei o fonte que o João postou neste mesmo tópico, um exemplo antigo que postei para gerar qrcode e uma função para gerar o CRC exigido no PIX que não existe em xHarbour

façam os devidos testes e a responsabilidade de uso é de cada um (MIT License)

Segue tudo no GITHUB em um repositório publico

https://github.com/eduardomotta-emottasistemas/pix_qrcode.git

 

Boa noite emotta! Estou testando a sua rotina (tentando)... mas qdo compilo aparece erro em algumas linha dizendo: conversion may lose significant digits in function crc_ccitt_generic (ai são varias outras funcoes tmb), nas linhas 192,193,194, etc

        short_c = 0x00ff & (unsigned short) *ptr;
        tmp     = (crc >> 8) ^ short_c;
        crc     = (crc << 8) ^ crc_tabccitt[tmp];
 

algo que estou compilando errado, falta alguma lib? o que pode ser?

 

Link to comment
Share on other sites

12 horas atrás, Theotokos disse:

OBGDAO

Eu refatorei o código e tirei tudo que não era necessário, nele tinha várias funções de CRC e eu deixei apenas a que é usada para gerar o PIX.

Então clone novamente o repositório pra pegar as ultimas modificações que eu fiz, compile o código e executa. Veja se continua o problema.

Lembrando que é necessário colocar as libs do fivewin.

Link to comment
Share on other sites

Em 05/04/2022 at 08:52, emotta disse:

Eu refatorei o código e tirei tudo que não era necessário, nele tinha várias funções de CRC e eu deixei apenas a que é usada para gerar o PIX.

Então clone novamente o repositório pra pegar as ultimas modificações que eu fiz, compile o código e executa. Veja se continua o problema.

Lembrando que é necessário colocar as libs do fivewin.

Oi Bom Dia!!!!

Não Resolveu o erro!!!

conversion may lose significant digits in function crc_ccitt_generic da na linha 128,129,130

 128:       short_c = 0x00ff & (unsigned short) *ptr;
 129:       tmp     = (crc >> 8) ^ short_c;
 130:        crc     = (crc << 8) ^ crc_tabccitt[tmp];

Link to comment
Share on other sites

É um warning ou é um erro? Você pode postar um print da tela?

Você fez alguma mudança no test_pix.prg ? Estranho ter erro de compilação pois compilo normalmente. Meu xHarbour é o comercial e compilo pelo xBuild

Se o seu xharbour não é o comercial possivelmente é algo que você precisa setar na hora da compilação deste código que é em C.

 

Link to comment
Share on other sites

2 horas atrás, emotta disse:

É um warning ou é um erro? Você pode postar um print da tela?

Você fez alguma mudança no test_pix.prg ? Estranho ter erro de compilação pois compilo normalmente. Meu xHarbour é o comercial e compilo pelo xBuild

Se o seu xharbour não é o comercial possivelmente é algo que você precisa setar na hora da compilação deste código que é em C.

 

* (62/63) Compilando test_pix.c
Embarcadero C++ 7.40 for Win32 Copyright (c) 1993-2018 Embarcadero Technologies, Inc.
.\test_pix.c:
Warning W8071 D:\\Tools\\QRCode\\test_pix.prg 128: Conversion may lose significant digits in function crc_ccitt_generic
Warning W8071 D:\\Tools\\QRCode\\test_pix.prg 129: Conversion may lose significant digits in function crc_ccitt_generic
Warning W8071 D:\\Tools\\QRCode\\test_pix.prg 130: Conversion may lose significant digits in function crc_ccitt_generic
*** 1 errors in Compile ***
Fim do script de compilacao!

utilizo xHarbour 123 e bcc74  e utilizo xDev72 para editar e compilar

E Não fiz nenhuma mudança, apenas baixei e incluir no projeto de um sistema meu

Link to comment
Share on other sites

1 hora atrás, Theotokos disse:

* (62/63) Compilando test_pix.c
Embarcadero C++ 7.40 for Win32 Copyright (c) 1993-2018 Embarcadero Technologies, Inc.
.\test_pix.c:
Warning W8071 D:\\Tools\\QRCode\\test_pix.prg 128: Conversion may lose significant digits in function crc_ccitt_generic
Warning W8071 D:\\Tools\\QRCode\\test_pix.prg 129: Conversion may lose significant digits in function crc_ccitt_generic
Warning W8071 D:\\Tools\\QRCode\\test_pix.prg 130: Conversion may lose significant digits in function crc_ccitt_generic
*** 1 errors in Compile ***
Fim do script de compilacao!

utilizo xHarbour 123 e bcc74  e utilizo xDev72 para editar e compilar

E Não fiz nenhuma mudança, apenas baixei e incluir no projeto de um sistema meu

essas mensagens são de warning e não é erro. Certamente não é isso que está dando erro.

Faça o teste de maneira isolada, sem colocar no seu projeto. Após tudo funcionando aí sim coloque.

Link to comment
Share on other sites

8 minutos atrás, emotta disse:

essas mensagens são de warning e não é erro. Certamente não é isso que está dando erro.

Faça o teste de maneira isolada, sem colocar no seu projeto. Após tudo funcionando aí sim coloque.

EU FIZ ISSO TMB, TESTEI FORA DO PROJETO, Dá mesma coisa.... muito estranho, não acho o erro... porque só aparece isso ai Warning.... :(

Link to comment
Share on other sites

  • 2 months later...

Emotta , compilei e o meu esta dando esses erros:

 

sera q e a versao do bcc ??

 

Error E2209 C:\\Guardiao_nfce\\lib_pix.prg 38: Unable to open include file 'stdbool.h'
Error E2141 C:\\Guardiao_nfce\\lib_pix.prg 47: Declaration syntax error
Error E2141 C:\\Guardiao_nfce\\lib_pix.prg 52: Declaration syntax error
Error E2141 C:\\Guardiao_nfce\\lib_pix.prg 55: Declaration syntax error
Error E2141 C:\\Guardiao_nfce\\lib_pix.prg 56: Declaration syntax error
Error E2141 C:\\Guardiao_nfce\\lib_pix.prg 58: Declaration syntax error
Error E2141 C:\\Guardiao_nfce\\lib_pix.prg 59: Declaration syntax error
Error E2141 C:\\Guardiao_nfce\\lib_pix.prg 69: Declaration syntax error
*** 8 errors in Compile ***

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...