Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Impresión (https://www.clubdelphi.com/foros/forumdisplay.php?f=4)
-   -   Codigo QR AFIP Argentina (https://www.clubdelphi.com/foros/showthread.php?t=96361)

Carmelo Cash 19-09-2023 12:17:11

Codigo QR AFIP Argentina
 
Buenas noches:

Estoy utilizando delphi 7

Necesito imprimir el codigo QR en las facturas. Ya tengo el componente que imprime el Codigo y puedo armé el string.

Ejemplo:

mensaje:='hola loco';
qr.Text:=mensaje;

Imprimo la factura y escaneo el codigo y se lee.. "Hola loco".

Ahora bien, hay que armar un string con los campos de la factura, pero ese string hay que codificarlo de alguna manera y luego cargarlo al qr.

Ej,
mensaje:='{"factura": 123456, "fecha ":2023-09-10 ..... etc etc}'
mensaje:=fcodificarQR(mensaje);
qr.Text:=mensaje;

ni idea de como es ese fcodificarQR

El link de las especificaciones de la AFIP, están mas abajo, pero son muy claras para quien ya sabe la respuesta.
y les copio el ejemplo de JSON y el codificado.

Si alguien sabe por donde iniciar esto, se lo agradezco.

Saludos



https://www.afip.gob.ar/fe/qr/especificaciones.asp


JSON con datos del comprobante:

{"ver":1,"fecha":"2020-10-13","cuit":30000000007,"ptoVta":10,"tipoCmp":1,"nroCmp":94,"importe":12100,"moneda":"DOL","ctz":65," tipoDocRec":80,"nroDocRec":20000000001,"tipoCodAut":"E","codAut":70417054367476}


Texto codificado en el QR:

https://www.afip.gob.ar/fe/qr/?p=eyJ...A1NDM2NzQ3Nn0=

Carmelo Cash 19-09-2023 12:20:16

Esto último no se copió.

JSON con datos del comprobante:

{"ver":1,"fecha":"2020-10-13","cuit":30000000007,"ptoVta":10,"tipoCmp":1,"nroCmp":94,"importe":12100,"moneda":"DOL","ctz":65," tipoDocRec":80,"nroDocRec":20000000001,"tipoCodAut":"E","codAut":70417054367476}

Carmelo Cash 19-09-2023 12:21:37

Texto codificado en el QR:

https://www.afip.gob.ar/fe/qr/?p=eyJ...A1NDM2NzQ3Nn0=




esto es lo que hay que conseguir

Neftali [Germán.Estévez] 19-09-2023 13:29:30

Tal vez se me escapa algo, pero por lo que he entendido...
1) Montar un JSON con los datos que te piden:
Cita:

{"ver":1,"fecha":"2020-10-13","cuit":30000000007,"ptoVta":10,"tipoCmp":1,"nroCmp":94,"importe":12100,"moneda":"DOL","ctz":65," tipoDocRec":80,"nroDocRec":20000000001,"tipoCodAut":"E","codAut":70417054367476}

2) Codificar ese JSON en base64; Con esa codificación obtienes esto:
Cita:

eyJ2ZXIiOjEsImZlY2hhIjoiMjAyMC0xMC0xMyIsImN1aXQiOjMwMDAwMDAwMDA3LCJwdG9WdGEiOjEwLCJ0aXBvQ21wIjoxLCJu cm9DbXAiOjk0LCJpbXBvcnRlIjoxMjEwMCwibW9uZWRhIjoiRE9MIiwiY3R6Ijo2NSwidGlwb0RvY1JlYyI6ODAsIm5yb0RvY1Jl YyI6MjAwMDAwMDAwMDEsInRpcG9Db2RBdXQiOiJFIiwiY29kQXV0Ijo3MDQxNzA1NDM2NzQ3Nn0
(https://www.base64encode.org/)

3) Con eso montas la URL, añadiendo delante esto: https://www.afip.gob.ar/fe/qr/?p=
Resultado es esta URL:

Cita:

h_t_t_ps://www.afip.gob.ar/fe/qr/?p=eyJ2ZXIiOjEsImZlY2hhIjoiMjAyMC0xMC0xMyIsImN1aXQiOjMwMDAwMDAwMDA3LCJwdG9WdGEiOjEwLCJ0aXBvQ21wIjoxL CJucm9DbXAiOjk0LCJpbXBvcnRlIjoxMjEwMCwibW9uZWRhIjoiRE9MIiwiY3R6Ijo2NSwidGlwb0RvY1JlYyI6ODAsIm5yb0RvY 1JlYyI6MjAwMDAwMDAwMDEsInRpcG9Db2RBdXQiOiJFIiwiY29kQXV0Ijo3MDQxNzA1NDM2NzQ3Nn0=
4) Con eso ya puedes generar un QR:


(https://qrcode.tec-it.com/es)

5) y puedes probar a "decodificarlo" en este web: https://www.codigos-qr.com/lector-qr-online/
Y volverás a obtener el texto:

Cita:

h_t_tps://www.afip.gob.ar/fe/qr/?p=eyJ2ZXIiOjEsImZlY2hhIjoiMjAyMC0xMC0xMyIsImN1aXQiOjMwMDAwMDAwMDA3LCJwdG9WdGEiOjEwLCJ0aXBvQ21wIjoxL CJucm9DbXAiOjk0LCJpbXBvcnRlIjoxMjEwMCwibW9uZWRhIjoiRE9MIiwiY3R6Ijo2NSwidGlwb0RvY1JlYyI6ODAsIm5yb0RvY 1JlYyI6MjAwMDAwMDAwMDEsInRpcG9Db2RBdXQiOiJFIiwiY29kQXV0Ijo3MDQxNzA1NDM2NzQ3Nn0=
NOTA: A las URLs les he añadido h_t_tp... para que se vean completas

duilioisola 19-09-2023 16:08:42

Para crear la imagen QR utilizo el componente TDelphiZXingQRCode
Lo puedes descargar en https://github.com/foxitsoftware/DelphiZXingQRCode

Luego hice un procedimiento que me devuelve un TBitmap del mismo

Código Delphi [-]
procedure CrearCodigoQR(Bitmap: TBitmap; s: string; Factor: integer = 1);
var
  QRCode : TDelphiZXingQRCode;
  Row, Column : integer;
begin
  /// Pinta un codigo QR en el BITMAP.
  /// Modificara el tamaño del BITMAP para que entre el codigo QR.
  /// Factor es el tamaño de cada punto (1 = 1 pixel, 2 son puntos de 2x2 pixels, etc.)

  QRCode := TDelphiZXingQRCode.Create;
  try
     // Configuracion del codigo QR (Alfa o numerico automatico, 4 puntos de borde).
     QRCode.Data := s;
     QRCode.Encoding := qrAuto;
     QRCode.QuietZone := 4;

     // Modifico tamaño del Bitmap
     Bitmap.Height := QRCode.Rows * Factor;
     Bitmap.Width := QRCode.Columns * Factor;

     // Recorro el codigo QR y pinto los puntos
     for Row := 0 to QRCode.Rows - 1 do
     begin
        for Column := 0 to QRCode.Columns - 1 do
        begin
           if (QRCode.IsBlack[Row, Column]) then
              Bitmap.Canvas.Brush.Color := clBlack
           else
              Bitmap.Canvas.Brush.Color := clWhite;

           // Cada punto se corresponderá a un cuadrado de (Factor x Factor) pixeles
           Bitmap.Canvas.FillRect(Classes.Rect((Factor * Column), (Factor * Row), (Factor * Column) + Factor, (Factor * Row) + Factor));
        end;
     end;
  finally
     QRCode.Free;
  end;

Y lo utilizo para la imagen que voy a imprimir.
Código Delphi [-]
        [...]
        Imagen := TImage.Create(nil);
        try
           CrearCodigoQR(Imagen.Picture.Bitmap, xCabecera.FieldByName('SFV_CODIGO_RESPUESTA_RAPIDA').AsString, 3);
           TfrPictureView(View).Picture.Assign(Imagen.Picture);
        finally
           Imagen.Free;
        end;
        [...]

Carmelo Cash 20-09-2023 13:41:44

Buen día:

Gracias por responder.

lo que no sé como hacer es :

"Codificar ese JSON en base64"

duilioisola 20-09-2023 15:03:33

Yo utilizo una unidad que utiliza las librerías de windows para hacer eso...
Pasa de Stream a string y el string está codificado en Base64
También decodifica.

