Firma avanzada

La librer铆a permite firmar documentos XML de FacturaE que hayan sido generados con otros programas a trav茅s de la clase FacturaeSigner. Esta misma clase es usada a nivel interno para firmar las facturas creadas con Facturae-PHP.

use josemmo\Facturae\Common\FacturaeSigner;
use RuntimeException;

// Creaci贸n y configuraci贸n de la instancia
$signer = new FacturaeSigner();
$signer->loadPkcs12("certificado.pfx", "passphrase");
$signer->setTimestampServer("https://www.safestamper.com/tsa", "usuario", "contrase帽a");

// Firma electr贸nica
$xml = file_get_contents(__DIR__ . "/factura.xml");
try {
  $signedXml = $signer->sign($xml);
} catch (RuntimeException $e) {
  // Fallo al firmar
}

// Sellado de tiempo
try {
  $timestampedXml = $signer->timestamp($signedXml);
} catch (RuntimeException $e) {
  // Fallo al a帽adir sello de tiempo
}
file_put_contents(__DIR__ . "/factura.xsig", $timestampedXml);

FacturaeSigner es capaz de firmar cualquier documento XML v谩lido que cumpla con la especificaci贸n de FacturaE, siempre y cuando:

  • El elemento ra铆z del documento sea <fe:Facturae />
  • El namespace de FacturaE sea xmlns:fe
  • El namespace de XMLDSig no aparezca (recomendable) o sea xmlns:ds
  • El namespace de XAdES no aparezca (recomendable) o sea xmlns:xades

La inmensa mayor铆a de programas que generan documentos de FacturaE cumplen con estos requisitos.


Fecha de la firma

Por defecto, al firmar una factura se utilizan la fecha y hora actuales como sello de tiempo. Si se quiere indicar otro valor, se debe utilizar el siguiente m茅todo:

$signer->setSigningTime("2017-01-01T12:34:56+02:00");

NOTA

Cambiar manualmente la fecha de la firma puede entrar en conflicto con el sellado de tiempo.


Identificadores de elementos XML

Al firmar un documento XML, durante la firma se a帽aden una serie de identificadores a determinados nodos en forma de atributos (por ejemplo, <xades:SignedProperties Id="Signature1234-SignedProperties9876" />). Estos identificadores son necesarios para validar la firma e integridad del documento.

Por defecto, sus valores se generan de forma aleatoria en el momento de instanciaci贸n de la clase FacturaeSigner, por que lo que si se firman varias facturas con la misma instancia sus valores no cambian. Se recomienda llamar al m茅todo $signer->regenerateIds() si se firman varios documentos:

$firstXml = file_get_contents(__DIR__ . "/factura_1.xml");
$firstSignedXml = $signer->sign($firstXml);

$signer->regenerateIds();

$secondXml = file_get_contents(__DIR__ . "/factura_2.xml");
$secondSignedXml = $signer->sign($secondXml);

Tambi茅n es posible establecer valores deterministas a todos los IDs:

$signer->signatureId = "My-Custom-SignatureId";
$signer->certificateId = "My-Custom-CertificateId";
$signedXml = $signer->sign($xml);