sat_mx 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1d5bf99d58cf85c782f3b4154b95ec56f8e3dcc1d3b8081d5199052e43decb9
4
- data.tar.gz: 3e2b16a973bebaddec739002feaa9bfe144d276bdb3ca81d3d57a84e903f3af6
3
+ metadata.gz: ecf0432037eb033ade4de9f89e9d9edfcd4a7174391758d2c1dc47c5771e44b0
4
+ data.tar.gz: 0aaf19d6965d16cc6c28047964fe4d00be5c925e9cc921f37f3e86985f50993e
5
5
  SHA512:
6
- metadata.gz: 8e29de979da7288e094a4f668d2944c8b4af02193a9c85912101edd383cfc7494bb03074b4f3ed5e4fd103d2d09e5a76a8b0fb558f087a3bf93610ecb2e27490
7
- data.tar.gz: 9dbc83b0df6d6af8d2c06296fb727ca19566d3bded5b3d77f949a048f36b60024bfdcb3aa50cafc4150f664f5df0ca4d4b5a24c7b1235e47239aedf7aeb4ecf2
6
+ metadata.gz: 21ce855b92d37223820e13056c03468880473bd0a791987d2ba8adc65c7d6da11f5f058a52a7d2f3ca26b1cd4d2434c1308cd9e3f10235add7d6ab9a1b7c5a98
7
+ data.tar.gz: 8a5b7724f51b3698d1a71b15da5e75fa905082ce7b631d261e2c20fec9f0cc47fb4ea4f2992012437afc94759ae419b34b4aa565f79bace0ca1f8632eed97084
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "bundler/gem_tasks"
4
2
  require "rspec/core/rake_task"
5
3
 
@@ -1,43 +1,38 @@
1
- require "openssl"
2
1
  require "httpx"
3
- require "xmldsig"
4
2
  require "time"
3
+ require "base64"
5
4
 
6
5
  module SatMx
7
- Result = Data.define(:success?, :value)
8
-
9
- class BulkDownload
10
- AUTH_URL = "https://cfdidescargamasivasolicitud.clouda.sat.gob.mx/Autenticacion/Autenticacion.svc".freeze
11
- HEADERS = {
12
- "content-type" => "text/xml; charset=utf-8",
13
- "accept" => "text/xml",
14
- "SOAPAction" => "http://DescargaMasivaTerceros.gob.mx/IAutenticacion/Autentica"
15
- }.freeze
16
- private_constant :AUTH_URL
17
- private_constant :HEADERS
18
-
19
- def self.authenticate(certificate:, private_key:, id: nil)
6
+ class Authentication
7
+ def self.authenticate(certificate:, private_key:, uuid: SecureRandom.uuid)
20
8
  new(
21
- xml_auth_body: XmlAuthBody.new(certificate:, private_key:, id:)
9
+ xml_auth_body: XmlAuthBody.new(
10
+ certificate:,
11
+ uuid:
12
+ ),
13
+ client: Client.new(
14
+ private_key:,
15
+ access_token: ""
16
+ )
22
17
  ).authenticate
23
18
  end
24
19
 
25
- def initialize(xml_auth_body:)
20
+ def initialize(xml_auth_body:, client:)
26
21
  @xml_auth_body = xml_auth_body
22
+ @client = client
27
23
  end
28
24
 
29
25
  def authenticate
30
- response = HTTPX.post(
31
- AUTH_URL,
32
- headers: HEADERS,
33
- body: xml_auth_body.sign
34
- )
26
+ response = client.authenticate(xml_auth_body.generate)
35
27
 
36
28
  case response.status
37
29
  when 200..299
38
- Result.new(success?: true, value: response.xml)
30
+ Result.new(success?: true,
31
+ value: response.xml.xpath("//xmlns:AutenticaResult",
32
+ xmlns: "http://DescargaMasivaTerceros.gob.mx").inner_text,
33
+ xml: response.xml)
39
34
  when 400..599
40
- Result.new(success?: false, value: response.xml)
35
+ Result.new(success?: false, value: nil, xml: response.xml)
41
36
  else
42
37
  SatMx::Error
43
38
  end
@@ -45,39 +40,28 @@ module SatMx
45
40
 
46
41
  private
47
42
 
48
- attr_reader :xml_auth_body
43
+ attr_reader :xml_auth_body, :client
49
44
  end
50
45
 
51
46
  class XmlAuthBody