Para utilizarlo con un string -> string deberás crear un TMemoryStream de la cadena (JSON) y pasárselo.

Código Delphi [-]
const
  CRYPT_STRING_BASE64 = 1;

function CryptBinaryToString(pbBinary: PByte; cbBinary: DWORD; dwFlags: DWORD; pszString: PChar; var pcchString: DWORD): BOOL; stdcall;
  external 'Crypt32.dll' Name 'CryptBinaryToStringA';

function CryptStringToBinary(pszString: PChar; cchString: DWORD; dwFlags: DWORD; pbBinary: PByte; var pcbBinary: DWORD; pdwSkip: PDWORD; pdwFlags: PDWORD): BOOL; stdcall;
  external 'Crypt32.dll' Name 'CryptStringToBinaryA';

//---------------------------------------------------------------------------
// Codifica un TMemoryStrean a cadena Encode64
function StreamToStrB64(MStream: TMemoryStream; var Str: string): boolean;
var
  Size : DWORD;
begin
  Result := CryptBinaryToString(MStream.Memory, MStream.Size, CRYPT_STRING_BASE64, 0, Size);
  if Result then
  begin
     SetLength(Str, Size);
     Result := CryptBinaryToString(MStream.Memory, MStream.Size, CRYPT_STRING_BASE64, @Str[1], Size);
  end;
end;

//---------------------------------------------------------------------------
// Decodifica una cadena Encode64 a su binario original en un TMemoryStream
function StrB64ToStream(var Str: string; MStream: TMemoryStream): boolean;
var
  Size : DWORD;
begin
  Result := CryptStringToBinary(@Str[1], Length(Str), CRYPT_STRING_BASE64, 0, Size, nil, nil);
  if Result then
  begin
     MStream.SetSize(Size);
     Result := CryptStringToBinary(@Str[1], Length(Str), CRYPT_STRING_BASE64, MStream.Memory, Size, nil, nil);
  end;
end;

duilioisola 20-09-2023 15:44:33

Un ejemplo de utilización completa sería:

Código Delphi [-]
procedure TFMPruebas.BBase64Click(Sender: TObject);
var
  strJSON, strBase64 : string;
  StreamOrigen, AMemoryStream : TStream;
  QR : TImage;
begin
   inherited;

   // String JSON de ejemplo
   strJSON := '{"ver":1,"fecha":"2020-10-13","cuit":30000000007,"ptoVta":10,"tipoCmp":1,"nroCmp":94,"importe":12100,"moneda":"DOL","ctz":65,"  tipoDocRec":80,"nroDocRec":20000000001,"tipoCodAut":"E","codAut":70417054367476}';

   // Cargo JSON en un Stream
   StreamOrigen := TStringStream.Create(strJSON);
   AMemoryStream := TMemoryStream.Create;
   QR := TImage.Create(Self);
   try
      AMemoryStream.CopyFrom(StreamOrigen, StreamOrigen.Size);
      // Convierto a Base64
      StreamToStrB64(TMemoryStream(AMemoryStream), strBase64);

      // Creo imagen con código QR de string Base64
      CrearCodigoQR(QR.Picture.Bitmap, strBase64, 3);
   finally
      StreamOrigen.Free;
      AMemoryStream.Free;
      QR.Free;
   end;
end;

Neftali [Germán.Estévez] 21-09-2023 09:40:55

Cita:

Empezado por Carmelo Cash (Mensaje 552578)
"Codificar ese JSON en base64"


Ya te han puesto ejemplos.
En la docwiki de embarcadero tienes información de cómo hacerlo. Las versiones nueva ya incluyen lo necesario para hacerlo.
https://docwiki.embarcadero.com/Libr...coding_Methods

Esta clase: System.NetEncoding.TBase64Encoding se describe como:
Provides methods to encode and decode data in base64 format.

Posee métodos de clase que puedes llamar directamente.
Y algún ejemplos:

For example:

Encode('Example') returns 'RXhhbXBsZQ=='.
Decode('RXhhbXBsZQ==') returns 'Example'.

Carmelo Cash 25-09-2023 16:33:14

Casi Casi
 
Buenos días:

Estoy probando la función que pasó duilioisola.


El tema es que codifica bien hasta la posición 164, luego comienzan las diferencias..
:confused:


esto debería dar:

eyJ2ZXIiOjEsImZlY2hhIjoiMjAyMC0xMC0xMyIsImN1aXQiOjMwMDAwMDAwMDA3LCJwdG9WdGEiOjEwLCJ0aXBvQ21wIjoxLCJu cm9DbXAiOjk0LCJpbXBvcnRlIjoxMjEwMCwibW9uZWRhIjoiRE9MIiwiY3R6Ijo2NSwidGlwb0RvY1JlYyI6ODAsIm5yb0RvY1Jl YyI6MjAwMDAwMDAwMDEsInRpcG9Db2RBdXQiOiJFIiwiY29kQXV0Ijo3MDQxNzA1NDM2NzQ3Nn0

esto da:

eyJ2ZXIiOjEsImZlY2hhIjoiMjAyMC0xMC0xMyIsImN1aXQiOjMwMDAwMDAwMDA3
LCJwdG9WdGEiOjEwLCJ0aXBvQ21wIjoxLCJucm9DbXAiOjk0LCJpbXBvcnRlIjox
MjEwMCwibW9uZWRhIjoiRE9MIiwiY3R6Ijo2NSwiIHRpcG9Eb2NSZWMiOjgwLCJu
cm9Eb2NSZWMiOjIwMDAwMDAwMDAxLCJ0aXBvQ29kQXV0IjoiRSIsImNvZEF1dCI6
NzA0MTcwNTQzNjc0NzZ9

duilioisola 25-09-2023 19:46:48

Me sucedió lo mismo con el ejemplo que enviaste...
El problema era que había un espacio de más...

En el ejemplo que escribí hay espacios de más:
Código Delphi [-]
   strJSON := '{"ver":1,"fecha":"2020-10-13","cuit":30000000007,"ptoVta":10,"tipoCmp":1,"nroCmp":94,"importe":12100,"moneda":"DOL","ctz":65  ,"  TipoDocRec":80,"nroDocRec":20000000001,"tipoCodAut":"E","codAut":70417054367476}';
Mira :"ctz":65,"__tipoDocRec":80,"nroDocRec":

Si corriges esto la conversión a Base 64 es correcta.

waly2k1 09-01-2024 20:54:38

Buenas!!!
Uso el mismo componente para crear un .bmp con el QR, lo que me está dificultando es la impresión,
ya que no sale del tamaño que debería. Ahí usas otros componentes gráficos?


Recién noto que usas FastReport, Sorry!



Saludos y muchas gracias

waly2k1 09-01-2024 21:33:04

Impresion del QR?
 
Y cómo sería la impresión del .bmp? sin FastReport
probé con:


Código Delphi [-]
BitMap := TBitmap.Create;
BitMap.LoadFromFile( ExtractFilePath( Application.ExeName ) + '\QR.bmp' ); // el QR generado con TDelphiZXingQRCode


Canvas.StretchDraw();
Canvas.Draw();


Y nada, solo logro imprimir una imagen muy pequeña ilegible


Saludos y muchas gracias!

duilioisola 10-01-2024 08:28:18

Depende de cómo estés imprimiendo...

Yo utilizo FastReport, pero hay otros muchos componentes para impresión. ¿Cuál utilizas?

Supongo que podrías generar un PDF e insertar el gráfico.
Además se puede hacer una impresión directa a la impresora.
Ciertas impresoras de tickets tienen la funcionalidad de imprimir imágenes o códigos de barra directamente, como si fuera una impresora matricial a la que le envías un código especial y luego la imagen.

waly2k1 17-01-2024 04:18:04

Buenas!
No utilizo componentes sino con canvas nomás lo hice
Pasa que ya tenía el ticket con impresión manual (Printer), luego encontré
en otro hilo que decía que la imagen debe ser mucho más grande para que se imprima
en tamaño acorde. La hice de 1000 * 1000 e imprime en una pulgada +/-.
Perdón por no contestar antes, pero anduve como loco con eso y cuando funcionó
suspiré al fin.
Siempre uso FastReport, pero para Tickets nunca, me hubiera ahorrado mucho tiempo con
la impresión manual de logos/QR.
Saludos y muchas gracias por tu tiempo!


La franja horaria es GMT +2. Ahora son las 17:03:47.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi