Sample code for 30+ languages & platforms
Pascal (Lazarus/Delphi)

Create SOAP with multiple VeriFactu Digitally Signed Registration Records

See more Verifactu Examples

Creates a SOAP message containing a multiple digitally signed invoice registration records, formatted according to the specifications for Spain's Veri*Factu system.

Chilkat Pascal (Lazarus/Delphi) Downloads

Pascal (Lazarus/Delphi)
program ChilkatDemo;

// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils,
  CkDllLoader,
  Chilkat.StringBuilder,
  Chilkat.Xml;

// ---------------------------------------------------------------------------

procedure RunDemo;
var
  success: Boolean;
  xml: TXml;
  sbXml: TStringBuilder;
  sbSignedSoap: TStringBuilder;

begin
  success := False;

  success := True;

  //  Begin with the following SOAP XML:

  //  <?xml version="1.0" encoding="utf-8"?>
  //  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sum="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd" xmlns:sum1="https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
  //      <soapenv:Header/>
  //      <soapenv:Body>
  //          <sum:RegFactuSistemaFacturacion>
  //              <sum:Cabecera>
  //                  <sum1:ObligadoEmision>
  //                      <sum1:NombreRazon>XYZ STORE SL</sum1:NombreRazon>
  //                      <sum1:NIF>B99999999</sum1:NIF>
  //                  </sum1:ObligadoEmision>
  //                  <sum1:RemisionRequerimiento>
  //                      <sum1:RefRequerimiento>3333333333</sum1:RefRequerimiento>
  //                      <sum1:FinRequerimiento>S</sum1:FinRequerimiento>
  //                  </sum1:RemisionRequerimiento>
  //              </sum:Cabecera>
  //  
  //          </sum:RegFactuSistemaFacturacion>
  //      </soapenv:Body>
  //  </soapenv:Envelope>

  xml := TXml.Create;
  xml.Tag := 'soapenv:Envelope';
  xml.AddAttribute('xmlns:soapenv','http://schemas.xmlsoap.org/soap/envelope/');
  xml.AddAttribute('xmlns:sum','https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd');
  xml.AddAttribute('xmlns:sum1','https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd');
  xml.AddAttribute('xmlns:xd','http://www.w3.org/2000/09/xmldsig#');
  xml.UpdateChildContent('soapenv:Header','');
  xml.UpdateChildContent('soapenv:Body|sum:RegFactuSistemaFacturacion|sum:Cabecera|sum1:ObligadoEmision|sum1:NombreRazon','XYZ STORE SL');
  xml.UpdateChildContent('soapenv:Body|sum:RegFactuSistemaFacturacion|sum:Cabecera|sum1:ObligadoEmision|sum1:NIF','B99999999');
  xml.UpdateChildContent('soapenv:Body|sum:RegFactuSistemaFacturacion|sum:Cabecera|sum1:RemisionRequerimiento|sum1:RefRequerimiento','3333333333');
  xml.UpdateChildContent('soapenv:Body|sum:RegFactuSistemaFacturacion|sum:Cabecera|sum1:RemisionRequerimiento|sum1:FinRequerimiento','S');

  //  Prior to this code, we created N signed SOAP messages, each containing a single signed record.
  //  Load each of these signed SOAP messages into a StringBuilder and insert after the "</sum:Cabecera>"
  //  Note: We must NOT use Chilkat.Xml for this.  We must do string operations using Chilkat StringBuilder to prevent whitespace or formatting modifications which would break the signatures.

  sbXml := TStringBuilder.Create;
  xml.GetXmlSb(sbXml);

  //  ---------------------------------------------------------------------------------------------
  //  Load the previously signed XML containing just one signed record.
  sbSignedSoap := TStringBuilder.Create;
  success := sbSignedSoap.LoadFile('c:/temp/qa_output/signedSoapXml1.xml','utf-8');
  if (success = False) then
    begin
      WriteLn(sbSignedSoap.LastErrorText);
      Exit;
    end;

  //  Remove everything before "</sum:Cabecera>", including the "</sum:Cabecera>"
  sbSignedSoap.RemoveBefore('</sum:Cabecera>');

  //  Remove everything after the "</sum:RegFactuSistemaFacturacion>", including the "</sum:RegFactuSistemaFacturacion>"
  sbSignedSoap.RemoveAfterFinal('</sum:RegFactuSistemaFacturacion>');

  //  We now have the portion of the signed SOAP xml from <sum:RegistroFactura> to </sum:RegistroFactura>
  //  Insert it after the </sum:Cabecera>
  sbSignedSoap.Prepend('</sum:Cabecera>');
  sbXml.ReplaceFirst('</sum:Cabecera>',sbSignedSoap.GetAsString());

  //  ---------------------------------------------------------------------------------------------
  //  Add the next signed SOAP containing a single signed record.
  success := sbSignedSoap.LoadFile('c:/temp/qa_output/signedSoapXml2.xml','utf-8');
  if (success = False) then
    begin
      WriteLn(sbSignedSoap.LastErrorText);
      Exit;
    end;

  //  Remove everything before "</sum:Cabecera>", including the "</sum:Cabecera>"
  sbSignedSoap.RemoveBefore('</sum:Cabecera>');

  //  Remove everything after the "</sum:RegFactuSistemaFacturacion>", including the "</sum:RegFactuSistemaFacturacion>"
  sbSignedSoap.RemoveAfterFinal('</sum:RegFactuSistemaFacturacion>');

  //  We now have the portion of the signed SOAP xml from <sum:RegistroFactura> to </sum:RegistroFactura>
  //  Insert it after the </sum:Cabecera>
  sbSignedSoap.Prepend('</sum:Cabecera>');
  sbXml.ReplaceFirst('</sum:Cabecera>',sbSignedSoap.GetAsString());

  //  ---------------------------------------------------------------------------------------------
  //  Continue adding more signed records if needed.

  //  Save the SOAP containing multiple signed records..
  sbXml.WriteFile('c:/temp/qa_output/soap_combined.xml','utf-8',False);


  xml.Free;
  sbXml.Free;
  sbSignedSoap.Free;

end;

// ---------------------------------------------------------------------------

begin

  try
    RunDemo;
  except
    on E: Exception do
      WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
  end;

  WriteLn;
  {$IFDEF MSWINDOWS}
  WriteLn('Press Enter to exit...');
  ReadLn;
  {$ENDIF}
end.