zatca-sdk 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE +21 -0
  5. data/README.md +60 -0
  6. data/Rakefile +4 -0
  7. data/bin/console +15 -0
  8. data/bin/setup +8 -0
  9. data/lib/zatca/client.rb +211 -0
  10. data/lib/zatca/hacks.rb +45 -0
  11. data/lib/zatca/hashing.rb +18 -0
  12. data/lib/zatca/qr_code_extractor.rb +31 -0
  13. data/lib/zatca/qr_code_generator.rb +28 -0
  14. data/lib/zatca/signing/certificate.rb +78 -0
  15. data/lib/zatca/signing/csr.rb +220 -0
  16. data/lib/zatca/signing/ecdsa.rb +59 -0
  17. data/lib/zatca/tag.rb +44 -0
  18. data/lib/zatca/tags.rb +46 -0
  19. data/lib/zatca/tags_schema.rb +22 -0
  20. data/lib/zatca/types.rb +7 -0
  21. data/lib/zatca/ubl/base_component.rb +142 -0
  22. data/lib/zatca/ubl/builder.rb +166 -0
  23. data/lib/zatca/ubl/common_aggregate_components/allowance_charge.rb +64 -0
  24. data/lib/zatca/ubl/common_aggregate_components/classified_tax_category.rb +25 -0
  25. data/lib/zatca/ubl/common_aggregate_components/delivery.rb +27 -0
  26. data/lib/zatca/ubl/common_aggregate_components/invoice_line.rb +63 -0
  27. data/lib/zatca/ubl/common_aggregate_components/item.rb +21 -0
  28. data/lib/zatca/ubl/common_aggregate_components/legal_monetary_total.rb +59 -0
  29. data/lib/zatca/ubl/common_aggregate_components/party.rb +28 -0
  30. data/lib/zatca/ubl/common_aggregate_components/party_identification.rb +25 -0
  31. data/lib/zatca/ubl/common_aggregate_components/party_legal_entity.rb +19 -0
  32. data/lib/zatca/ubl/common_aggregate_components/party_tax_scheme.rb +30 -0
  33. data/lib/zatca/ubl/common_aggregate_components/postal_address.rb +59 -0
  34. data/lib/zatca/ubl/common_aggregate_components/price.rb +20 -0
  35. data/lib/zatca/ubl/common_aggregate_components/tax_category.rb +56 -0
  36. data/lib/zatca/ubl/common_aggregate_components/tax_total.rb +58 -0
  37. data/lib/zatca/ubl/common_aggregate_components.rb +2 -0
  38. data/lib/zatca/ubl/invoice.rb +481 -0
  39. data/lib/zatca/ubl/invoice_subtype_builder.rb +50 -0
  40. data/lib/zatca/ubl/signing/cert.rb +48 -0
  41. data/lib/zatca/ubl/signing/invoice_signed_data_reference.rb +44 -0
  42. data/lib/zatca/ubl/signing/key_info.rb +25 -0
  43. data/lib/zatca/ubl/signing/object.rb +20 -0
  44. data/lib/zatca/ubl/signing/qualifying_properties.rb +27 -0
  45. data/lib/zatca/ubl/signing/signature.rb +50 -0
  46. data/lib/zatca/ubl/signing/signature_information.rb +19 -0
  47. data/lib/zatca/ubl/signing/signature_properties_reference.rb +26 -0
  48. data/lib/zatca/ubl/signing/signed_info.rb +21 -0
  49. data/lib/zatca/ubl/signing/signed_properties.rb +81 -0
  50. data/lib/zatca/ubl/signing/signed_signature_properties.rb +23 -0
  51. data/lib/zatca/ubl/signing/ubl_document_signatures.rb +25 -0
  52. data/lib/zatca/ubl/signing/ubl_extension.rb +22 -0
  53. data/lib/zatca/ubl/signing/ubl_extensions.rb +17 -0
  54. data/lib/zatca/ubl/signing.rb +2 -0
  55. data/lib/zatca/ubl.rb +2 -0
  56. data/lib/zatca/version.rb +5 -0
  57. data/lib/zatca.rb +48 -0
  58. data/zatca_sdk.gemspec +52 -0
  59. metadata +301 -0
