sat_mx 0.3.0 → 0.4.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 +4 -4
- data/README.md +6 -5
- data/lib/sat_mx/client.rb +11 -0
- data/lib/sat_mx/download_request_received.rb +110 -0
- data/lib/sat_mx/download_request_received_body.rb +112 -0
- data/lib/sat_mx/version.rb +1 -1
- data/lib/sat_mx.rb +67 -0
- metadata +5 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6f23a9065a4facc1ea12963a7a27587c8055775cbb729e3070c0a5a2a8144cd
|
|
4
|
+
data.tar.gz: c043c861ed94a4cb049b3664f37b6a3b13e502917e28dd7b6f07608f15212485
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a4ca5be6421a81e686b084207556f320fc4294d0d9731d9febd8e4d303a49bf10dcbfde496d86d2a8eef72fb172d69b7948ae2812e79f9c950d6749e038c8d8
|
|
7
|
+
data.tar.gz: 6dfb7a7364d74260cb0eb5e804b19b2e113e3fbfd8a5a61baee671e22cb15a109618decae7c7851b941e07901e61b93ec9ba12ede074b736e08fe355717bc227
|
data/README.md
CHANGED
|
@@ -33,14 +33,15 @@ raise "Auth failed" unless result.success?
|
|
|
33
33
|
|
|
34
34
|
token = result.value
|
|
35
35
|
|
|
36
|
-
# 2. Request download
|
|
37
|
-
result = SatMx.
|
|
36
|
+
# 2. Request download of received CFDI
|
|
37
|
+
result = SatMx.download_request_received(
|
|
38
38
|
start_date: Time.new(2024, 1, 1),
|
|
39
39
|
end_date: Time.new(2024, 1, 31),
|
|
40
40
|
request_type: :cfdi,
|
|
41
|
-
|
|
42
|
-
recipient_rfcs: ["XYZ020202XYZ"],
|
|
41
|
+
recipient_rfc: "ABC010101ABC",
|
|
43
42
|
requester_rfc: "ABC010101ABC",
|
|
43
|
+
issuing_rfc: "XYZ020202XYZ",
|
|
44
|
+
document_status: "Vigente",
|
|
44
45
|
access_token: token
|
|
45
46
|
)
|
|
46
47
|
raise "Request failed" unless result.success?
|
|
@@ -84,7 +85,7 @@ end
|
|
|
84
85
|
| `SatMx.configure` | Configure certificate and private key |
|
|
85
86
|
| `SatMx.configuration` | Get current configuration |
|
|
86
87
|
| `SatMx.authenticate` | Get access token |
|
|
87
|
-
| `SatMx.
|
|
88
|
+
| `SatMx.download_request_received` | Request download of received CFDI |
|
|
88
89
|
| `SatMx.verify_request` | Check request status |
|
|
89
90
|
| `SatMx.download_petition` | Download package |
|
|
90
91
|
|
data/lib/sat_mx/client.rb
CHANGED
|
@@ -33,6 +33,17 @@ module SatMx
|
|
|
33
33
|
)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def download_request_received(payload)
|
|
37
|
+
HTTPX.post(
|
|
38
|
+
"https://cfdidescargamasivasolicitud.clouda.sat.gob.mx/SolicitaDescargaService.svc",
|
|
39
|
+
headers: {
|
|
40
|
+
"SOAPAction" => "http://DescargaMasivaTerceros.sat.gob.mx/ISolicitaDescargaService/SolicitaDescargaRecibidos"
|
|
41
|
+
}.merge(authorization)
|
|
42
|
+
.merge(HEADERS),
|
|
43
|
+
body: sign(payload)
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
36
47
|
def verify_request(payload)
|
|
37
48
|
HTTPX.post(
|
|
38
49
|
"https://cfdidescargamasivasolicitud.clouda.sat.gob.mx/VerificaSolicitudDescargaService.svc",
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require_relative "body"
|
|
2
|
+
|
|
3
|
+
module SatMx
|
|
4
|
+
# @api private
|
|
5
|
+
class DownloadRequestReceived
|
|
6
|
+
def self.call(start_date:,
|
|
7
|
+
end_date:,
|
|
8
|
+
request_type:,
|
|
9
|
+
recipient_rfc:,
|
|
10
|
+
access_token:,
|
|
11
|
+
certificate:,
|
|
12
|
+
private_key:,
|
|
13
|
+
requester_rfc: nil,
|
|
14
|
+
issuing_rfc: nil,
|
|
15
|
+
complement: nil,
|
|
16
|
+
document_status: nil)
|
|
17
|
+
new(
|
|
18
|
+
download_request_received_body: DownloadRequestReceivedBody.new(
|
|
19
|
+
start_date:,
|
|
20
|
+
end_date:,
|
|
21
|
+
request_type:,
|
|
22
|
+
recipient_rfc:,
|
|
23
|
+
requester_rfc:,
|
|
24
|
+
certificate:,
|
|
25
|
+
issuing_rfc:,
|
|
26
|
+
complement:,
|
|
27
|
+
document_status:
|
|
28
|
+
),
|
|
29
|
+
client: Client.new(private_key:, access_token:)
|
|
30
|
+
).call
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def initialize(download_request_received_body:, client:)
|
|
34
|
+
@download_request_received_body = download_request_received_body
|
|
35
|
+
@client = client
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def call
|
|
39
|
+
if (validation_error = validate_complement!)
|
|
40
|
+
return validation_error
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if (validation_error = validate_document_status!)
|
|
44
|
+
return validation_error
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
response = client.download_request_received(download_request_received_body.generate)
|
|
48
|
+
|
|
49
|
+
case response.status
|
|
50
|
+
when 200..299
|
|
51
|
+
check_body_status response.xml
|
|
52
|
+
when 400..599
|
|
53
|
+
Result.new(success?: false, value: nil, xml: response.xml)
|
|
54
|
+
else
|
|
55
|
+
Error
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
attr_reader :download_request_received_body, :client
|
|
62
|
+
|
|
63
|
+
def validate_complement!
|
|
64
|
+
complement = download_request_received_body.complement
|
|
65
|
+
return unless complement
|
|
66
|
+
return if DownloadRequestReceivedBody::COMPLEMENT_TYPES.include?(complement)
|
|
67
|
+
|
|
68
|
+
Result.new(
|
|
69
|
+
success?: false,
|
|
70
|
+
value: {cod_estatus: "INVALID_COMPLEMENT", mensaje: "Invalid complement type: #{complement}"},
|
|
71
|
+
xml: nil
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def validate_document_status!
|
|
76
|
+
document_status = download_request_received_body.document_status
|
|
77
|
+
return unless document_status
|
|
78
|
+
return if DownloadRequestReceivedBody::DOCUMENT_STATUS.include?(document_status)
|
|
79
|
+
|
|
80
|
+
Result.new(
|
|
81
|
+
success?: false,
|
|
82
|
+
value: {cod_estatus: "INVALID_DOCUMENT_STATUS", mensaje: "Invalid document status: #{document_status}"},
|
|
83
|
+
xml: nil
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def check_body_status(xml)
|
|
88
|
+
download_result_tag = xml.xpath(
|
|
89
|
+
"//xmlns:SolicitaDescargaRecibidosResult",
|
|
90
|
+
xmlns: Body::NAMESPACE
|
|
91
|
+
)
|
|
92
|
+
if download_result_tag.attr("CodEstatus").value == "5000"
|
|
93
|
+
Result.new(
|
|
94
|
+
success?: true,
|
|
95
|
+
value: download_result_tag.attr("IdSolicitud").value,
|
|
96
|
+
xml:
|
|
97
|
+
)
|
|
98
|
+
else
|
|
99
|
+
Result.new(
|
|
100
|
+
success?: false,
|
|
101
|
+
value: {
|
|
102
|
+
cod_estatus: download_result_tag.attr("CodEstatus").value,
|
|
103
|
+
mensaje: download_result_tag.attr("Mensaje").value
|
|
104
|
+
},
|
|
105
|
+
xml:
|
|
106
|
+
)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
require "time"
|
|
2
|
+
|
|
3
|
+
module SatMx
|
|
4
|
+
# @api private
|
|
5
|
+
class DownloadRequestReceivedBody
|
|
6
|
+
include Body
|
|
7
|
+
|
|
8
|
+
REQUEST_TYPES = {
|
|
9
|
+
cfdi: "CFDI",
|
|
10
|
+
metadata: "Metadata"
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
DOCUMENT_STATUS = %w[
|
|
14
|
+
Todos
|
|
15
|
+
Cancelado
|
|
16
|
+
Vigente
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
COMPLEMENT_TYPES = %w[
|
|
20
|
+
acreditamientoieps10
|
|
21
|
+
aerolineas
|
|
22
|
+
certificadodedestruccion
|
|
23
|
+
cfdiregistrofiscal
|
|
24
|
+
comercioexterior10
|
|
25
|
+
comercioexterior11
|
|
26
|
+
comprobante
|
|
27
|
+
consumodecombustibles
|
|
28
|
+
consumodecombustibles11
|
|
29
|
+
detallista
|
|
30
|
+
divisas
|
|
31
|
+
donat11
|
|
32
|
+
ecc11
|
|
33
|
+
ecc12
|
|
34
|
+
gastoshidrocarbonos10
|
|
35
|
+
iedu
|
|
36
|
+
implocal
|
|
37
|
+
ine11
|
|
38
|
+
ingresoshidrocarbonos
|
|
39
|
+
leyendasfisc
|
|
40
|
+
nomina11
|
|
41
|
+
nomina12
|
|
42
|
+
notariospublicos
|
|
43
|
+
obrasarteantiguedades
|
|
44
|
+
pagoenespecie
|
|
45
|
+
pagos10
|
|
46
|
+
pfic
|
|
47
|
+
renovacionysustitucionvehiculos
|
|
48
|
+
servicioparcialconstruccion
|
|
49
|
+
spei
|
|
50
|
+
terceros11
|
|
51
|
+
turistapasajeroextranjero
|
|
52
|
+
valesdedespensa
|
|
53
|
+
vehiculousado
|
|
54
|
+
ventavehiculos11
|
|
55
|
+
].freeze
|
|
56
|
+
|
|
57
|
+
def initialize(
|
|
58
|
+
start_date:,
|
|
59
|
+
end_date:,
|
|
60
|
+
request_type:,
|
|
61
|
+
recipient_rfc:,
|
|
62
|
+
requester_rfc:,
|
|
63
|
+
certificate:,
|
|
64
|
+
issuing_rfc: nil,
|
|
65
|
+
complement: nil,
|
|
66
|
+
document_status: nil
|
|
67
|
+
)
|
|
68
|
+
@start_date = start_date
|
|
69
|
+
@end_date = end_date
|
|
70
|
+
@request_type = request_type
|
|
71
|
+
@recipient_rfc = recipient_rfc
|
|
72
|
+
@requester_rfc = requester_rfc
|
|
73
|
+
@certificate = certificate
|
|
74
|
+
@issuing_rfc = issuing_rfc
|
|
75
|
+
@complement = complement
|
|
76
|
+
@document_status = document_status
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def generate
|
|
80
|
+
envelope do |xml|
|
|
81
|
+
xml[Body::DES].SolicitaDescargaRecibidos do
|
|
82
|
+
attrs = {
|
|
83
|
+
"FechaInicial" => start_date,
|
|
84
|
+
"FechaFinal" => end_date,
|
|
85
|
+
"TipoSolicitud" => request_type,
|
|
86
|
+
"RfcReceptor" => recipient_rfc
|
|
87
|
+
}
|
|
88
|
+
attrs["RfcEmisor"] = issuing_rfc if issuing_rfc
|
|
89
|
+
attrs["RfcSolicitante"] = requester_rfc if requester_rfc
|
|
90
|
+
attrs["Complemento"] = complement if complement
|
|
91
|
+
attrs["EstadoComprobante"] = document_status if document_status
|
|
92
|
+
|
|
93
|
+
xml[Body::DES].solicitud(attrs) do
|
|
94
|
+
signature(xml)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
attr_reader :complement, :document_status
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
attr_reader :recipient_rfc, :requester_rfc, :certificate, :issuing_rfc
|
|
105
|
+
|
|
106
|
+
def start_date = @start_date.strftime("%Y-%m-%dT%H:%M:%S")
|
|
107
|
+
|
|
108
|
+
def end_date = @end_date.strftime("%Y-%m-%dT%H:%M:%S")
|
|
109
|
+
|
|
110
|
+
def request_type = REQUEST_TYPES.fetch(@request_type)
|
|
111
|
+
end
|
|
112
|
+
end
|
data/lib/sat_mx/version.rb
CHANGED
data/lib/sat_mx.rb
CHANGED
|
@@ -7,6 +7,8 @@ module SatMx
|
|
|
7
7
|
autoload(:Authentication, "sat_mx/authentication")
|
|
8
8
|
autoload(:DownloadRequest, "sat_mx/download_request")
|
|
9
9
|
autoload(:DownloadRequestBody, "sat_mx/download_request_body")
|
|
10
|
+
autoload(:DownloadRequestReceived, "sat_mx/download_request_received")
|
|
11
|
+
autoload(:DownloadRequestReceivedBody, "sat_mx/download_request_received_body")
|
|
10
12
|
autoload(:VerifyRequest, "sat_mx/verify_request")
|
|
11
13
|
autoload(:VerifyRequestBody, "sat_mx/verify_request_body")
|
|
12
14
|
autoload(:DownloadPetition, "sat_mx/download_petition")
|
|
@@ -115,6 +117,71 @@ module SatMx
|
|
|
115
117
|
)
|
|
116
118
|
end
|
|
117
119
|
|
|
120
|
+
# Requests a download of received CFDI documents from the SAT web service SolicitaDescargaService with SOAPAction SolicitaDescargaRecibidos
|
|
121
|
+
#
|
|
122
|
+
# result = SatMx.download_request_received(
|
|
123
|
+
# start_date: Time.new(2024, 1, 1),
|
|
124
|
+
# end_date: Time.new(2024, 1, 31),
|
|
125
|
+
# request_type: :cfdi,
|
|
126
|
+
# recipient_rfc: "ABC010101ABC",
|
|
127
|
+
# requester_rfc: "ABC010101ABC",
|
|
128
|
+
# access_token: "your_access_token"
|
|
129
|
+
# )
|
|
130
|
+
# if result.success?
|
|
131
|
+
# puts "Request ID: #{result.value}"
|
|
132
|
+
# else
|
|
133
|
+
# puts "Request failed: #{result.value}"
|
|
134
|
+
# end
|
|
135
|
+
#
|
|
136
|
+
# @param start_date [Time] Start date for the search range
|
|
137
|
+
# @param end_date [Time] End date for the search range
|
|
138
|
+
# @param request_type [Symbol] Type of request (:cfdi or :metadata)
|
|
139
|
+
# @param access_token [String] Authentication token from SatMx.authenticate
|
|
140
|
+
# @param recipient_rfc [String] RFC of the receiver (required)
|
|
141
|
+
# @param requester_rfc [String, nil] RFC of the requester (optional)
|
|
142
|
+
# @param issuing_rfc [String, nil] RFC of the issuer (optional)
|
|
143
|
+
# @param complement [String, nil] Complement type to filter (e.g., "nomina12", "pagos10")
|
|
144
|
+
# This value is optional. If omitted, the SAT web service will return all documents.
|
|
145
|
+
# @param document_status [String, nil] Document status filter (Todos, Cancelados, Vigentes) defaults to Todos
|
|
146
|
+
# @param certificate [String, nil] Certificate object (uses configuration if nil)
|
|
147
|
+
# @param private_key [String, nil] Private key object (uses configuration if nil)
|
|
148
|
+
#
|
|
149
|
+
# @return [SatMx::Result] A Result object containing:
|
|
150
|
+
# - success?: [Boolean] whether the request was successful
|
|
151
|
+
# - value: [String, nil] the request ID if successful, or {cod_estatus:, mensaje:} on failure
|
|
152
|
+
# - xml: [Nokogiri::XML::Document] the raw XML response from the service
|
|
153
|
+
#
|
|
154
|
+
# @see SatMx::DownloadRequestReceived
|
|
155
|
+
# @see SatMx::Result
|
|
156
|
+
def download_request_received(
|
|
157
|
+
access_token:,
|
|
158
|
+
start_date:,
|
|
159
|
+
end_date:,
|
|
160
|
+
request_type:,
|
|
161
|
+
recipient_rfc:,
|
|
162
|
+
issuing_rfc: nil,
|
|
163
|
+
requester_rfc: nil,
|
|
164
|
+
document_status: nil,
|
|
165
|
+
complement: nil,
|
|
166
|
+
**options
|
|
167
|
+
)
|
|
168
|
+
certificate = options[:certificate] || configuration.certificate
|
|
169
|
+
private_key = options[:private_key] || configuration.private_key
|
|
170
|
+
DownloadRequestReceived.call(
|
|
171
|
+
start_date:,
|
|
172
|
+
end_date:,
|
|
173
|
+
request_type:,
|
|
174
|
+
recipient_rfc:,
|
|
175
|
+
requester_rfc:,
|
|
176
|
+
issuing_rfc:,
|
|
177
|
+
complement:,
|
|
178
|
+
document_status:,
|
|
179
|
+
access_token:,
|
|
180
|
+
certificate:,
|
|
181
|
+
private_key:
|
|
182
|
+
)
|
|
183
|
+
end
|
|
184
|
+
|
|
118
185
|
# Verifies the status of a previously submitted download request.
|
|
119
186
|
#
|
|
120
187
|
# result = SatMx.verify_request(
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sat_mx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oscar Rivas
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: xmldsig
|
|
@@ -131,6 +130,8 @@ files:
|
|
|
131
130
|
- lib/sat_mx/download_petition_body.rb
|
|
132
131
|
- lib/sat_mx/download_request.rb
|
|
133
132
|
- lib/sat_mx/download_request_body.rb
|
|
133
|
+
- lib/sat_mx/download_request_received.rb
|
|
134
|
+
- lib/sat_mx/download_request_received_body.rb
|
|
134
135
|
- lib/sat_mx/result.rb
|
|
135
136
|
- lib/sat_mx/signer.rb
|
|
136
137
|
- lib/sat_mx/verify_request.rb
|
|
@@ -143,7 +144,6 @@ licenses:
|
|
|
143
144
|
metadata:
|
|
144
145
|
homepage_uri: https://github.com/kadru/sat_mx
|
|
145
146
|
changelog_uri: https://github.com/kadru/sat_mx/CHANGELOG.md
|
|
146
|
-
post_install_message:
|
|
147
147
|
rdoc_options: []
|
|
148
148
|
require_paths:
|
|
149
149
|
- lib
|
|
@@ -158,8 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
159
|
version: '0'
|
|
160
160
|
requirements: []
|
|
161
|
-
rubygems_version:
|
|
162
|
-
signing_key:
|
|
161
|
+
rubygems_version: 4.0.4
|
|
163
162
|
specification_version: 4
|
|
164
163
|
summary: a client to connect to SAT web services
|
|
165
164
|
test_files: []
|