diff --git a/lib/zatca/ubl/builder.rb b/lib/zatca/ubl/builder.rb index 0b7002c..68acfc7 100644 --- a/lib/zatca/ubl/builder.rb +++ b/lib/zatca/ubl/builder.rb @@ -51,25 +51,25 @@ def apply_qualifying_properties_hacks(invoice, xml) # C14N 1.1 then manually adds back the whitespace in the format that ZATCA # expects. def canonicalized_xml(builder:) + return builder.doc.canonicalize(Nokogiri::XML::XML_C14N_1_1) + + # TODO: In case ZATCA ever asks us to use their whitespace format again. + # In some meetings they say we have to use it, in some meetings they say + # we don't. The simpler approach is that we don't use it. + # # ZATCA's docs specifically state we must use C14N 1.1 canonicalization. xml = uncanonicalized_xml(builder: builder, spaces: 4) xml_doc = Nokogiri::XML(xml) canonical_xml = xml_doc.canonicalize(Nokogiri::XML::XML_C14N_1_1) - require "byebug" - byebug - canonical_xml end def uncanonicalized_xml(builder:, spaces: 4) xml = builder.to_xml(indent: spaces.to_i) - xml = match_xml_string_to_zatca_whitespaces(xml) - - require "byebug" - byebug + # xml = match_xml_string_to_zatca_whitespaces(xml) xml end @@ -95,9 +95,13 @@ def match_xml_string_to_zatca_whitespaces(xml) # This part is not clear, ZATCA shared documents with us that use CRLF # but the samples in the SDK use LF, so we're not sure which one is correct. # ZATCA wants CRLF (\r\n) in their canonicalized form instead of just LF (\n) - # xml.gsub!("\n", "\r\n") + xml.gsub!("\n", "\r\n") + + xml end + # Not sure if this is needed, in some meetings ZATCA says you have to match + # their whitspace exactly and in some meetings they say you don't. # HACK: This is really hacky, using regexes or XPaths would be better, but # that wasn't easy to build and maintain, so we're using this if/until we run # into issues. diff --git a/lib/zatca/ubl/invoice.rb b/lib/zatca/ubl/invoice.rb index 845c70f..cf9600b 100644 --- a/lib/zatca/ubl/invoice.rb +++ b/lib/zatca/ubl/invoice.rb @@ -180,7 +180,7 @@ def generate_hash # When submitting to ZATCA, we need to submit the XML in Base64 format, and it # needs to be pretty-printed matching their indentation style. # The canonicalized option here is left only for debugging purposes. - def to_base64(canonicalized: false) + def to_base64(canonicalized: true) canonicalized_xml_with_hacks_applied = generate_xml( canonicalized: canonicalized, apply_invoice_hacks: true, @@ -195,7 +195,7 @@ def to_base64(canonicalized: false) # an after_initialize callback. We just need to set the qualifying properties # at any point before generating the XML. def generate_xml( - canonicalized: false, + canonicalized: true, spaces: 4, apply_invoice_hacks: true, remove_root_xml_tag: false @@ -216,7 +216,7 @@ def generate_xml( end def generate_unsigned_xml( - canonicalized: false, + canonicalized: true, apply_invoice_hacks: false, remove_root_xml_tag: false ) diff --git a/spec/lib/zatca/ubl/invoice_spec.rb b/spec/lib/zatca/ubl/invoice_spec.rb index a7bd5c5..9f1ea6b 100644 --- a/spec/lib/zatca/ubl/invoice_spec.rb +++ b/spec/lib/zatca/ubl/invoice_spec.rb @@ -10,7 +10,7 @@ def clear_dynamic_values_from_xml(xml) invoice = construct_simplified_invoice zatca_xml = read_xml_fixture("simplified_invoice_signed.xml") - expect(invoice.generate_xml).to eq(zatca_xml) + expect(invoice.generate_xml(canonicalized: false, spaces: 2)).to eq(zatca_xml) end it "should be able to create an unsigned invoice qr-less invoice then add them later" do @@ -56,7 +56,7 @@ def clear_dynamic_values_from_xml(xml) zatca_xml = read_xml_fixture("simplified_invoice_signed.xml") - generated_xml = invoice.generate_xml(canonicalized: true) + generated_xml = invoice.generate_xml(canonicalized: false, spaces: 2) # TODO: Remove these once done testing File.write("TEST_ME_WITH_ZATCA.xml", generated_xml) @@ -100,7 +100,7 @@ def clear_dynamic_values_from_xml(xml) invoice = construct_signed_standard_invoice zatca_xml = read_xml_fixture("standard_invoice.xml") - expect(invoice.generate_xml).to eq(zatca_xml) + expect(invoice.generate_xml(canonicalized: false, spaces: 2)).to eq(zatca_xml) end it "should be able to generate an unsigned qr-less standard invoice" do @@ -117,7 +117,7 @@ def clear_dynamic_values_from_xml(xml) .gsub(/\s*\s*QR<\/cbc:ID>.*<\/cac:AdditionalDocumentReference>/m, "") File.write("STANDARD_UNSIGNED_TEST_WITH_ZATCA.xml", invoice.generate_xml) - expect(invoice.generate_xml).to eq(zatca_xml) + expect(invoice.generate_xml(canonicalized: false, spaces: 2)).to eq(zatca_xml) end end end