@@ -0,0 +1,25 @@
1
+ class ZATCA::UBL::Signing::KeyInfo < ZATCA::UBL::BaseComponent
2
+ # <ds:KeyInfo>
3
+ # <ds:X509Data>
4
+ # <ds:X509Certificate>MIID9jCCA5ugAwIBAgITbwAAeCy9aKcLA99HrAABAAB4LDAKBggqhkjOPQQDAjBjMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNnb3YxFzAVBgoJkiaJk/IsZAEZFgdleHRnYXp0MRwwGgYDVQQDExNUU1pFSU5WT0lDRS1TdWJDQS0xMB4XDTIyMDQxOTIwNDkwOVoXDTI0MDQxODIwNDkwOVowWTELMAkGA1UEBhMCU0ExEzARBgNVBAoTCjMxMjM0NTY3ODkxDDAKBgNVBAsTA1RTVDEnMCUGA1UEAxMeVFNULS05NzA1NjAwNDAtMzEyMzQ1Njc4OTAwMDAzMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYYMMoOaFYAhMO/steotfZyavr6p11SSlwsK9azmsLY7b1b+FLhqMArhB2dqHKboxqKNfvkKDePhpqjui5hcn0aOCAjkwggI1MIGaBgNVHREEgZIwgY+kgYwwgYkxOzA5BgNVBAQMMjEtVFNUfDItVFNUfDMtNDdmMTZjMjYtODA2Yi00ZTE1LWIyNjktN2E4MDM4ODRiZTljMR8wHQYKCZImiZPyLGQBAQwPMzEyMzQ1Njc4OTAwMDAzMQ0wCwYDVQQMDAQxMTAwMQwwCgYDVQQaDANUU1QxDDAKBgNVBA8MA1RTVDAdBgNVHQ4EFgQUO5ZiU7NakU3eejVa3I2S1B2sDwkwHwYDVR0jBBgwFoAUdmCM+wagrGdXNZ3PmqynK5k1tS8wTgYDVR0fBEcwRTBDoEGgP4Y9aHR0cDovL3RzdGNybC56YXRjYS5nb3Yuc2EvQ2VydEVucm9sbC9UU1pFSU5WT0lDRS1TdWJDQS0xLmNybDCBrQYIKwYBBQUHAQEEgaAwgZ0wbgYIKwYBBQUHMAGGYmh0dHA6Ly90c3RjcmwuemF0Y2EuZ292LnNhL0NlcnRFbnJvbGwvVFNaRWludm9pY2VTQ0ExLmV4dGdhenQuZ292LmxvY2FsX1RTWkVJTlZPSUNFLVN1YkNBLTEoMSkuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vdHN0Y3JsLnphdGNhLmdvdi5zYS9vY3NwMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwMwJwYJKwYBBAGCNxUKBBowGDAKBggrBgEFBQcDAjAKBggrBgEFBQcDAzAKBggqhkjOPQQDAgNJADBGAiEA7mHT6yg85jtQGWp3M7tPT7Jk2+zsvVHGs3bU5Z7YE68CIQD60ebQamYjYvdebnFjNfx4X4dop7LsEBFCNSsLY0IFaQ==</ds:X509Certificate>
5
+ # </ds:X509Data>
6
+ # </ds:KeyInfo>
7
+
8
+ def initialize(certificate:)
9
+ super()
10
+
11
+ @certificate = certificate
12
+ end
13
+
14
+ def name
15
+ "ds:KeyInfo"
16
+ end
17
+
18
+ def elements
19
+ [
20
+ ZATCA::UBL::BaseComponent.new(name: "ds:X509Data", elements: [
21
+ ZATCA::UBL::BaseComponent.new(name: "ds:X509Certificate", value: @certificate)
22
+ ])
23
+ ]
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ class ZATCA::UBL::Signing::Object < ZATCA::UBL::BaseComponent
2
+ def initialize(signing_time:, cert_digest_value:, cert_issuer_name:, cert_serial_number:)
3
+ super()
4
+
5
+ @signing_time = signing_time
6
+ @cert_digest_value = cert_digest_value
7
+ @cert_issuer_name = cert_issuer_name
8
+ @cert_serial_number = cert_serial_number
9
+ end
10
+
11
+ def name
12
+ "ds:Object"
13
+ end
14
+
15
+ def elements
16
+ [
17
+ ZATCA::UBL::Signing::QualifyingProperties.new(signing_time: @signing_time, cert_digest_value: @cert_digest_value, cert_issuer_name: @cert_issuer_name, cert_serial_number: @cert_serial_number)
18
+ ]
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ class ZATCA::UBL::Signing::QualifyingProperties < ZATCA::UBL::BaseComponent
2
+ def initialize(signing_time:, cert_digest_value:, cert_issuer_name:, cert_serial_number:)
3
+ super()
4
+
5
+ @signing_time = signing_time
6
+ @cert_digest_value = cert_digest_value
7
+ @cert_issuer_name = cert_issuer_name
8
+ @cert_serial_number = cert_serial_number
9
+ end
10
+
11
+ def name
12
+ "xades:QualifyingProperties"
13
+ end
14
+
15
+ def attributes
16
+ {
17
+ "Target" => "signature",
18
+ "xmlns:xades" => "http://uri.etsi.org/01903/v1.3.2#"
19
+ }
20
+ end
21
+
22
+ def elements
23
+ [
24
+ ZATCA::UBL::Signing::SignedProperties.new(signing_time: @signing_time, cert_digest_value: @cert_digest_value, cert_issuer_name: @cert_issuer_name, cert_serial_number: @cert_serial_number)
25
+ ]
26
+ end
27
+ end
@@ -0,0 +1,50 @@
1
+ class ZATCA::UBL::Signing::Signature < ZATCA::UBL::BaseComponent
2
+ attr_reader :signing_time, :cert_digest_value, :cert_issuer_name, :cert_serial_number
3
+
4
+ def initialize(
5
+ invoice_hash:, signed_properties_hash:, signature_value:,
6
+ certificate:, signing_time:, cert_digest_value:, cert_issuer_name:,
7
+ cert_serial_number:
8
+ )
9
+ super()
10
+
11
+ @invoice_digest = invoice_hash
12
+ @signed_properties_hash = signed_properties_hash
13
+ @signature_value = signature_value
14
+ @certificate = certificate
15
+ @signing_time = signing_time
16
+ @cert_digest_value = cert_digest_value
17
+ @cert_issuer_name = cert_issuer_name
18
+ @cert_serial_number = cert_serial_number
19
+ end
20
+
21
+ def attributes
22
+ {
23
+ "xmlns:ds" => "http://www.w3.org/2000/09/xmldsig#",
24
+ "Id" => "signature"
25
+ }
26
+ end
27
+
28
+ def name
29
+ "ds:Signature"
30
+ end
31
+
32
+ def elements
33
+ [
34
+ ZATCA::UBL::Signing::SignedInfo.new(
35
+ invoice_digest: @invoice_digest,
36
+ signed_properties_hash: @signed_properties_hash
37
+ ),
38
+
39
+ ZATCA::UBL::BaseComponent.new(name: "ds:SignatureValue", value: @signature_value),
40
+ ZATCA::UBL::Signing::KeyInfo.new(certificate: @certificate),
41
+
42
+ ZATCA::UBL::Signing::Object.new(
43
+ signing_time: @signing_time,
44
+ cert_digest_value: @cert_digest_value,
45
+ cert_issuer_name: @cert_issuer_name,
46
+ cert_serial_number: @cert_serial_number
47
+ )
48
+ ]
49
+ end
50
+ end
@@ -0,0 +1,19 @@
1
+ class ZATCA::UBL::Signing::SignatureInformation < ZATCA::UBL::BaseComponent
2
+ def initialize(signature:)
3
+ super()
4
+
5
+ @signature = signature
6
+ end
7
+
8
+ def name
9
+ "sac:SignatureInformation"
10
+ end
11
+
12
+ def elements
13
+ [
14
+ ZATCA::UBL::BaseComponent.new(name: "cbc:ID", value: "urn:oasis:names:specification:ubl:signature:1"),
15
+ ZATCA::UBL::BaseComponent.new(name: "sbc:ReferencedSignatureID", value: "urn:oasis:names:specification:ubl:signature:Invoice"),
16
+ @signature
17
+ ]
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ class ZATCA::UBL::Signing::SignaturePropertiesReference < ZATCA::UBL::BaseComponent
2
+ attr_accessor :digest_value
3
+
4
+ def initialize(digest_value:)
5
+ super()
6
+ @digest_value = digest_value
7
+ end
8
+
9
+ def name
10
+ "ds:Reference"
11
+ end
12
+
13
+ def attributes
14
+ {
15
+ "Type" => "http://www.w3.org/2000/09/xmldsig#SignatureProperties",
16
+ "URI" => "#xadesSignedProperties"
17
+ }
18
+ end
19
+
20
+ def elements
21
+ [
22
+ ZATCA::UBL::BaseComponent.new(name: "ds:DigestMethod", attributes: {"Algorithm" => "http://www.w3.org/2001/04/xmlenc#sha256"}),
23
+ ZATCA::UBL::BaseComponent.new(name: "ds:DigestValue", value: @digest_value)
24
+ ]
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ class ZATCA::UBL::Signing::SignedInfo < ZATCA::UBL::BaseComponent
2
+ def initialize(invoice_digest:, signed_properties_hash:)
3
+ super()
4
+
5
+ @invoice_digest = invoice_digest
6
+ @signed_properties_hash = signed_properties_hash
7
+ end
8
+
9
+ def name
10
+ "ds:SignedInfo"
11
+ end
12
+
13
+ def elements
14
+ [
15
+ ZATCA::UBL::BaseComponent.new(name: "ds:CanonicalizationMethod", attributes: {"Algorithm" => "http://www.w3.org/2006/12/xml-c14n11"}),
16
+ ZATCA::UBL::BaseComponent.new(name: "ds:SignatureMethod", attributes: {"Algorithm" => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"}),
17
+ ZATCA::UBL::Signing::InvoiceSignedDataReference.new(digest_value: @invoice_digest),
18
+ ZATCA::UBL::Signing::SignaturePropertiesReference.new(digest_value: @signed_properties_hash)
19
+ ]
20
+ end
21
+ end
@@ -0,0 +1,81 @@
1
+ class ZATCA::UBL::Signing::SignedProperties < ZATCA::UBL::BaseComponent
2
+ def initialize(
3
+ signing_time:,
4
+ cert_digest_value:,
5
+ cert_issuer_name:,
6
+ cert_serial_number:
7
+ )
8
+ super()
9
+
10
+ @signing_time = signing_time
11
+ @cert_digest_value = cert_digest_value
12
+ @cert_issuer_name = cert_issuer_name
13
+ @cert_serial_number = cert_serial_number
14
+ end
15
+
16
+ def name
17
+ "xades:SignedProperties"
18
+ end
19
+
20
+ def attributes
21
+ {
22
+ "Id" => "xadesSignedProperties"
23
+ }
24
+ end
25
+
26
+ def elements
27
+ [
28
+ ZATCA::UBL::Signing::SignedSignatureProperties.new(
29
+ signing_time: @signing_time,
30
+ cert_digest_value: @cert_digest_value,
31
+ cert_issuer_name: @cert_issuer_name,
32
+ cert_serial_number: @cert_serial_number
33
+ )
34
+ ]
35
+ end
36
+
37
+ def generate_hash
38
+ ZATCA::Hashing.generate_hashes(zatca_whitespaced_xml_for_hashing)[:hexdigest_base64]
39
+ end
40
+
41
+ private
42
+
43
+ # rubocop:disable Layout/HeredocIndentation
44
+ # rubocop:disable Layout/ClosingHeredocIndentation
45
+ #
46
+ # We need this version of the XML with this exact whitespacing because ZATCA
47
+ # did not opt for canonicalization before hashing (unlike the invoice hash),
48
+ # and also because they have XML attributes that are only added the moment you
49
+ # generate the hash but are expected to be removed in all other instances.
50
+ #
51
+ # We will use this version of the XML to generate the hash only, and expect
52
+ # the output of `build_xml` to generate the non-signing version of the XML.
53
+ # See:
54
+ # - https://zatca1.discourse.group/t/what-do-signed-properties-look-like-when-hashing
55
+ # - https://web.archive.org/web/20230925182417/https://zatca1.discourse.group/t/what-do-signed-properties-look-like-when-hashing/717
56
+
57
+ def zatca_whitespaced_xml_for_hashing
58
+ # Note: chomp is used to get rid of the final newline character
59
+ <<-XML.chomp
60
+ <xades:SignedProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="xadesSignedProperties">
61
+ <xades:SignedSignatureProperties>
62
+ <xades:SigningTime>#{@signing_time}</xades:SigningTime>
63
+ <xades:SigningCertificate>
64
+ <xades:Cert>
65
+ <xades:CertDigest>
66
+ <ds:DigestMethod xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
67
+ <ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">#{@cert_digest_value}</ds:DigestValue>
68
+ </xades:CertDigest>
69
+ <xades:IssuerSerial>
70
+ <ds:X509IssuerName xmlns:ds="http://www.w3.org/2000/09/xmldsig#">#{@cert_issuer_name}</ds:X509IssuerName>
71
+ <ds:X509SerialNumber xmlns:ds="http://www.w3.org/2000/09/xmldsig#">#{@cert_serial_number}</ds:X509SerialNumber>
72
+ </xades:IssuerSerial>
73
+ </xades:Cert>
74
+ </xades:SigningCertificate>
75
+ </xades:SignedSignatureProperties>
76
+ </xades:SignedProperties>
77
+ XML
78
+ end
79
+ # rubocop:enable Layout/HeredocIndentation
80
+ # rubocop:enable Layout/ClosingHeredocIndentation
81
+ end
@@ -0,0 +1,23 @@
1
+ class ZATCA::UBL::Signing::SignedSignatureProperties < ZATCA::UBL::BaseComponent
2
+ def initialize(signing_time:, cert_digest_value:, cert_issuer_name:, cert_serial_number:)
3
+ super()
4
+
5
+ @signing_time = signing_time
6
+ @cert_digest_value = cert_digest_value
7
+ @cert_issuer_name = cert_issuer_name
8
+ @cert_serial_number = cert_serial_number
9
+ end
10
+
11
+ def name
12
+ "xades:SignedSignatureProperties"
13
+ end
14
+
15
+ def elements
16
+ [
17
+ ZATCA::UBL::BaseComponent.new(name: "xades:SigningTime", value: @signing_time),
18
+ ZATCA::UBL::BaseComponent.new(name: "xades:SigningCertificate", elements: [
19
+ ZATCA::UBL::Signing::Cert.new(cert_digest_value: @cert_digest_value, cert_issuer_name: @cert_issuer_name, cert_serial_number: @cert_serial_number)
20
+ ])
21
+ ]
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ class ZATCA::UBL::Signing::UBLDocumentSignatures < ZATCA::UBL::BaseComponent
2
+ def initialize(signature:)
3
+ super()
4
+
5
+ @signature = signature
6
+ end
7
+
8
+ def name
9
+ "sig:UBLDocumentSignatures"
10
+ end
11
+
12
+ def attributes
13
+ {
14
+ "xmlns:sig" => "urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2",
15
+ "xmlns:sac" => "urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2",
16
+ "xmlns:sbc" => "urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2"
17
+ }
18
+ end
19
+
20
+ def elements
21
+ [
22
+ ZATCA::UBL::Signing::SignatureInformation.new(signature: @signature)
23
+ ]
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ class ZATCA::UBL::Signing::UBLExtension < ZATCA::UBL::BaseComponent
2
+ def initialize(signature:)
3
+ super()
4
+
5
+ @signature = signature
6
+ end
7
+
8
+ def name
9
+ "ext:UBLExtension"
10
+ end
11
+
12
+ def elements
13
+ [
14
+ ZATCA::UBL::BaseComponent.new(name: "ext:ExtensionURI", value: "urn:oasis:names:specification:ubl:dsig:enveloped:xades"),
15
+ ZATCA::UBL::BaseComponent.new(name: "ext:ExtensionContent", elements: [
16
+ ZATCA::UBL::Signing::UBLDocumentSignatures.new(signature: @signature)
17
+ ])
18
+ ]
19
+ end
20
+
21
+ private
22
+ end
@@ -0,0 +1,17 @@
1
+ class ZATCA::UBL::Signing::UBLExtensions < ZATCA::UBL::BaseComponent
2
+ def initialize(signature:)
3
+ super()
4
+
5
+ @signature = signature
6
+ end
7
+
8
+ def name
9
+ "ext:UBLExtensions"
10
+ end
11
+
12
+ def elements
13
+ [
14
+ ZATCA::UBL::Signing::UBLExtension.new(signature: @signature)
15
+ ]
16
+ end
17
+ end
@@ -0,0 +1,2 @@
1
+ module ZATCA::UBL::Signing
2
+ end
data/lib/zatca/ubl.rb ADDED
@@ -0,0 +1,2 @@
1
+ module ZATCA::UBL
2
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ZATCA
4
+ VERSION = "1.1.0"
5
+ end
data/lib/zatca.rb ADDED
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "zatca/version"
4
+ require_relative "zatca/types"
5
+
6
+ require "active_support/all"
7
+ require "zeitwerk"
8
+ require "dry-initializer"
9
+ require "dry-types"
10
+
11
+ loader = Zeitwerk::Loader.for_gem
12
+ loader.inflector.inflect(
13
+ "zatca" => "ZATCA",
14
+ "qr_code_generator" => "QRCodeGenerator",
15
+ "qr_code_extractor" => "QRCodeExtractor",
16
+ "ubl" => "UBL",
17
+ "csr" => "CSR",
18
+ "ubl_document_signature" => "UBLDocumentSignature",
19
+ "ubl_document_signatures" => "UBLDocumentSignatures",
20
+ "ubl_extension" => "UBLExtension",
21
+ "ubl_extensions" => "UBLExtensions",
22
+ "id" => "ID",
23
+ "ecdsa" => "ECDSA"
24
+ )
25
+ loader.setup
26
+
27
+ module ZATCA
28
+ extend self
29
+
30
+ class Error < StandardError; end
31
+
32
+ def self.extract_qr_base64_from_base64_invoice(base64_invoice)
33
+ QRCodeExtractor.new(invoice_base64: base64_invoice).extract
34
+ end
35
+
36
+ def self.render_qr_code(tags: nil, base64: nil)
37
+ if tags.present?
38
+ tags = ZATCA::Tags.new(tags) if tags.is_a?(Hash)
39
+ QRCodeGenerator.new(tags: tags).render
40
+ elsif base64.present?
41
+ QRCodeGenerator.new(base64: base64).render
42
+ else
43
+ raise ArgumentError, "Either tags or base64 must be provided"
44
+ end
45
+ end
46
+ end
47
+
48
+ loader.eager_load
data/zatca_sdk.gemspec ADDED
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/zatca/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "zatca-sdk"
7
+ spec.version = ZATCA::VERSION
8
+ spec.authors = ["Omar Bahareth"]
9
+ spec.email = ["omar@omar.engineer"]
10
+
11
+ spec.summary = "A library for generating QR Codes for the e-invoice standard by ZATCA in Saudi Arabia."
12
+ spec.description = "A library for generating QR Codes for the e-invoice standard by ZATCA in Saudi Arabia."
13
+ spec.homepage = "https://github.com/obahareth/zatca"
14
+ spec.required_ruby_version = ">= 2.5.0"
15
+
16
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/obahareth/zatca"
20
+ spec.metadata["changelog_uri"] = "https://github.com/obahareth/zatca/releases"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features|einvoicing-sdk)/|\.(?:git|travis|circleci)|appveyor)})
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ # Dependencies
34
+ spec.add_dependency "zeitwerk", "~> 2.4"
35
+ spec.add_dependency "dry-schema", ">= 1.5"
36
+ spec.add_dependency "rqrcode", "~> 2.1.0"
37
+ spec.add_dependency "httpx", "~> 0.21.0"
38
+ spec.add_dependency "nokogiri", ">= 1.12"
39
+ spec.add_dependency "activesupport", ">= 5.2"
40
+ spec.add_dependency "dry-initializer", ">= 3.0"
41
+ spec.add_dependency "starkbank-ecdsa", "~> 2.0"
42
+
43
+ # Development Dependencies
44
+ spec.add_development_dependency "standard", "~> 1.3"
45
+ spec.add_development_dependency "byebug", "~> 9.0"
46
+ spec.add_development_dependency "rspec", "~> 3.10"
47
+ spec.add_development_dependency "vcr", "~> 6.0.0"
48
+ spec.add_development_dependency "webmock", "~> 3.18.1"
49
+ spec.add_development_dependency "amazing_print", "~> 1.4.0"
50
+ # For more information and examples about making a new gem, checkout our
51
+ # guide at: https://bundler.io/guides/creating_gem.html
52
+ end