52
- def initialize(certificate:, private_key:, id: "uuid-#{SecureRandom.uuid}-1")
47
+ def initialize(certificate:, uuid:)
53
48
  @certificate = certificate
54
- @private_key = private_key
55
- @id = id
49
+ @uuid = uuid
56
50
  end
57
51
 
58
- def sign
59
- Xmldsig::SignedDocument.new(xml_document).sign do |data|
60
- private_key.sign(OpenSSL::Digest.new("SHA1"), data)
61
- end
62
- end
63
-
64
- private
65
-
66
- attr_reader :private_key, :certificate, :id
67
-
68
- def xml_document
52
+ def generate
69
53
  <<~XML
70
54
  <S11:Envelope xmlns:S11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
71
55
  <S11:Header>
72
56
  <wsse:Security S11:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
73
57
  #{timestamp}
74
- <wsse:BinarySecurityToken wsu:Id="#{id}" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">#{Base64.strict_encode64(certificate.to_der)}</wsse:BinarySecurityToken>
58
+ <wsse:BinarySecurityToken wsu:Id="#{uuid}" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">#{Base64.strict_encode64(certificate.to_der)}</wsse:BinarySecurityToken>
75
59
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
76
60
  #{signed_info}
77
61
  <SignatureValue></SignatureValue>
78
62
  <KeyInfo>
79
63
  <wsse:SecurityTokenReference>
80
- <wsse:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="##{id}" />
64
+ <wsse:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="##{uuid}" />
81
65
  </wsse:SecurityTokenReference>
82
66
  </KeyInfo>
83
67
  </Signature>
@@ -90,6 +74,10 @@ module SatMx
90
74
  XML
91
75
  end
92
76
 
77
+ private
78
+
79
+ attr_reader :certificate
80
+
93
81
  def timestamp
94
82
  current_time = Time.now.utc
95
83
  <<~XML
@@ -115,5 +103,9 @@ module SatMx
115
103
  </SignedInfo>
116
104
  XML
117
105
  end
106
+
107
+ def uuid
108
+ "uuid-#{@uuid}-1"
109
+ end
118
110
  end
119
111
  end
