Buenas tardes,
Estoy con un problema que no consigo encontrar la solución, a ver si alguien pudiese echarme una mano.
Cuando envío más de 20 facturas emitidas (me pasa lo mismo con las recibidas) recibo el siguiente error:
Se requiere un certificado para completar la autenticación de cliente - URL:
https://www7.aeat.es/wlpl/SSII-FACT/...iiFactFEV1SOAP - SOAPAction:""
Si esas mismas facturas las envío en dos veces, me las envía sin problema.
Para realizar el envío, genero el xml con delphi 7 y realizo el envío mediante una dll que he creado con Delphi XE7.
El código mediante el cual hago el envío es el siguiente:
Código:
type
TComunicacionSW = class(TObject)
private
FArchivoEnvio: String;
FArchivoRespuesta: String;
FHTTPRIO: THTTPRIO;
procedure HTTPRIOBeforeExecute(const MethodName: string; SOAPRequest: TStream);
procedure HTTPRIOAfterExecute(const MethodName: string; SOAPResponse: TStream);
public
Constructor Create;
Destructor Destroy;
end;
procedure TComunicacionSW.HTTPRIOBeforeExecute(const MethodName: string; SOAPRequest: TStream);
var
v_fileStream: TFileStream;
begin
SOAPRequest.Size := 0;
v_fileStream := TFileStream.Create(FArchivoEnvio, fmOpenRead);
SOAPRequest.Position := 0;
SOAPRequest.CopyFrom(v_fileStream, v_fileStream.Size);
v_fileStream.Free;
SOAPRequest.Position := 0;
end;
procedure TComunicacionSW.HTTPRIOAfterExecute(const MethodName: string; SOAPResponse: TStream);
var
v_fileStream: TFileStream;
begin
if FileExists(FArchivoRespuesta) then
DeleteFile(FArchivoRespuesta);
v_fileStream := TFileStream.Create(FArchivoRespuesta, fmCreate);
SOAPResponse.Position := 0;
v_fileStream.CopyFrom(SOAPResponse, SOAPResponse.size);
v_fileStream.Free;
SOAPResponse.Position := 0;
end;
function ObtenerNumeroSerieCertificado(p_nombreCertificado: String): string;
var
hStore: HCERTSTORE;
PrevContext, CurContext: PCERT_CONTEXT;
cbSize: DWORD;
v_nombre: String;
begin
Result := '';
hStore := CertOpenSystemStore(0, PChar('MY'));
if hStore <> nil then
begin
PrevContext := nil;
CurContext := CertEnumCertificatesInStore(hStore, PrevContext);
while CurContext <> nil do begin
v_nombre := '';
cbSize := CertGetNameString(CurContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, nil, 0);
if cbSize > 0 then
begin
SetLength(v_nombre, cbSize-1);
CertGetNameString(CurContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, PChar(v_nombre), cbSize);
if SameText(p_nombreCertificado, v_nombre) then
begin
result := GetCertSerialNumber(@CurContext^.pCertInfo^.SerialNumber);
break;
end;
end;
PrevContext := CurContext;
CurContext := CertEnumCertificatesInStore(hStore, PrevContext);
end;
end;
end;
function EnviarFacturasEmitidas(p_nombreCertificado, p_archivoEnvio, p_archivoRespuesta: ShortString): PChar;stdcall;export;
var
v_suministroLRFacturasEmitidas: SuministroFactEmitidas.SuministroLRFacturasEmitidas;
v_respuestaLRFacturasEmitidas: SuministroFactEmitidas.RespuestaLRFacturasEmitidas;
v_siiSOAP: SuministroFactEmitidas.siiSOAP;
v_serialNum: String;
v_error: string;
v_comunicacionSW: TComunicacionSW;
begin
v_error := '';
v_serialNum := ObtenerNumeroSerieCertificado(p_nombreCertificado);
v_comunicacionSW := TComunicacionSW.Create;
v_suministroLRFacturasEmitidas := SuministroFactEmitidas.SuministroLRFacturasEmitidas.Create;
v_respuestaLRFacturasEmitidas := SuministroFactEmitidas.RespuestaLRFacturasEmitidas.Create;
try
try
v_comunicacionSW.FArchivoEnvio := p_archivoEnvio;
v_comunicacionSW.FArchivoRespuesta := p_archivoRespuesta;
v_comunicacionSW.FHTTPRIO.HTTPWebNode.ClientCertificate.SerialNum := v_serialNum;
//Se realiza la llamada sin datos y en el evento HTTPRIOBeforeExecute se establece el xml con los datos generados anteriormente
v_siiSOAP := SuministroFactEmitidas.GetsiiSOAP(true,'',v_comunicacionSW.FHTTPRIO);
v_respuestaLRFacturasEmitidas := v_siiSOAP.SuministroLRFacturasEmitidas(v_suministroLRFacturasEmitidas);
except
on e:Exception do
v_error := 'Error DLL: Error en la comunicación con el servicio web.' + e.Message;
end;
finally
v_suministroLRFacturasEmitidas.Free;
v_respuestaLRFacturasEmitidas.Free;
end;
result := StringToPChar(v_error);
end;
El archivo SuministroFactEmitidas lo he generado automáticamente con WSDL Importer de delphi y le he modificado lo siguiente (defURL realmente no lo utilizo):
const
defWSDL = 'https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/ssii/fact/ws/SuministroFactEmitidas.wsdl';
defURL = 'https://www7.aeat.es/wlpl/SSII-FACT/wlpl/SSII-FACT/ws/fe/SiiFactFEV1SOAP';
defSvc = 'siiService';
defPrt = 'SuministroFactEmitidasPruebas';
¿Se le ocurre a alguien que es lo que estoy haciendo mal?
Un saludo