generateUBLXml method

String generateUBLXml({
  1. required String invoiceHash,
  2. required String signingTime,
  3. required String digitalSignature,
  4. required String invoiceXmlString,
  5. required String qrString,
})

Implementation

String generateUBLXml({
  required String invoiceHash,
  required String signingTime,
  required String digitalSignature,
  required String invoiceXmlString,
  required String qrString,
}) {
  final cleanedCertificate = CertificateUtil.cleanCertificatePem(
    _certificatePem!,
  );
  final certificateInfo = CertificateUtil.getCertificateInfo(
    _certificatePem!,
  );
  final defaultUBLExtensionsSignedPropertiesForSigningXML =
      XmlUtil.defaultUBLExtensionsSignedPropertiesForSigning(
        signingTime: signingTime,
        certificateHash: certificateInfo.hash,
        certificateIssuer: certificateInfo.issuer,
        certificateSerialNumber: certificateInfo.serialNumber,
      );

  // 5: Get SignedProperties hash
  String defaultUBLExtensionsSignedPropertiesForSigningXMLString =
      defaultUBLExtensionsSignedPropertiesForSigningXML.toXmlString(
        pretty: true,
        indent: '    ',
      );
  defaultUBLExtensionsSignedPropertiesForSigningXMLString =
      defaultUBLExtensionsSignedPropertiesForSigningXMLString
          .split('\n')
          .map((e) {
            return e.padLeft(e.length + 32);
          })
          .join('\n');
  defaultUBLExtensionsSignedPropertiesForSigningXMLString =
      defaultUBLExtensionsSignedPropertiesForSigningXMLString.replaceFirst(
        '                                <xades:SignedProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="xadesSignedProperties">',
        '<xades:SignedProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="xadesSignedProperties">',
      );

  final signedPropertiesBytes = utf8.encode(
    defaultUBLExtensionsSignedPropertiesForSigningXMLString,
  );
  final signedPropertiesHash =
      sha256.convert(signedPropertiesBytes).toString();
  final signedPropertiesHashBase64 = base64.encode(
    utf8.encode(signedPropertiesHash),
  );

  final defaultUBLExtensionsSignedPropertiesXML =
      XmlUtil.defaultUBLExtensionsSignedProperties(
        signingTime: signingTime,
        certificateHash: certificateInfo.hash,
        certificateIssuer: certificateInfo.issuer,
        certificateSerialNumber: certificateInfo.serialNumber,
      );
  final ublStandardXML = XmlUtil.generateUBLSignExtensionsXml(
    invoiceHash: invoiceHash,
    signedPropertiesHash: signedPropertiesHashBase64,
    digitalSignature: digitalSignature,
    certificateString: cleanedCertificate,
    ublSignatureSignedPropertiesXML: defaultUBLExtensionsSignedPropertiesXML,
  );

  final xmlDocument = XmlDocument.parse(invoiceXmlString);
  xmlDocument.rootElement.children.insert(
    0,
    ublStandardXML.rootElement.copy(),
  );

  final qrXml = XmlUtil.generateQrAndSignatureXMl(qrString: qrString);

  final supplierPartyIndex = xmlDocument.rootElement.children.indexWhere(
    (node) =>
        node is XmlElement && node.name.local == 'AccountingSupplierParty',
  );
  xmlDocument.rootElement.children.insertAll(
    supplierPartyIndex,
    qrXml.children.map((node) => node.copy()).toList(),
  );

  String xml = xmlDocument.toXmlString(pretty: true, indent: '    ');
  String defaultUBLExtensionsSignedPropertiesXMLString =
      defaultUBLExtensionsSignedPropertiesXML.rootElement.toXmlString(
        pretty: true,
        indent: '    ',
      );
  defaultUBLExtensionsSignedPropertiesXMLString =
      defaultUBLExtensionsSignedPropertiesXMLString
          .split('\n')
          .map((e) {
            return e.padLeft(e.length + 28);
          })
          .join('\n');
  defaultUBLExtensionsSignedPropertiesXMLString =
      defaultUBLExtensionsSignedPropertiesXMLString.replaceFirst(
        '                            <xades:QualifyingProperties Target="signature" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">',
        '<xades:QualifyingProperties Target="signature" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">',
      );
  String replacable = """<ds:Object>
                          $defaultUBLExtensionsSignedPropertiesXMLString
                          </ds:Object>""";
  xml = xml.replaceFirst('<ds:Object-1/>', replacable);

  return xml;
}