@@ -0,0 +1,65 @@
1
+ require "base64"
2
+
3
+ module SatMx
4
+ module Body
5
+ S11 = "S11"
6
+ XMLNS = "xmlns"
7
+ DES = "des"
8
+ DS = "ds"
9
+
10
+ ENVELOPE_ATTRS = {
11
+ "#{XMLNS}:#{S11}" => "http://schemas.xmlsoap.org/soap/envelope/",
12
+ "#{XMLNS}:#{DES}" => "http://DescargaMasivaTerceros.sat.gob.mx",
13
+ "#{XMLNS}:#{DS}" => "http://www.w3.org/2000/09/xmldsig#"
14
+ }.freeze
15
+
16
+ NAMESPACE = ENVELOPE_ATTRS["#{XMLNS}:#{DES}"]
17
+
18
+ private
19
+
20
+ def envelope
21
+ Nokogiri::XML::Builder.new do |xml|
22
+ xml[S11].Envelope(
23
+ ENVELOPE_ATTRS
24
+ ) do
25
+ xml[S11].Header
26
+ xml[S11].Body do
27
+ yield xml
28
+ end
29
+ end
30
+ end.doc.root.to_xml
31
+ end
32
+
33
+ def signature(xml)
34
+ xml.Signature(XMLNS => "http://www.w3.org/2000/09/xmldsig#") do
35
+ xml.SignedInfo do
36
+ xml.CanonicalizationMethod("Algorithm" => "http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
37
+ xml.SignatureMethod("Algorithm" => "http://www.w3.org/2000/09/xmldsig#rsa-sha1")
38
+ xml.Reference("URI" => "") do
39
+ xml.Transforms do
40
+ xml.Transform("Algorithm" => "http://www.w3.org/2000/09/xmldsig#enveloped-signature")
41
+ end
42
+ xml.DigestMethod("Algorithm" => "http://www.w3.org/2000/09/xmldsig#sha1")
43
+ xml.DigestValue
44
+ end
45
+ end
46
+ xml.SignatureValue
47
+ xml.KeyInfo do
48
+ xml.X509Data do
49
+ xml.X509IssuerSerial do
50
+ xml.X509IssuerName(certificate_issuer)
51
+ xml.X509SerialNumber(certificate_serial)
52
+ end
53
+ xml.X509Certificate(encoded_certificate)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ def certificate_issuer = certificate.issuer.to_s(OpenSSL::X509::Name::RFC2253)
60
+
61
+ def certificate_serial = certificate.serial
62
+
63
+ def encoded_certificate = Base64.strict_encode64(certificate.to_der)
64
+ end
65
+ end
@@ -0,0 +1,69 @@
1
+ module SatMx
2
+ class Client
3
+ HEADERS = {
4
+ "content-type" => "text/xml; charset=utf-8",
5
+ "accept" => "text/xml"
6
+ }.freeze
7
+ private_constant :HEADERS
8
+
9
+ def initialize(private_key:, access_token:)
10
+ @private_key = private_key
11
+ @access_token = access_token
12
+ end
13
+
14
+ def authenticate(payload)
15
+ HTTPX.post(
16
+ "https://cfdidescargamasivasolicitud.clouda.sat.gob.mx/Autenticacion/Autenticacion.svc",
17
+ headers: {
18
+ "SOAPAction" => "http://DescargaMasivaTerceros.gob.mx/IAutenticacion/Autentica"
19
+ }.merge(HEADERS),
20
+ body: sign(payload)
21
+ )
22
+ end
23
+
24
+ def download_request(payload)
25
+ HTTPX.post(
26
+ "https://cfdidescargamasivasolicitud.clouda.sat.gob.mx/SolicitaDescargaService.svc",
27
+ headers: {
28
+ "SOAPAction" => "http://DescargaMasivaTerceros.sat.gob.mx/ISolicitaDescargaService/SolicitaDescarga"
29
+ }.merge(authorization)
30
+ .merge(HEADERS),
31
+ body: sign(payload)
32
+ )
33
+ end
34
+
35
+ def verify_request(payload)
36
+ HTTPX.post(
37
+ "https://cfdidescargamasivasolicitud.clouda.sat.gob.mx/VerificaSolicitudDescargaService.svc",
38
+ headers: {
39
+ "SOAPAction" => "http://DescargaMasivaTerceros.sat.gob.mx/IVerificaSolicitudDescargaService/VerificaSolicitudDescarga"
40
+ }.merge(authorization)
41
+ .merge(HEADERS),
42
+ body: sign(payload)
43
+ )
44
+ end
45
+
46
+ def download_petition(payload)
47
+ HTTPX.post(
48
+ "https://cfdidescargamasiva.clouda.sat.gob.mx/DescargaMasivaService.svc",
49
+ headers: {
50
+ "SOAPAction" => "http://DescargaMasivaTerceros.sat.gob.mx/IDescargaMasivaTercerosService/Descargar"
51
+ }.merge(authorization)
52
+ .merge(HEADERS),
53
+ body: sign(payload)
54
+ )
55
+ end
56
+
57
+ private
58
+
59
+ attr_reader :private_key, :access_token
60
+
61
+ def authorization
62
+ {"Authorization" => "WRAP access_token=\"#{access_token}\""}
63
+ end
64
+
65
+ def sign(payload)
66
+ Signer.sign(document: payload, private_key:)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,13 @@
1
+ module SatMx
2
+ Configuration = Data.define(:certificate, :private_key) do
3
+ def initialize(certificate:, private_key:, password:)
4
+ super(
5
+ certificate: OpenSSL::X509::Certificate.new(File.read(certificate)),
6
+ private_key: OpenSSL::PKey::RSA.new(
7
+ File.read(private_key),
8
+ password
9
+ )
10
+ )
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,64 @@
1
+ module SatMx
2
+ class DownloadPetition
3
+ def self.call(package_id:, requester_rfc:, access_token:, certificate:, private_key:)
4
+ new(
5
+ body: DownloadPetitionBody.new(
6
+ package_id:,
7
+ requester_rfc:,
8
+ certificate:
9
+ ),
10
+ client: Client.new(private_key:, access_token:)
11
+ ).call
12
+ end
13
+
14
+ def initialize(body:, client:)
15
+ @body = body
16
+ @client = client
17
+ end
18
+
19
+ def call
20
+ response = client.download_petition(body.generate)
21
+
22
+ case response.status
23
+ when 200..299
24
+ xml = response.xml
25
+ response_tag = xml.xpath(
26
+ "//xmlns:respuesta",
27
+ xmlns: "http://DescargaMasivaTerceros.sat.gob.mx"
28
+ )[0]
29
+
30
+ if response_tag["CodEstatus"] == "5000"
31
+ Result.new(
32
+ success?: true,
33
+ xml: response.xml,
34
+ value: response.xml.xpath(
35
+ "//xmlns:Paquete",
36
+ xmlns: "http://DescargaMasivaTerceros.sat.gob.mx"
37
+ ).inner_text
38
+ )
39
+ else
40
+ Result.new(
41
+ success?: false,
42
+ xml: response.xml,
43
+ value: {
44
+ CodEstatus: response_tag["CodEstatus"],
45
+ Mensaje: response_tag["Mensaje"]
46
+ }
47
+ )
48
+ end
49
+ when 400..599
50
+ Result.new(
51
+ success?: false,
52
+ xml: nil,
53
+ value: nil
54
+ )
55
+ else
56
+ SatMx::Error
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :client, :body
63
+ end
64
+ end
@@ -0,0 +1,28 @@
1
+ module SatMx
2
+ class DownloadPetitionBody
3
+ include Body
4
+
5
+ def initialize(package_id:, requester_rfc:, certificate:)
6
+ @package_id = package_id
7
+ @requester_rfc = requester_rfc
8
+ @certificate = certificate
9
+ end
10
+
11
+ def generate
12
+ envelope do |xml|
13
+ xml[Body::DES].PeticionDescargaMasivaTercerosEntrada do
14
+ xml[Body::DES].peticionDescarga(
15
+ IdPaquete: package_id,
16
+ RfcSolicitante: requester_rfc
17
+ ) do
18
+ signature(xml)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :package_id, :requester_rfc, :certificate
27
+ end
28
+ end
@@ -0,0 +1,67 @@
1
+ module SatMx
2
+ class DownloadRequest
3
+ def self.call(start_date:,
4
+ end_date:,
5
+ request_type:,
6
+ issuing_rfc:,
7
+ recipient_rfcs:,
8
+ requester_rfc:,
9
+ access_token:,
10
+ certificate:,
11
+ private_key:)
12
+ new(
13
+ download_request_body: DownloadRequestBody.new(
14
+ start_date:,
15
+ end_date:,
16
+ request_type:,
17
+ issuing_rfc:,
18
+ recipient_rfcs:,
19
+ requester_rfc:,
20
+ certificate:
21
+ ),
22
+ client: Client.new(private_key:, access_token:)
23
+ ).call
24
+ end
25
+
26
+ def initialize(download_request_body:, client:)
27
+ @download_request_body = download_request_body
28
+ @client = client
29
+ end
30
+
31
+ def call
32
+ response = client.download_request(download_request_body.generate)
33
+
34
+ case response.status
35
+ when 200..299
36
+ check_body_status response.xml
37
+ when 400..599
38
+ Result.new(success?: false, value: nil, xml: response.xml)
39
+ else
40
+ SatMx::Error
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :download_request_body, :client
47
+
48
+ def check_body_status(xml)
49
+ download_result_tag = xml.xpath("//xmlns:SolicitaDescargaResult",
50
+ xmlns: Body::NAMESPACE)
51
+ if download_result_tag.attr("CodEstatus").value == "5000"
52
+ Result.new(success?: true,
53
+ value: download_result_tag.attr("IdSolicitud").value,
54
+ xml: xml)
55
+ else
56
+ Result.new(
57
+ success?: false,
58
+ value: {
59
+ CodEstatus: download_result_tag.attr("CodEstatus").value,
60
+ Mensaje: download_result_tag.attr("Mensaje").value
61
+ },
62
+ xml:
63
+ )
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,59 @@
1
+ require "time"
2
+
3
+ module SatMx
4
+ class DownloadRequestBody
5
+ include Body
6
+
7
+ REQUEST_TYPES = {
8
+ cfdi: "CFDI",
9
+ metadata: "Metadata"
10
+ }.freeze
11
+
12
+ def initialize(start_date:,
13
+ end_date:,
14
+ request_type:,
15
+ issuing_rfc:,
16
+ recipient_rfcs:,
17
+ requester_rfc:,
18
+ certificate:)
19
+ @start_date = start_date
20
+ @end_date = end_date
21
+ @request_type = request_type
22
+ @issuing_rfc = issuing_rfc
23
+ @recipient_rfcs = recipient_rfcs
24
+ @requester_rfc = requester_rfc
25
+ @certificate = certificate
26
+ end
27
+
28
+ def generate
29
+ envelope do |xml|
30
+ xml[Body::DES].SolicitaDescarga do
31
+ xml[Body::DES].solicitud(
32
+ "FechaInicial" => start_date,
33
+ "FechaFinal" => end_date,
34
+ "RfcEmisor" => issuing_rfc,
35
+ "RfcSolicitante" => requester_rfc,
36
+ "TipoSolicitud" => request_type
37
+ ) do
38
+ xml[Body::DES].RfcReceptores do
39
+ @recipient_rfcs.each do |rfc|
40
+ xml[Body::DES].RfcReceptor(rfc)
41
+ end
42
+ end
43
+ signature(xml)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :issuing_rfc, :requester_rfc, :certificate
52
+
53
+ def start_date = @start_date.strftime("%Y-%m-%dT%H:%M:%S")
54
+
55
+ def end_date = @end_date.strftime("%Y-%m-%dT%H:%M:%S")
56
+
57
+ def request_type = REQUEST_TYPES.fetch(@request_type)
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module SatMx
2
+ Result = Data.define(:success?, :value, :xml)
3
+ end
@@ -0,0 +1,25 @@
1
+ require "openssl"
2
+ require "xmldsig"
3
+
4
+ module SatMx
5
+ class Signer
6
+ def self.sign(document:, private_key:)
7
+ new(document:, private_key:).sign
8
+ end
9
+
10
+ def initialize(document:, private_key:)
11
+ @unsigned_document = Xmldsig::SignedDocument.new(document)
12
+ @private_key = private_key
13
+ end
14
+
15
+ def sign
16
+ unsigned_document.sign do |data|
17
+ private_key.sign(OpenSSL::Digest.new("SHA1"), data)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :unsigned_document, :private_key
24
+ end
25
+ end
@@ -0,0 +1,69 @@
1
+ module SatMx
2
+ class VerifyRequest
3
+ STATUS = {
4
+ "1" => :accepted,
5
+ "2" => :in_proccess,
6
+ "3" => :finished,
7
+ "4" => :error,
8
+ "5" => :rejected,
9
+ "6" => :expired
10
+ }
11
+ private_constant :STATUS
12
+
13
+ def self.call(request_id:, requester_rfc:, access_token:, private_key:, certificate:)
14
+ new(
15
+ body: VerifyRequestBody.new(request_id:, requester_rfc:, certificate:),
16
+ client: Client.new(private_key:, access_token:)
17
+ ).call
18
+ end
19
+
20
+ def initialize(body:, client:)
21
+ @body = body
22
+ @client = client
23
+ end
24
+
25
+ def call
26
+ response = client.verify_request(body.generate)
27
+ case response.status
28
+ when 200..299
29
+ check_body_status(response.xml)
30
+ when 400..599
31
+ Result.new(success?: false, value: nil, xml: response.xml)
32
+ else
33
+ SatMx::Error
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :body, :client
40
+
41
+ def check_body_status(xml)
42
+ download_result_tag = xml.xpath("//xmlns:VerificaSolicitudDescargaResult",
43
+ xmlns: Body::NAMESPACE)
44
+ if download_result_tag.attr("CodEstatus").value == "5000"
45
+ Result.new(success?: true,
46
+ value: value(download_result_tag, xml),
47
+ xml: xml)
48
+ else
49
+ Result.new(
50
+ success?: false,
51
+ value: {
52
+ CodEstatus: download_result_tag.attr("CodEstatus").value,
53
+ Mensaje: download_result_tag.attr("Mensaje").value
54
+ },
55
+ xml:
56
+ )
57
+ end
58
+ end
59
+
60
+ def value(tag, xml)
61
+ {
62
+ request_status: STATUS.fetch(
63
+ tag.attribute("EstadoSolicitud").value
64
+ ),
65
+ package_ids: xml.xpath("//xmlns:IdsPaquetes", xmlns: Body::NAMESPACE).map(&:inner_text)
66
+ }
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,28 @@
1
+ module SatMx
2
+ class VerifyRequestBody
3
+ include Body
4
+
5
+ def initialize(certificate:, request_id:, requester_rfc:)
6
+ @certificate = certificate
7
+ @request_id = request_id
8
+ @requester_rfc = requester_rfc
9
+ end
10
+
11
+ def generate
12
+ envelope do |xml|
13
+ xml[Body::DES].VerificaSolicitudDescarga do
14
+ xml[Body::DES].solicitud(
15
+ "IdSolicitud" => request_id,
16
+ "RfcSolicitante" => requester_rfc
17
+ ) do
18
+ signature(xml)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :certificate, :request_id, :requester_rfc
27
+ end
28
+ end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module SatMx
4
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
5
3
  end
data/lib/sat_mx.rb CHANGED
@@ -1,8 +1,63 @@
1
- # frozen_string_literal: true
2
-
1
+ require "httpx"
3
2
  require_relative "sat_mx/version"
4
3
 
5
4
  module SatMx
6
5
  class Error < StandardError; end
7
- autoload(:BulkDownload, "sat_mx/bulk_download")
6
+ autoload(:Configuration, "sat_mx/configuration")
7
+ autoload(:Authentication, "sat_mx/authentication")
8
+ autoload(:DownloadRequest, "sat_mx/download_request")
9
+ autoload(:DownloadRequestBody, "sat_mx/download_request_body")
10
+ autoload(:VerifyRequest, "sat_mx/verify_request")
11
+ autoload(:VerifyRequestBody, "sat_mx/verify_request_body")
12
+ autoload(:DownloadPetition, "sat_mx/download_petition")
13
+ autoload(:DownloadPetitionBody, "sat_mx/download_petition_body")
14
+ autoload(:Body, "sat_mx/body")
15
+ autoload(:Result, "sat_mx/result")
16
+ autoload(:Signer, "sat_mx/signer")
17
+ autoload(:Client, "sat_mx/client")
18
+
19
+ class << self
20
+ # Configures the gem using a block, its not threadsafe, so its recommended call only when you're initializing
21
+ # your application, e.g. in your initializers directory of your rails app
22
+ # @example
23
+ # SatMx.configure do |config|
24
+ # config[:certificate] = "path/to/certificate.cer"
25
+ # config[:private_key] = "path/to/private.key"
26
+ # config[:password] = "key_password"
27
+ # end
28
+ def configure
29
+ config = {}
30
+ yield(config)
31
+ @configuration = Configuration.new(**config)
32
+ end
33
+
34
+ def configuration
35
+ @configuration ||= Configuration.new
36
+ end
37
+
38
+ # Authenticates with the SAT web service using the configured certificate and private key.
39
+ # This method uses SOAP to communicate with the SAT authentication service and returns
40
+ # a token that can be used for subsequent requests.
41
+ #
42
+ # result = SatMx.authenticate
43
+ # if result.success?
44
+ # puts "Authentication token: #{result.value}"
45
+ # else
46
+ # puts "Authentication failed"
47
+ # end
48
+ #
49
+ # @return [SatMx::Result] A Result object containing:
50
+ # - success?: [Boolean] whether the authentication was successful
51
+ # - value: [String, nil] the authentication token if successful, nil otherwise
52
+ # - xml: [Nokogiri::XML::Document] the raw XML response from the service
53
+ #
54
+ # @see SatMx::Authentication
55
+ # @see SatMx::Result
56
+ def authenticate
57
+ Authentication.authenticate(
58
+ certificate: configuration.certificate,
59
+ private_key: configuration.private_key
60
+ )
61
+ end
62
+ end
8
63
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sat_mx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Rivas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-03 00:00:00.000000000 Z
11
+ date: 2025-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: xmldsig
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: base64
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: '1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "<"
53
+ - !ruby/object:Gem::Version
54
+ version: '1'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: standard
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -109,7 +123,18 @@ files:
109
123
  - README.md
110
124
  - Rakefile
111
125
  - lib/sat_mx.rb
112
- - lib/sat_mx/bulk_download.rb
126
+ - lib/sat_mx/authentication.rb
127
+ - lib/sat_mx/body.rb
128
+ - lib/sat_mx/client.rb
129
+ - lib/sat_mx/configuration.rb
130
+ - lib/sat_mx/download_petition.rb
131
+ - lib/sat_mx/download_petition_body.rb
132
+ - lib/sat_mx/download_request.rb
133
+ - lib/sat_mx/download_request_body.rb
134
+ - lib/sat_mx/result.rb
135
+ - lib/sat_mx/signer.rb
136
+ - lib/sat_mx/verify_request.rb
137
+ - lib/sat_mx/verify_request_body.rb
113
138
  - lib/sat_mx/version.rb
114
139
  - sig/sat_mx.rbs
115
140
  homepage: https://github.com/kadru/sat_mx
@@ -133,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
158
  - !ruby/object:Gem::Version
134
159
  version: '0'
135
160
  requirements: []
136
- rubygems_version: 3.5.11
161
+ rubygems_version: 3.5.23
137
162
  signing_key:
138
163
  specification_version: 4
139
164
  summary: a client to connect to SAT web services