Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Proyecto SIF/Veri*Factu/Ley Antifraude > Envío de registros y sus respuestas
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #201  
Antiguo 05-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
Cita:
Empezado por Quim Herrera Ver Mensaje
No sé si ya lo habéis detectado, creo que hay un error en uVerifactuFuncs.pas en TEventosWebNode.WebNodeBeforePost al validar un NIF con P12 o PFX en la asignación del nombre del archivo y password:

Código Delphi [-]
 if sesion=-1 then // viene de un validador de nif
  begin
      pass:=nifValidator;
      cert:=nifValidatorPass;
  end
  else     // viene de un objeto verifactu

deberia ser:

Código Delphi [-]
  if sesion=-1 then // viene de un validador de nif
  begin
      cert:=nifValidator;
      pass:=nifValidatorPass;
  end
  else     // viene de un objeto verifactu
Saludos
gracias, añado la correccion.
Responder Con Cita
  #202  
Antiguo 05-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
Cita:
Empezado por DarkDudae Ver Mensaje
No, no se interrumpe.

He probado a hacer un envío con 4 facturas. La segunda de ellas con el NIF incorrecto. Las otras 3 se envían sin problemas.
aparentemente la huella, seria la misma para la siguiente ¿no? entiendo que no habria problema de encadenamiento, al enviar la que falta, subsanado el error.


los datos de huella son ciertos, ocurra el fallo que ocurra:

Código:
  CadenaTemporalHuella:= 'IDEmisorFactura='+         alta.IDFactura.IDEmisorFactura+'&'+
                           'NumSerieFactura='+         alta.IDFactura.NumSerieFactura+'&'+
                           'FechaExpedicionFactura='+  alta.IDFactura.FechaExpedicionFactura+'&'+
                           'TipoFactura='+             TipoFacturaVerifactuToString( alta.TipoFactura )+'&'+
                           'CuotaTotal='+              alta.CuotaTotal+'&'+
                           'ImporteTotal='+            alta.ImporteTotal+'&'+
                           'Huella='+                  huellaAnterior+'&'+
                           'FechaHoraHusoGenRegistro='+alta.FechaHoraHusoGenRegistro.NativeToXS;
Saludos !


La carga del certificado PFX o P12 no tengo ni idea, hay algun usuario que le funcionó (podeis revisar el hilo). Lamentablemente mas alla de eso no tengo tiempo para comprobar, pero mirare un poco por google. El codigo es copy-paste de uno que supuestamente funcionaba.

( ¿has aplicado la correccion de Quim Herrera ? )

Saludos !
Responder Con Cita
  #203  
Antiguo 05-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
El usuario garada tiene un codigo ligeramente distinto en:

https://www.clubdelphi.com/foros/showthread.php?t=95356

dale una mirada al hilo.

Este es el codigo, señalo en rojo, lo que puede ser distinto. la carga del pfx la deja libre, sin determinar.

Código:
procedure HTTPRIOHTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);

  procedure CheckError(Puntero: Pointer);
  begin
    if not Assigned(Puntero) then
      RaiseLastOSError;
  end;

const
  INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;
  Pass = 'LaContraseña';
var
  pStore: HCERTSTORE;
  pCert: PCERT_CONTEXT;
  DataBlob: CRYPT_DATA_BLOB;
  PFX: AnsiString;
begin
  pStore := nil;
  pCert := nil;

  PFX := FuncionQueLeaElFicheroPFX;

  try
    DataBlob.cbData := Length(PFX);
    DataBlob.pbData := @PFX[1];

    // Almacen temporal con el contenido del PFX
    pStore := PFXImportCertStore(DataBlob, PWideChar(Pass), {PKCS12_NO_PERSIST_KEY + }PKCS12_INCLUDE_EXTENDED_PROPERTIES);
    CheckError(pStore);

    // Buscar un certificado con clave privada
    // Solo debería haber uno
    pCert := CertFindCertificateInStore(pStore,
                                        X509_ASN_ENCODING,
                                        0,
                                        CERT_FIND_HAS_PRIVATE_KEY, //CERT_FIND_ANY,
                                        nil,
                                        nil);
    CheckError(pCert);

    // Pasarlo al servicio
    InternetSetOption(Data, INTERNET_OPTION_CLIENT_CERT_CONTEXT, pCert, SizeOf(CERT_CONTEXT));
  finally
    if Assigned(pCert) then
      CertFreeCertificateContext(pCert);

    if Assigned(pStore) then
      CertCloseStore(pStore, 0);
  end;
end;
Responder Con Cita
  #204  
Antiguo 05-03-2025
elguille elguille is offline
Miembro
 
Registrado: ene 2005
Posts: 119
Poder: 21
elguille Va por buen camino
Cita:
Empezado por ramherfer Ver Mensaje
Hola termino de hacer una prueba validando NIF del cliente, por hacer una prueba rápida y sencilla con PFX y me pide que seleccione un certificado del almacen. Esto con el nombre de certificado cierto que no ocurre y funciona bien. Habiendo realizado una prueba con validación, creo que tampoco funcionará con los envíos. No lo he probado en los envíos por si se me lía un trifostio. Luego si acaso probaré con una factura y amplio la información lo tengo fácil para cambiar el uso de certificados.

