Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   TICKET BAI (TicketBAI); Nuevo sistema de la Agencia Tributaria del Pais Vasco (https://www.clubdelphi.com/foros/showthread.php?t=94264)

elcharlie 05-11-2020 09:26:20

Cita:

Empezado por juramisa (Mensaje 538967)
¿Serías tan amable de mandarme ese procedimiento en la versión Rio?. Viéndolo, parece que es un problema al cargar la lista de los certificados presentes en el ordenador.
¿Tal vez hay una orden previa para la carga de los certificados y que yo no la esté realizando?
Gracias.

Te lo envío, pero sigo creyendo que éste no es el problema, el problema lo tienes en otra parte.

Código Delphi [-]
procedure TWinHTTPClient.DoGetClientCertificates(const ARequest: THTTPRequest;
  const ACertificateList: TList);
var
  LRequest: TWinHTTPRequest;
  LStore: HCERTSTORE;
  LIssuerList: PSecPkgContext_IssuerListInfoEx;
  LClientCert: PCCERT_CONTEXT;
  LSearchCriteria: CERT_CHAIN_FIND_BY_ISSUER_PARA;
  LIssuerListSize: DWORD;
  LPrevChainContext, LClientCertChain: PCCERT_CHAIN_CONTEXT;

  procedure AddToCertificateList(const AClientCert: PCCERT_CONTEXT);
  var
    LCertificate: TCertificate;
  begin
    CertDuplicateCertificateContext(AClientCert); // Need to be released (CertFreeCertificateContext)
    CryptCertToTCertificate(AClientCert, LCertificate);
    FCertificateList.Add(LCertificate);
    FWinCertList.Add(AClientCert);
  end;
begin
  inherited;

  if FWinCertList.Count = 0 then
  begin
    LRequest := TWinHTTPRequest(ARequest);

    LIssuerList := nil;
    LIssuerListSize := SizeOf(LIssuerList);
    LStore := TWinHttpLib.GetCertStore;

    if WinHttpQueryOption(LRequest.FWRequest, WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST, LIssuerList, LIssuerListSize) and (LIssuerList <> nil) then
    begin
      FillChar(LSearchCriteria, SizeOf(LSearchCriteria), 0);
      LSearchCriteria.cbSize := SizeOf(LSearchCriteria);
      LSearchCriteria.cIssuer := LIssuerList.cIssuers;
      LSearchCriteria.rgIssuer := LIssuerList.aIssuers;

      if LStore <> nil then
      begin
        LPrevChainContext := nil;
        while True do
        begin
          LClientCertChain := CertFindChainInStore(LStore, X509_ASN_ENCODING,
            CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG or CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG,
            CERT_CHAIN_FIND_BY_ISSUER, @LSearchCriteria, LPrevChainContext);

          if LClientCertChain <> nil then
          begin
            LPrevChainContext := LClientCertChain;
            LClientCert := LClientCertChain.rgpChain^.rgpElement^.pCertContext;
            AddToCertificateList(LClientCert);
          end else
            Break;
        end;
      end;
      GlobalFree(HGLOBAL(LIssuerList));
    end else
    begin
      if LStore <> nil then
      begin
        LClientCert := nil;
        while True do
        begin
          LClientCert := CertFindCertificateInStore(LStore,
            X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
            0, CERT_FIND_ANY, nil, LClientCert);
          if LClientCert <> nil then
            AddToCertificateList(LClientCert)
          else
            Break;
        end;
      end;
    end;
  end;
  ACertificateList.Clear;
  ACertificateList.AddRange(FCertificateList);
end;

juramisa 05-11-2020 09:31:29

Hola

Por el error si pasa

Código Delphi [-]
procedure TfrmEnve140CTB.NetHTTPClient1RequestError(const Sender: TObject;
  const AError: string);
begin
  ShowMessage(Aerror);
end;

por el evento
Código Delphi [-]
procedure TfrmEnve140CTB.NetHTTPClient1NeedClientCertificate(const Sender: TObject; const ARequest: TURLRequest; const ACertificateList: TCertificateList; var AnIndex: Integer);
var
  i: Integer;
begin
  AnIndex := 0;
no llega, ambos tienen una parada. Da el error comentado anteriormente y termina.
gracias

keys 05-11-2020 09:39:57

¿ y que Contiene Aerror?.

juramisa 05-11-2020 09:45:08

Hola

He visto esta nota en 'http://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_an_HTTP_Client'

Nota: Si el método HTTP de la primera solicitud a un servidor que requiere un certificado del lado del cliente no es HEAD o GET (por ejemplo, POST), el código de estado de la respuesta del servidor es 413. Siempre envíe una solicitud HEAD o GET primero. Usar una solicitud HEAD suele ser una mejor opción, ya que se transfieren menos datos.

y lo he probado a realizar lo siguiente
Código Delphi [-]
      NetHTTPRequest1.MethodString := 'HEAD';
      NetHTTPClient1.Head(la_url_pruebas, nil).ContentStream;
pero da lo mismo.

juramisa 05-11-2020 09:46:32

keys

Aerror = Access violation at address 00B19045 in module 'BATUZ.exe'. Read of address 00000004

keys 05-11-2020 10:56:12

Yo creo que el problema es de delphi seattle.

Si el error da en ese punto es que tu programa no a podido negociar la conexión con el servidor de hacienda, es decir el protocolo que estan utilizando es diferente. Nosotros cuando empezamos las pruebas nos ocurria algo parecido al hacer los envíos y tampoco llegaba al evento OnNeedClientCertificate, pero si nos mostraba el error, que era distinto. Trabajabamos con el delphi Tokio 10.2.0, es decir la primera que sacaron.

Mirando por internet encontramos lo siguiente https://edn.embarcadero.com/print/44770 es decir que la versión que teniamos no estaba preparada para TLS 1.2 que es lo que recomienda hacienda. Tambien puedes seguir el siguiente enlace https://blog.marcocantu.com/blog/201...ents-1022.html que tambien habla de ello. Actualizamos a delphi 10.2.2 y funciono todo correcto.

Yo lo que te recomiendo es que mires si lo puedes probar en un delphi mas actualizado.

Por otra parte hacienda ha publicado esto.

"Se recomienda hacer uso de protocolos de comunicación seguros con el servicio de entradas, con versiones TLS 1.2 o superiores."

Aunque ahora mismo tienen habilitado el 1.0 y el 1.1, pero me comentaron que puede que luego solo dejen el 1.2 o superior. Para indicarle al componente TNEtHttpClient que trabaje con la verisión del protocolo que nosotros queremos es
Código Delphi [-]
Componente.SecureProtocols := [THTTPSecureProtocol.TLS12];

Esta propiedad solo esta disponible a partir de la version 10.2.2(Tokio) de delphi.

Un Saludo.

juramisa 05-11-2020 11:48:15

Buenos días

keys, está claro que es la versión. Por lo que deduzco, y dime si me equivoco, que si lo intento con otros componentes de la misma versión de Delphi, me ocurriría lo mismo.
Voy a echar un vistazo a TsbxHTTPClient, de 'SecureBlackbox 2020'. De todas formas si alguien trabaja con otros componentes, y que le funcione la comunicación, por favor, hacérmelo saber, para ir por ese camino.

Muchas gracias de nuevo.

keys 05-11-2020 11:56:03

Si no puedes cambiar la versión de delphi prueba con otros componentes de terceros. No se si con alguno de los otros de delphi funcionará. Los de secureblackbox yo los utilizo para otras cosas, no para enviar y funcionan bien. Si tienes la version 2020 me imagino que estaran adaptados a todos los protocolos.

Un Saludo y suerte.

juramisa 08-11-2020 13:15:01

Entorno pruebas TicketBai
 
Buenos días

Perdonar mi torpeza. Estoy intentando realizar pruebas de envío LROE, en esta ocasión con Delphi 10.4 Sydney, (Trial) con el siguiente código:

Código Delphi [-]
    // Fichero a enviar 'D:\...\Modelos 140-240\temp\CTB-0001-2020-11-08 12-41-50-ALENVIO.xml.gz'
    if FileExists(DMBatu.CDSEnvc.FieldByName('EN050').AsString + '.gz') then 
    begin
      NetHTTPClient1.SecureProtocols := [THTTPSecureProtocol.TLS12];
      // Cargo la cabecera de la petición

      NetHTTPRequest1.CustomHeaders['Accept-Encoding'] := el_accept_Encoding;   // 'gzip'
      NetHTTPRequest1.CustomHeaders['Content-Encoding'] := el_Content_Encoding; // 'gzip'
      NetHTTPRequest1.CustomHeaders['Content-Length'] := IntToStr(tamanoFichero(DMBatu.CDSEnvc.FieldByName('EN050').AsString + '.gz'));
      NetHTTPRequest1.CustomHeaders['Content-Type'] := el_Content_Type;   // 'application/octet-stream'
      NetHTTPRequest1.CustomHeaders['eus-bizkaia-n3-version'] := el_eus_bizkaia_n3_version;  // '1.0'
      NetHTTPRequest1.CustomHeaders['eus-bizkaia-n3-content-type'] := el_eus_bizkaia_n3_content_type;  // 'application/xml'
      el_eus_bizkaia_n3_data := f_cabecera_LROE(el_concepto, el_subcapitulo, DMBatu.CDSPres.FieldByName('PR020').AsString, DMBatu.CDSPres.FieldByName('PR040').AsString,
                                                                         DMBatu.CDSPres.FieldByName('PR090').AsString, DMBatu.CDSPres.FieldByName('PR100').AsString, DMBatu.CDSPres.FieldByName('PR080').AsString, 
                                                                         IntToStr(ejercicio_presentacion.Value));
      //   '{"con": "LROE", "apa": "1.1", "inte": {"nif": "14XXXXXXA","nrs": "MXXXXXX","ap1": "SXXXXXX","ap2": "JXXXXXXXX"},"drs": {"mode": "140","ejer": "2020"}}'
      NetHTTPRequest1.CustomHeaders['eus-bizkaia-n3-data'] := el_eus_bizkaia_n3_data;

     S := TStringList.Create;
     M := TMemoryStream.Create;

      NetHTTPRequest1.MethodString := 'POST';
      case rg_Entorno.ItemIndex of
        0: begin
            NetHTTPRequest1.Post(la_url_pruebas, // https://pruesarrerak.bizkaia.eus/N3B4000M/aurkezpena
                                 DMBatu.CDSEnvc.FieldByName('EN050').AsString + '.gz',  // Fichero a enviar 'D:\...\Modelos 140-240\temp\CTB-0001-2020-11-08 12-41-50-ALENVIO.xml.gz'
                                 M);
            M.Position := 0;
            S.LoadFromStream(M);
            Memo1.Lines.AddStrings(S);
           end;
        .............
      end;

Pues bien, el certificado me lo pide, como es de ciudadano, me solicita la clave, se la doy y tras un breve tiempo, me da el siguiente error:
'Error sending data: (12030) La conexión con el servidor finalizó anormalmente'


Si alguien que utilice este método, puede corregirme, qué estoy haciendo mal, agradecido.

Muchas gracias a todos

keys 09-11-2020 09:15:29

Yo creo que el problema esta en como envías el fichero. Te pongo como lo hago yo

Código Delphi [-]
var
 json : string;
 RequestBody: TFileStream;
 AResponse: IHTTPResponse;
begin
 RequestBody := TFileStream.Create(FicheroComprimido, fmOpenRead);

 EnvioBizkaia.SecureProtocols := [THTTPSecureProtocol.TLS12];
 EnvioBizkaia.CustomHeaders['Accept-Encoding'] := 'gzip';
 EnvioBizkaia.CustomHeaders['Content-Encoding'] := 'gzip';
 EnvioBizkaia.CustomHeaders['Content-Type'] := 'application/octet-stream';

 EnvioBizkaia.CustomHeaders['eus-bizkaia-n3-version'] := '1.0';
 EnvioBizkaia.CustomHeaders['eus-bizkaia-n3-content-type'] := 'application/xml';

//Formamos los parametros json de entrada
 json := '{"con": "LROE","apa": "1.1","inte": {"nif": "'+ Factura.DatosAsesoria.CIF +'",';

 if PersonaFisica  then
    json := json + '"nrs": "' + NombreP + '","ap1": "' + Apellido1P + '","ap2": "'+ Apellido2P +'"},'
 else
    json := json + '"nrs": "' + Nombre + '","ap1": "","ap2": ""},';

 json := json + '"drs":{"mode": "' + Modelo + '","ejer": "2020"}}';

 EnvioBizkaia.CustomHeaders['eus-bizkaia-n3-data'] := json;
 AResponse := EnvioBizkaia.Post('https://pruesarrerak.bizkaia.eus/N3B4000M/aurkezpena',RequestBody);
end;

Espero que te sirva. Un Saludo

elcharlie 09-11-2020 10:30:11

Cita:

Empezado por juramisa (Mensaje 539008)
Buenos días

Pues bien, el certificado me lo pide, como es de ciudadano, me solicita la clave, se la doy y tras un breve tiempo, me da el siguiente error:
'Error sending data: (12030) La conexión con el servidor finalizó anormalmente'


Si alguien que utilice este método, puede corregirme, qué estoy haciendo mal, agradecido.

Muchas gracias a todos

A mi me hace lo mismo, si seguidamente, lo vuelves a enviar, ya no te pide que valides la clave y lo envía. Debe de ser algo de la configuración del timeout de su servidor de pruebas, digo yo..

juramisa 09-11-2020 11:06:23

Entorno pruebas TicketBai
 
Tienes razón, la segunda vez lo admite. Muchas gracias, ya no sabía que cambiar. La única diferencia que tenía con keys era:

Código Delphi [-]
     NetHTTPClient1.CustomHeaders['Content-Length'] := IntToStr(tamanoFichero(FicheroComprimido));

Que han introducido en una última versión.

Gracias

juramisa 09-11-2020 18:43:50

Cita:

Empezado por elcharlie (Mensaje 539019)
A mi me hace lo mismo, si seguidamente, lo vuelves a enviar, ya no te pide que valides la clave y lo envía. Debe de ser algo de la configuración del timeout de su servidor de pruebas, digo yo..

Si lo reintento como dices, no me funciona, me había equivocado, al controlar el error me da un

Código Delphi [-]
Error
Server error 408: Request Timeout

Si encuentras la solución ya me dirás. Yo seguiré también haciendo pruebas.

keys 10-11-2020 08:19:00

Si os sirve de algo a mi me funciona correctamente. Eso si los certificados no necesitan clave son de la FNMT.

Un Saludo.

elcharlie 10-11-2020 10:52:18

Cita:

Empezado por juramisa (Mensaje 539025)
Si lo reintento como dices, no me funciona, me había equivocado, al controlar el error me da un

Código Delphi [-]
Error
Server error 408: Request Timeout

Si encuentras la solución ya me dirás. Yo seguiré también haciendo pruebas.

A mi me funciona bien con el certificado de sello de empresa, eso si, la primera vez, me pide la clave y como tienes que esperar a que te salga la ventana del pin, lo pones, bla bla blau, me da el error
Código:

[Error sending data: (12030) La conexión con el servidor finalizó anormalmente
Pero de seguido lo vuelvo a intentar y sin problemas, ya te digo, que supongo, que será problemas de ajustes de tiemouts de su servidor de pruebas, pero tampoco puedo estar seguro.
Eso si con un certificado que no pida pin, a la primera.

juramisa 10-11-2020 10:58:05

Hola

Con el certificado de FNMT, efectivamente va mejor, aún así, desde hace un momento me sale

HTTP/1.1 500 Internal Server Error:

Esto es problema de que algo estoy mandando yo mal, o es problema sólo del servidor. Parece tan ambiguo el error 500.

elcharlie 10-11-2020 11:06:24

Cita:

Empezado por juramisa (Mensaje 539030)
Hola

Con el certificado de FNMT, efectivamente va mejor, aún así, desde hace un momento me sale

HTTP/1.1 500 Internal Server Error:

Esto es problema de que algo estoy mandando yo mal, o es problema sólo del servidor. Parece tan ambiguo el error 500.

Te pongo como lo envío yo, por si te sirve:
Código Delphi [-]
    HttpClient.SecureProtocols := [THTTPSecureProtocol.TLS12];

    HttpClient.ContentType := 'application/octet-stream';
    HttpClient.AcceptCharSet := 'utf-8';

    HttpClient.CustomHeaders['Accept-Encoding'] := 'gzip';
    HttpClient.CustomHeaders['Content-Encoding'] := 'gzip';

    HttpClient.CustomHeaders['eus-bizkaia-n3-version'] := '1.0';
    HttpClient.CustomHeaders['eus-bizkaia-n3-content-type'] := 'application/xml';
    HttpClient.CustomHeaders['eus-bizkaia-n3-data'] := JsonData;

   Response := HttpRequest.Post('https://pruesarrerak.bizkaia.eus/N3B4000M/aurkezpena', FicheroGZip);

elcharlie 10-11-2020 11:16:19

Tambien podrias intentar analizar que te responden desde el servidor haciendo esto:

Código Delphi [-]
var
ResponseStreamString: TStringStream;

Rsponse := HttpRequest.Post('https://pruesarrerak.bizkaia.eus/N3B4000M/aurkezpena', FicheroGZip, ResponseStreamString,nil);

if Response.StatusCode  <> 200 then
      ShowMessage(ResponseStreamString.DataString);

Espero ayudarte.

juramisa 10-11-2020 12:03:44

Hola

Por favor alguien puede hacer una prueba de envío ahora. Me da la sensación de que es el servicio de pruebas el que no funciona. La programación es idéntica a la vuestra, es más he optado por copiar y pregar y comentar lo mío y sigue dando error 500.

Gracias.

elcharlie 10-11-2020 12:09:06

Cita:

Empezado por juramisa (Mensaje 539033)
Hola

Por favor alguien puede hacer una prueba de envío ahora. Me da la sensación de que es el servicio de pruebas el que no funciona. La programación es idéntica a la vuestra, es más he optado por copiar y pregar y comentar lo mío y sigue dando error 500.

Gracias.

Probado a las 12:08 y sin problemas


La franja horaria es GMT +2. Ahora son las 04:25:44.

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