Probado, pide el certificado tanto al comprobar el nif como al facturar del almacen de certificados.
Creo que pide el certificado por el error que señalo, al no poder cargarse este, te enseña los del almacen.

Saludos
Responder Con Cita
  #205  
Antiguo 05-03-2025
elguille elguille is offline
Miembro
 
Registrado: ene 2005
Posts: 119
Poder: 21
elguille Va por buen camino
Cita:
Empezado por seccion_31 Ver Mensaje
El usuario garada tiene un codigo ligeramente distinto en:

https://www.clubdelphi.com/foros/showthread.php?t=95356

dale una mirada al hilo.

Este es el codigo, señalo en rojo, lo que puede ser distinto. la carga del pfx la deja libre, sin determinar.

Código:
procedure HTTPRIOHTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);

  procedure CheckError(Puntero: Pointer);
  begin
    if not Assigned(Puntero) then
      RaiseLastOSError;
  end;

const
  INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;
  Pass = 'LaContraseña';
var
  pStore: HCERTSTORE;
  pCert: PCERT_CONTEXT;
  DataBlob: CRYPT_DATA_BLOB;
  PFX: AnsiString;
begin
  pStore := nil;
  pCert := nil;

  PFX := FuncionQueLeaElFicheroPFX;

  try
    DataBlob.cbData := Length(PFX);
    DataBlob.pbData := @PFX[1];

    // Almacen temporal con el contenido del PFX
    pStore := PFXImportCertStore(DataBlob, PWideChar(Pass), {PKCS12_NO_PERSIST_KEY + }PKCS12_INCLUDE_EXTENDED_PROPERTIES);
    CheckError(pStore);

    // Buscar un certificado con clave privada
    // Solo debería haber uno
    pCert := CertFindCertificateInStore(pStore,
                                        X509_ASN_ENCODING,
                                        0,
                                        CERT_FIND_HAS_PRIVATE_KEY, //CERT_FIND_ANY,
                                        nil,
                                        nil);
    CheckError(pCert);

    // Pasarlo al servicio
    InternetSetOption(Data, INTERNET_OPTION_CLIENT_CERT_CONTEXT, pCert, SizeOf(CERT_CONTEXT));
  finally
    if Assigned(pCert) then
      CertFreeCertificateContext(pCert);

    if Assigned(pStore) then
      CertCloseStore(pStore, 0);
  end;
end;
Ese codigo en delphi 10.3 me da error aqui
Código Delphi [-]
    pStore := PFXImportCertStore(DataBlob, PWideChar(widestring(pass)), PKCS12_INCLUDE_EXTENDED_PROPERTIES);
debido a que cambia
Código Delphi [-]
DataBlob.pbData := @PFX[1];
si lo dejo en
Código Delphi [-]
DataBlob.pbData := @PFX[0];
va bien pero en la linea internetsetoption recibo el mismo error que al principio, "codigo error 6"
Responder Con Cita
  #206  
Antiguo 05-03-2025
Avatar de DarkDudae
DarkDudae DarkDudae is offline
Miembro
 
Registrado: abr 2006
Posts: 126
Poder: 20
DarkDudae Va por buen camino
Cita:
Empezado por seccion_31 Ver Mensaje
aparentemente la huella, seria la misma para la siguiente ¿no? entiendo que no habria problema de encadenamiento, al enviar la que falta, subsanado el error.
Cada registro de facturación tiene que tener su huella y su encadenamiento, independientemente de que la AEAT lo haya rechazado por, por ejemplo, un NIF incorrecto.
__________________
El recuerdo es la prisión en la que el alma sueña pasado, cuando no vive el presente, ni quiere un futuro.
Responder Con Cita
  #207  
Antiguo 06-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
Cita:
Empezado por elguille Ver Mensaje
Ese codigo en delphi 10.3 me da error aqui
Código Delphi [-]
    pStore := PFXImportCertStore(DataBlob, PWideChar(widestring(pass)), PKCS12_INCLUDE_EXTENDED_PROPERTIES);
debido a que cambia
Código Delphi [-]
DataBlob.pbData := @PFX[1];
si lo dejo en
Código Delphi [-]
DataBlob.pbData := @PFX[0];
va bien pero en la linea internetsetoption recibo el mismo error que al principio, "codigo error 6"
He revisado el codigo y hay un monton de errores ahi dentro

el codigo que carga el certificado esta correcto

pero no se transmite el password a la DLL
y en la DLL el array de sesiones se comprueba al llegar a la zona de carga del certificado de forma erronea.

creo que corrigiendo esto:

en el componente:

Código:
function TVerifactu.validNIF(nif, nombre:string; var resultado, nombreRes:string):boolean;
var
    valida_nif: TValidadorNIF;
    j:integer;
begin
      checkAutoRun;

      result:=false;

      valida_nif.nombreCertificado:=Certificado;
      valida_nif.passwordCerficado:=passwordCertificado;
      valida_nif.nifvalidar       :=nif;
      valida_nif.nombre           :=nombre;
      valida_nif.resultado        :='';
      valida_Nif.error            :=true;

      validarNIF( valida_nif );

      if valida_Nif.error then
      begin
              resultado:='';
              nombreRes:='';
              result:=false;
              exit;
      end;

      resultado:=valida_Nif.resultado;
      nombreRes:=valida_Nif.resultadoN;
      result:=true;
end;

y esto en la DLL:

Código:
procedure TEventosWebNode.WebNodeBeforePost(const HTTPReqResp: THTTPReqResp;
  Data: Pointer);
var
  pStore: HCERTSTORE;
  pCert: PCERT_CONTEXT;
  DataBlob: CRYPT_BIT_BLOB;
  PFX: TBytes;
  pass,cert:string;
begin
  if sesion=-1 then // viene de un validador de nif
  begin
      pass:=nifValidatorPass;
      cert:=nifValidator;
  end
  else     // viene de un objeto verifactu
  begin
      pass:=sesiones[sesion].inicio.passwordCertificado;
      cert:=sesiones[sesion].inicio.nombreCertificado;
  end;


  if (pos('.PFX',uppercase(cert))=0) and
     (pos('.P12',uppercase(cert))=0) then exit;


  cargaCertificado(data, cert, pass);
end;

ya deberia funcionar, a mi me funciona.

A principios de la semana que viene publicare una nueva version corregida.

Pero ya esta solucionado.

slds
Responder Con Cita
  #208  
Antiguo 06-03-2025
Avatar de ramherfer
ramherfer ramherfer is offline
Miembro
 
Registrado: may 2013
Ubicación: Valencia
Posts: 128
Poder: 12
ramherfer Va por buen camino
Buenas tardes.
Si se le factura a un cliente con recargo de equivalencia no se si está asignando la clave de régimen 01 (Operación de Régimen General).
Creo que en este caso debería de asignar la clave de regimen 18 (Recargo de equivalencia).

Por favor corregirme si me equivoco.
__________________
Se humilde para admitir tus errores, inteligente para aprender de ellos y maduro para corregirlos.
Responder Con Cita
  #209  
Antiguo 07-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
Cita:
Empezado por ramherfer Ver Mensaje
Buenas tardes.
Si se le factura a un cliente con recargo de equivalencia no se si está asignando la clave de régimen 01 (Operación de Régimen General).
Creo que en este caso debería de asignar la clave de regimen 18 (Recargo de equivalencia).

Por favor corregirme si me equivoco.
Que yo sepa debe quedarse como 01.

En uveriFactuFuncs.

La variable Condatos en la consulta se quedaba siempre a false, al menos en la version que yo tengo.
Si os ocurre esto, cambiar esta funcion asi:



Código:
function consultar(sesion:integer; var resultado:TConsultaResultado):boolean;
var
  consulta          : ConsultaFactuSistemaFacturacion;                  // Objeto a enviar
  res               : RespuestaConsultaFactuSistemaFacturacionType;    // Respuesta tras el envio

  HTTPRIO1          : THTTPRIO;

  j                 : integer;

  direccion_envio,  estado  : string;

  eventos       : TEventosHttpPrio;
  eventosWebNode: TEventosWebNode;
begin
      consulta:=ConsultaFactuSistemaFacturacion.Create;

      consulta.Cabecera:=CabeceraConsultaSf.Create;
      consulta.Cabecera.ObligadoEmision             :=ObligadoEmisionConsultaType.Create;
      consulta.Cabecera.ObligadoEmision.NombreRazon :=sesiones[sesion].inicio.emisor.NombreRazonEmisor;
      consulta.Cabecera.ObligadoEmision.NIF         :=sesiones[sesion].inicio.emisor.nifEmisor;

      consulta.FiltroConsulta:=LRFiltroRegFacturacionType.Create;
      consulta.FiltroConsulta.PeriodoImputacion           :=PeriodoImputacionType.Create;
      consulta.FiltroConsulta.PeriodoImputacion.Ejercicio :=resultado.Cabecera.ejercicio;
      consulta.FiltroConsulta.PeriodoImputacion.Periodo   :=veriFactuPeriodo( resultado.Cabecera.periodo );

      if resultado.Cabecera.NumSerieFactura='' then
      begin
          consulta.FiltroConsulta.FechaExpedicionFactura:=FechaExpedicionConsultaType.Create;
          if resultado.Cabecera.dfecha=resultado.Cabecera.hfecha then
          begin
            consulta.FiltroConsulta.FechaExpedicionFactura.FechaExpedicionFactura:=verifactuFecha(datetostr(resultado.Cabecera.dfecha));
          end else
          begin
            consulta.FiltroConsulta.FechaExpedicionFactura.RangoFechaExpedicion:=RangoFechaExpedicionType.Create;
            consulta.FiltroConsulta.FechaExpedicionFactura.RangoFechaExpedicion.Desde:=verifactuFecha(datetoStr(resultado.Cabecera.dfecha));
            consulta.FiltroConsulta.FechaExpedicionFactura.RangoFechaExpedicion.Hasta:=verifactuFecha(datetoStr(resultado.Cabecera.hfecha));
          end;
      end
      else
      begin
          consulta.FiltroConsulta.NumSerieFactura:=resultado.Cabecera.NumSerieFactura;
      end;

      If resultado.Cabecera.filtroSIF then
      Begin
            //Vamos a establecer un filtro por sistema informático (opcional)
            consulta.FiltroConsulta.SistemaInformatico:=SistemaInformaticoType.Create;
            consulta.FiltroConsulta.SistemaInformatico.NombreRazon                 := sesiones[sesion].inicio.sistemaInformatico.razonSocial;
            consulta.FiltroConsulta.SistemaInformatico.NIF                         := sesiones[sesion].inicio.sistemaInformatico.nif;
            consulta.FiltroConsulta.SistemaInformatico.NombreSistemaInformatico    := sesiones[sesion].inicio.sistemaInformatico.nombre;
            consulta.FiltroConsulta.SistemaInformatico.IdSistemaInformatico        := sesiones[sesion].inicio.sistemaInformatico.ID;
            consulta.FiltroConsulta.SistemaInformatico.Version                     := sesiones[sesion].inicio.sistemaInformatico.Version;
            consulta.FiltroConsulta.SistemaInformatico.NumeroInstalacion           := sesiones[sesion].inicio.sistemaInformatico.NumeroInstalacion;
            consulta.FiltroConsulta.SistemaInformatico.TipoUsoPosibleSoloVerifactu := SiNoType.S;

            if sesiones[sesion].inicio.sistemaInformatico.multiplesOT then
                consulta.FiltroConsulta.SistemaInformatico.TipoUsoPosibleMultiOT       := SiNoType.S
            else
                consulta.FiltroConsulta.SistemaInformatico.TipoUsoPosibleMultiOT       := SiNoType.N;
      End;

      eventos:=TEventosHttpPrio.Create;

      eventos.fileNameBefore  :=sesiones[sesion].inicio.saveXMLenvio;
      eventos.fileNameAfter   :=sesiones[sesion].inicio.saveXMLResultado;

      eventosWebNode:=TEventosWebNode.Create;
      eventosWebNode.sesion:=sesion;

      HTTPRIO1:=THTTPRIO.create(nil);
      HTTPRIO1.onBeforeExecute:=eventos.BeforeExecute;
      HTTPRIO1.onAfterExecute :=eventos.AfterExecute;

      // Cargar certificado del disco
      if ( pos('.PFX',uppercase(sesiones[sesion].inicio.nombreCertificado))<>0) or
         ( pos('.P12',uppercase(sesiones[sesion].inicio.nombreCertificado))<>0) then
          HTTPRIO1.HTTPWebNode.onBeforePost:=eventosWebNode.WebNodeBeforePost;

      // --> envío pre-produccion:  'https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP';
      try
          // Cargar certificado del almacen
          if ( pos('.PFX',uppercase(sesiones[sesion].inicio.nombreCertificado))=0) and
             ( pos('.P12',uppercase(sesiones[sesion].inicio.nombreCertificado))=0) then
            HTTPRIO1.HTTPWebNode.ClientCertificate.SerialNum := Buscar_Certificado_SERIAL( sesiones[sesion].inicio.nombreCertificado );  // coloca el certificado

          direccion_envio :=sesiones[sesion].inicio.direccion_envio;

          res:=   RespuestaConsultaFactuSistemaFacturacionType.Create;
          res:=   GetsfPortTypeVerifactu( false, direccion_envio , HTTPRIO1 ).ConsultaFactuSistemaFacturacion( consulta ); // Enviarlo !

          // limpiar resultado antes de procesarlo
          clear_consulta(resultado);

          // resultado del envio:
          resultado.ConDatos:=(res.ResultadoConsulta=ResultadoConsultaType.ConDatos);
          resultado.error   :=false;
          resultado.errorDes:='';



          procesarConsulta(res,resultado );
      except
      on E:Exception do
      begin
          resultado.ConDatos:=false;
          resultado.error:=true;
          resultado.errorDes:=Format('(%s)-%s',[E.ClassName, E.Message]);
          result:=false;
          exit;
      end;

            // Finalmente:
            // HTTPRIO1.free;  //<- no puede ser destruido con NIL como constructor
            //eventos.Free;
      end;
      result:=true;
end;
Responder Con Cita
  #210  
Antiguo 07-03-2025
Avatar de ramherfer
ramherfer ramherfer is offline
Miembro
 
Registrado: may 2013
Ubicación: Valencia
Posts: 128
Poder: 12
ramherfer Va por buen camino
Cita:
Empezado por seccion_31 Ver Mensaje
Que yo sepa debe quedarse como 01.

En uveriFactuFuncs.

La variable Condatos en la consulta se quedaba siempre a false, al menos en la version que yo tengo.
Si os ocurre esto, cambiar esta funcion asi:



Código:
function consultar(sesion:integer; var resultado:TConsultaResultado):boolean;
var
  consulta          : ConsultaFactuSistemaFacturacion;                  // Objeto a enviar
  res               : RespuestaConsultaFactuSistemaFacturacionType;    // Respuesta tras el envio

  HTTPRIO1          : THTTPRIO;

  j                 : integer;

  direccion_envio,  estado  : string;

  eventos       : TEventosHttpPrio;
  eventosWebNode: TEventosWebNode;
begin
      consulta:=ConsultaFactuSistemaFacturacion.Create;

      consulta.Cabecera:=CabeceraConsultaSf.Create;
      consulta.Cabecera.ObligadoEmision             :=ObligadoEmisionConsultaType.Create;
      consulta.Cabecera.ObligadoEmision.NombreRazon :=sesiones[sesion].inicio.emisor.NombreRazonEmisor;
      consulta.Cabecera.ObligadoEmision.NIF         :=sesiones[sesion].inicio.emisor.nifEmisor;

      consulta.FiltroConsulta:=LRFiltroRegFacturacionType.Create;
      consulta.FiltroConsulta.PeriodoImputacion           :=PeriodoImputacionType.Create;
      consulta.FiltroConsulta.PeriodoImputacion.Ejercicio :=resultado.Cabecera.ejercicio;
      consulta.FiltroConsulta.PeriodoImputacion.Periodo   :=veriFactuPeriodo( resultado.Cabecera.periodo );

      if resultado.Cabecera.NumSerieFactura='' then
      begin
          consulta.FiltroConsulta.FechaExpedicionFactura:=FechaExpedicionConsultaType.Create;
          if resultado.Cabecera.dfecha=resultado.Cabecera.hfecha then
          begin
            consulta.FiltroConsulta.FechaExpedicionFactura.FechaExpedicionFactura:=verifactuFecha(datetostr(resultado.Cabecera.dfecha));
          end else
          begin
            consulta.FiltroConsulta.FechaExpedicionFactura.RangoFechaExpedicion:=RangoFechaExpedicionType.Create;
            consulta.FiltroConsulta.FechaExpedicionFactura.RangoFechaExpedicion.Desde:=verifactuFecha(datetoStr(resultado.Cabecera.dfecha));
            consulta.FiltroConsulta.FechaExpedicionFactura.RangoFechaExpedicion.Hasta:=verifactuFecha(datetoStr(resultado.Cabecera.hfecha));
          end;
      end
      else
      begin
          consulta.FiltroConsulta.NumSerieFactura:=resultado.Cabecera.NumSerieFactura;
      end;

      If resultado.Cabecera.filtroSIF then
      Begin
            //Vamos a establecer un filtro por sistema informático (opcional)
            consulta.FiltroConsulta.SistemaInformatico:=SistemaInformaticoType.Create;
            consulta.FiltroConsulta.SistemaInformatico.NombreRazon                 := sesiones[sesion].inicio.sistemaInformatico.razonSocial;
            consulta.FiltroConsulta.SistemaInformatico.NIF                         := sesiones[sesion].inicio.sistemaInformatico.nif;
            consulta.FiltroConsulta.SistemaInformatico.NombreSistemaInformatico    := sesiones[sesion].inicio.sistemaInformatico.nombre;
            consulta.FiltroConsulta.SistemaInformatico.IdSistemaInformatico        := sesiones[sesion].inicio.sistemaInformatico.ID;
            consulta.FiltroConsulta.SistemaInformatico.Version                     := sesiones[sesion].inicio.sistemaInformatico.Version;
            consulta.FiltroConsulta.SistemaInformatico.NumeroInstalacion           := sesiones[sesion].inicio.sistemaInformatico.NumeroInstalacion;
            consulta.FiltroConsulta.SistemaInformatico.TipoUsoPosibleSoloVerifactu := SiNoType.S;

            if sesiones[sesion].inicio.sistemaInformatico.multiplesOT then
                consulta.FiltroConsulta.SistemaInformatico.TipoUsoPosibleMultiOT       := SiNoType.S
            else
                consulta.FiltroConsulta.SistemaInformatico.TipoUsoPosibleMultiOT       := SiNoType.N;
      End;

      eventos:=TEventosHttpPrio.Create;

      eventos.fileNameBefore  :=sesiones[sesion].inicio.saveXMLenvio;
      eventos.fileNameAfter   :=sesiones[sesion].inicio.saveXMLResultado;

      eventosWebNode:=TEventosWebNode.Create;
      eventosWebNode.sesion:=sesion;

      HTTPRIO1:=THTTPRIO.create(nil);
      HTTPRIO1.onBeforeExecute:=eventos.BeforeExecute;
      HTTPRIO1.onAfterExecute :=eventos.AfterExecute;

      // Cargar certificado del disco
      if ( pos('.PFX',uppercase(sesiones[sesion].inicio.nombreCertificado))<>0) or
         ( pos('.P12',uppercase(sesiones[sesion].inicio.nombreCertificado))<>0) then
          HTTPRIO1.HTTPWebNode.onBeforePost:=eventosWebNode.WebNodeBeforePost;

      // --> envío pre-produccion:  'https://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP';
      try
          // Cargar certificado del almacen
          if ( pos('.PFX',uppercase(sesiones[sesion].inicio.nombreCertificado))=0) and
             ( pos('.P12',uppercase(sesiones[sesion].inicio.nombreCertificado))=0) then
            HTTPRIO1.HTTPWebNode.ClientCertificate.SerialNum := Buscar_Certificado_SERIAL( sesiones[sesion].inicio.nombreCertificado );  // coloca el certificado

          direccion_envio :=sesiones[sesion].inicio.direccion_envio;

          res:=   RespuestaConsultaFactuSistemaFacturacionType.Create;
          res:=   GetsfPortTypeVerifactu( false, direccion_envio , HTTPRIO1 ).ConsultaFactuSistemaFacturacion( consulta ); // Enviarlo !

          // limpiar resultado antes de procesarlo
          clear_consulta(resultado);

          // resultado del envio:
          resultado.ConDatos:=(res.ResultadoConsulta=ResultadoConsultaType.ConDatos);
          resultado.error   :=false;
          resultado.errorDes:='';



          procesarConsulta(res,resultado );
      except
      on E:Exception do
      begin
          resultado.ConDatos:=false;
          resultado.error:=true;
          resultado.errorDes:=Format('(%s)-%s',[E.ClassName, E.Message]);
          result:=false;
          exit;
      end;

            // Finalmente:
            // HTTPRIO1.free;  //<- no puede ser destruido con NIL como constructor
            //eventos.Free;
      end;
      result:=true;
end;
No el código no lo he alterado. Digo que si emitimos una factura a un cliente con recargo de equivalencia, la clave de regimen pone 01 y debiera ser clave 18, ya que no es una operación del Régimen General (01), se trata de una operación del Régimen de Recargo de Equivalencia (18). O por lo menos eso es lo que tengo entendido, corregirme si me equivoco.
Lo mismo que ocurriría si es una operación REBU 03 (Régimen de bienes usados), no la puedo calificar con el Régimen General (01).
__________________
Se humilde para admitir tus errores, inteligente para aprender de ellos y maduro para corregirlos.
Responder Con Cita
  #211  
Antiguo 07-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
Cita:
Empezado por ramherfer Ver Mensaje
No el código no lo he alterado. Digo que si emitimos una factura a un cliente con recargo de equivalencia, la clave de regimen pone 01 y debiera ser clave 18, ya que no es una operación del Régimen General (01), se trata de una operación del Régimen de Recargo de Equivalencia (18). O por lo menos eso es lo que tengo entendido, corregirme si me equivoco.
Lo mismo que ocurriría si es una operación REBU 03 (Régimen de bienes usados), no la puedo calificar con el Régimen General (01).
creo que aqui se aclara todo, normalmente sigo creyendo que sera 01:

https://arnaldes.com/expedientes-de-...sos-indebidos/

A ver que conclusiones sacamos

Saludos !
Responder Con Cita
  #212  
Antiguo 11-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
en la proxima version que publicaremos este fin de semana incluira previsiblemente entre otras tres flags de factura

subsanacion
rechazoprevioExiste
rechazoPrevioNoExiste

Con la intencion de marcar a true la modalidad de rechazoprevio, cuando se envie un registro por un fallo, por ejemplo el de un DNI. (subsanacion, rechazoPrevioNoExiste)

Tenemos el siguiente caso:

Factura 1 aceptada huella: A
Factura 2 error por dni huella B
Factura 3 aceptada huella C

Factura 2 aceptada huella D

Cuando se vuelva a enviar la factura 2, tendra una nueva huella D y habria que marchar esos dos flags.

Ahora viene una pregunta:


El resto de huellas de la 2 en adelante y hasta el fin de la facturacion estara mal por dos causas:

https://www.agenciatributaria.es/sta..._registros.pdf

Cita:
a) Datos de campos a utilizar en el caso de registros de facturación de alta
(y la “ruta” de su localización dentro del registro):
1. IDEmisorFactura (RegistroAlta/IDFactura/IDEmisorFactura)
2. NumSerieFactura (RegistroAlta/IDFactura/NumSerieFactura)
3. FechaExpedicionFactura
(RegistroAlta/IDFactura/FechaExpedicionFactura)
4. TipoFactura (RegistroAlta/TipoFactura)
5. CuotaTotal (RegistroAlta/CuotaTotal)
6. ImporteTotal (RegistroAlta/ImporteTotal)
7. Huella (RegistroAlta/Encadenamiento/RegistroAnterior/Huella)
8. FechaHoraHusoGenRegistro
(RegistroAlta/FechaHoraHusoGenRegistro)
Porque la huella de la factura anterior forma parte del calculo de huella de la factura actual, y ademas porque se envia como dato adicional en el apartado factura Anterior.

¿esto es asi?

Saludos !

Última edición por seccion_31 fecha: 11-03-2025 a las 08:42:37.
Responder Con Cita
  #213  
Antiguo 11-03-2025
Avatar de bmfranky
bmfranky bmfranky is offline
Miembro
 
Registrado: may 2024
Ubicación: Gandia, Valencia
Posts: 599
Poder: 1
bmfranky Va por buen camino
Cita:
Empezado por seccion_31 Ver Mensaje
en la proxima version que publicaremos este fin de semana incluira previsiblemente entre otras tres flags de factura

subsanacion
rechazoprevioExiste
rechazoPrevioNoExiste

Con la intencion de marcar a true la modalidad de rechazoprevio, cuando se envie un registro por un fallo, por ejemplo el de un DNI. (subsanacion, rechazoPrevioNoExiste)

Tenemos el siguiente caso:

Factura 1 aceptada huella: A
Factura 2 error por dni huella B
Factura 3 aceptada huella C

Factura 2 aceptada huella D

Cuando se vuelva a enviar la factura 2, tendra una nueva huella D y habria que marchar esos dos flags.

Ahora viene una pregunta:


El resto de huellas de la 2 en adelante y hasta el fin de la facturacion estara mal por dos causas:

https://www.agenciatributaria.es/sta..._registros.pdf



Porque la huella de la factura anterior forma parte del calculo de huella de la factura actual, y ademas porque se envia como dato adicional en el apartado factura Anterior.

¿esto es asi?

Saludos !
Hola, no, ellos quieren que el encadenamiento sea consistente, da igual que el encadenamiento que uses de base para calcular el siguiente sea erroneo, siempre que el actual este bien sacado, siempre has de usar el encadenamiento que pasaste anteriormente, osea el ultimo que calculaste, si es erroneo, lo solucionas, usando el ultimo que enviaste.




Cita:
Factura 1 aceptada huella: A
Factura 2 error por dni huella B
Factura 3 aceptada huella C <<- aunque el anterior Hash es incorrecto, este no , porque su semilla es la que tu enviaste , aunque fuese mal calculada, por algun motivo.

Factura 2 aceptada huella D <<-- esta está correctamente encadenada con la 3, porque la 3 se encadeno con el hash que enviaste y que ahora estas corrigiendo.


Abreviando, calculas el hash con datos erroneos , te da bbbb, lo usas en el siguiente aunque sea erroneo, el calculo da ccc, para el siguiente el calculo cccc, es correcto porque en su formula, usaste bbbb que es lo que enviaste.


Tenemos un hilo entero aqui, al respecto.

Ten en cuenta que corrijes la huella del 2 registro en la aeat, creando un nuevo registro, no sustituyes ese registro en tu SIF, se queda inalterado.
__________________
Uno se alegra de ser útil. (Isaac Asimov)

Última edición por bmfranky fecha: 11-03-2025 a las 09:34:58. Razón: Diferenciar AEAT con SIF
Responder Con Cita
  #214  
Antiguo 11-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
gracias por la respuesta bmfranky !

entonces tenemos

ENVIO 1
---------
F0001-ACEPTADA ENLACE CON NADA, PRIMER REGISTRO
F0002-ACEPTADA ENLACE CON F0001
F0003-DNI ERROR ENLACE CON F0002
F0004-ACEPTADA ENLACE CON F0003

ENVIO 2
---------
F0003 ACEPTADA-DNI YA CORRECTO - ENLACE CON F0004
F0005 ACEPTADA ENLACE CON F0004 ¿o con F0003?
F0006 ACEPTADA ENLACE CON F0005

¿seria asi?
Responder Con Cita
  #215  
Antiguo 11-03-2025
Avatar de DarkDudae
DarkDudae DarkDudae is offline
Miembro
 
Registrado: abr 2006
Posts: 126
Poder: 20
DarkDudae Va por buen camino
La F0005 iría con la F0003 en ese caso. Ya que la F0003 aceptada, es cronológicamente su predecesora.
__________________
El recuerdo es la prisión en la que el alma sueña pasado, cuando no vive el presente, ni quiere un futuro.

Última edición por DarkDudae fecha: 11-03-2025 a las 11:21:15.
Responder Con Cita
  #216  
Antiguo 11-03-2025
Avatar de bmfranky
bmfranky bmfranky is offline
Miembro
 
Registrado: may 2024
Ubicación: Gandia, Valencia
Posts: 599
Poder: 1
bmfranky Va por buen camino
Encadenamiento Registros , No Facturas

Cita:
Empezado por seccion_31 Ver Mensaje
gracias por la respuesta bmfranky !

entonces tenemos

ENVIO 1
---------
F0001-ACEPTADA ENLACE CON NADA, PRIMER REGISTRO
F0002-ACEPTADA ENLACE CON F0001
F0003-DNI ERROR ENLACE CON F0002
F0004-ACEPTADA ENLACE CON F0003

ENVIO 2
---------
F0003 ACEPTADA-DNI YA CORRECTO - ENLACE CON F0004
F0005 ACEPTADA ENLACE CON F0004 ¿o con F0003?
F0006 ACEPTADA ENLACE CON F0005

¿seria asi?
Cita:
Empezado por DarkDudae Ver Mensaje
La F5 iría con la F3 en ese caso. Ya que la F3 aceptada es cronológicamente su predecesora.

Hola, el encadenamiento es sobre el registro anterior, has de coger de el sus datos para el siguiente encadenamiento


Cita:
ENVIO 1
---------
NReg - Fac
0000 - F0001-ACEPTADA ENLACE CON NADA, PRIMER REGISTRO
0001 - F0002-ACEPTADA ENLACE CON 0000
0002 - F0003-DNI ERROR ENLACE CON 0001
0003 - F0004-ACEPTADA ENLACE CON 0002

ENVIO 2
---------
0004 - F0003 ACEPTADA-DNI YA CORRECTO - ENLACE CON 0003
0005 - F0005 ACEPTADA ENLACE CON 0004
0006 - F0006 ACEPTADA ENLACE CON 0005

Se enlaza con el contenido del registro anterior, sea de alta, baja, modificacion, no con la factura.
__________________
Uno se alegra de ser útil. (Isaac Asimov)

Última edición por bmfranky fecha: 11-03-2025 a las 11:26:32.
Responder Con Cita
  #217  
Antiguo 11-03-2025
Avatar de DarkDudae
DarkDudae DarkDudae is offline
Miembro
 
Registrado: abr 2006
Posts: 126
Poder: 20
DarkDudae Va por buen camino
Cita:
Empezado por bmfranky Ver Mensaje
Se enlaza con el contenido del registro anterior, sea de alta, baja, modificacion, no con la factura.
Exacto, me refería justo a a eso. Pensaba que se sobreentendía.
__________________
El recuerdo es la prisión en la que el alma sueña pasado, cuando no vive el presente, ni quiere un futuro.
Responder Con Cita
  #218  
Antiguo 11-03-2025
Avatar de bmfranky
bmfranky bmfranky is offline
Miembro
 
Registrado: may 2024
Ubicación: Gandia, Valencia
Posts: 599
Poder: 1
bmfranky Va por buen camino
Cita:
Empezado por DarkDudae Ver Mensaje
Exacto, me refería justo a a eso. Pensaba que se sobreentendía.
Si, pero como en el ejemplo, se hacia referencia al numero de factura F0003, he creido que se entenderia mejor de esta manera, un saludo.
__________________
Uno se alegra de ser útil. (Isaac Asimov)
Responder Con Cita
  #219  
Antiguo 11-03-2025
Avatar de DarkDudae
DarkDudae DarkDudae is offline
Miembro
 
Registrado: abr 2006
Posts: 126
Poder: 20
DarkDudae Va por buen camino
Cita:
Empezado por bmfranky Ver Mensaje
Si, pero como en el ejemplo, se hacia referencia al numero de factura F0003, he creido que se entenderia mejor de esta manera, un saludo.
Sí, se entiende mucho mejor.
__________________
El recuerdo es la prisión en la que el alma sueña pasado, cuando no vive el presente, ni quiere un futuro.
Responder Con Cita
  #220  
Antiguo 11-03-2025
Avatar de seccion_31
seccion_31 seccion_31 is offline
Miembro
 
Registrado: ene 2017
Posts: 292
Poder: 9
seccion_31 Va por buen camino
gracias por las respuestas !

¿y si el emisor tiene varias series? (una para tickets, y otra para facturas )

por ejemplo

F0003 ACEPTADA ENLAZADO CON F0002
V0002 ACEPTADA ¿ENLAZADO CON F0003?

saludos !
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Verifactu o por requerimiento (no-verifactu) ¿decisión del usuario? Maska10 Temas legales 2 07-12-2024 12:34:47
Demo de una applicación para una estación de enfermera con RAD Studio AgustinOrtu La Taberna 1 21-07-2015 17:41:35
Demo Delphi, EMail Caral Internet 1 19-12-2006 00:37:56
Demo de delphi 2005 mazinger Varios 2 18-12-2004 09:23:09
El Rave que viene con Delphi es una Demo? apicito Impresión 0 04-06-2003 11:33:36


La franja horaria es GMT +2. Ahora son las 19:11:58.


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