afip.rb 1.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1cc5b723a5764b5bb0e78ed11bb03b06157ef1e334f538f4284e8fea712150fa
4
+ data.tar.gz: d993b725b9d7664c45c59c38c220bcb1a9bc0f5c159b12dca6970c79980c2ebd
5
+ SHA512:
6
+ metadata.gz: 7d526e25cadd6f63f41596ad25453e9323dc4da5cfdf83233ae3a76c7262b8ffb0c86e57aceaf7355fcded889ebe9e8fdd80c5852245508609d1dc0feb2e9c75
7
+ data.tar.gz: 1ce71c5f5a02506ffb7dcb2661e08fd6a55a8b8820a69059c581ce91a4785b6c171ca159bb2879f7a0c485c1ac4ee45aff3fd811ae8dbcd6ec387e248d4c7b23
data/.rubocop.yml ADDED
@@ -0,0 +1,49 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 130
14
+
15
+ Style/RescueStandardError:
16
+ Enabled: false
17
+
18
+ Naming/MethodName:
19
+ Enabled: false
20
+
21
+ Naming/VariableName:
22
+ Enabled: false
23
+
24
+ Metrics/AbcSize:
25
+ Enabled: false
26
+
27
+ Metrics/CyclomaticComplexity:
28
+ Enabled: false
29
+
30
+ Metrics/MethodLength:
31
+ Enabled: false
32
+
33
+ Style/OptionalBooleanParameter:
34
+ Enabled: false
35
+
36
+ Style/Documentation:
37
+ Enabled: false
38
+
39
+ Metrics/PerceivedComplexity:
40
+ Enabled: false
41
+
42
+ Naming/VariableNumber:
43
+ Enabled: false
44
+
45
+ Style/NumericLiterals:
46
+ Enabled: false
47
+
48
+ Metrics/ClassLength:
49
+ Enabled: false
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Ivan Muñoz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ <!-- PROJECT SHIELDS -->
2
+ [![Contributors][contributors-shield]](https://github.com/afipsdk/afip.rb/graphs/contributors)
3
+ [![Closed issues][issues-shield]](https://github.com/afipsdk/afip.rb/issues)
4
+
5
+
6
+ <!-- PROJECT LOGO -->
7
+ <br />
8
+ <p align="center">
9
+ <a href="https://github.com/afipsdk/afip.rb">
10
+ <img src="https://github.com/afipsdk/afipsdk.github.io/blob/master/images/logo-colored.png" alt="Logo" width="130" height="130">
11
+ </a>
12
+
13
+ <h3 align="center">Afip.rb</h3>
14
+
15
+ <p align="center">
16
+ Librería para conectarse a los Web Services de AFIP en Ruby
17
+ <br />
18
+ <a href="https://docs.afipsdk.com"><strong>Explorar documentación »</strong></a>
19
+ <br />
20
+ <br />
21
+ <a href="https://github.com/afipsdk/afip.rb/issues">Reportar un bug</a>
22
+ </p>
23
+ </p>
24
+
25
+
26
+ <!-- DOCS -->
27
+ ## Documentación
28
+ [Explorar documentación](https://docs.afipsdk.com)
29
+
30
+ <!-- ABOUT THE PROJECT -->
31
+ ## Acerca del proyecto
32
+ Con más de 60.000 descargas en sus versiones de PHP, Node y Ruby desde el 2017 Afip SDK es la librería elegida por los desarrolladores para integrar sus plataformas con AFIP.
33
+
34
+ Esta librería fue creada con la intención de ayudar a los programadores a usar los Web Services de AFIP sin romperse la cabeza ni perder tiempo tratando de entender la complicada documentación que AFIP provee.
35
+
36
+ <!-- CONTACT -->
37
+ ### Contacto
38
+ Afip SDK - afipsdk@gmail.com
39
+
40
+ Link del proyecto: [https://github.com/afipsdk/afip.rb](https://github.com/afipsdk/afip.rb)
41
+
42
+
43
+ _Este software y sus desarrolladores no tienen ninguna relación con la AFIP._
44
+
45
+ <!-- MARKDOWN LINKS & IMAGES -->
46
+ [packagist-shield]: https://img.shields.io/packagist/dt/afipsdk/afip.rb.svg??logo=php&?logoColor=white
47
+ [contributors-shield]: https://img.shields.io/github/contributors/afipsdk/afip.rb.svg?color=orange
48
+ [issues-shield]: https://img.shields.io/github/issues-closed-raw/afipsdk/afip.rb.svg?color=blueviolet
49
+ [license-shield]: https://img.shields.io/github/license/afipsdk/afip.rb.svg?color=blue
50
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rubocop/rake_task"
5
+
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: :rubocop
data/afip.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/afip/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "afip.rb"
7
+ spec.version = Afip::VERSION
8
+ spec.authors = ["Afip SDK"]
9
+ spec.email = ["afipsdk@gmail.com"]
10
+
11
+ spec.summary = "Library to connect with AFIP"
12
+ spec.description = "AfipSDK is the easyest way to connect with AFIP"
13
+ spec.homepage = "https://afipsdk.com"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.3.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/AfipSDK/afip.rb"
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(__dir__) do
23
+ `git ls-files -z`.split("\x0").reject do |f|
24
+ (File.expand_path(f) == __FILE__) ||
25
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+
34
+ # For more information and examples about making a new gem, check out our
35
+ # guide at: https://bundler.io/guides/creating_gem.html
36
+ end
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afip
4
+ module WebServices
5
+ class ElectronicBilling < Afip::WebService
6
+ @soapv12 = true
7
+ @WSDL = "https://servicios1.afip.gov.ar/wsfev1/service.asmx?WSDL"
8
+ @URL = "https://servicios1.afip.gov.ar/wsfev1/service.asmx"
9
+ @WSDL_TEST = "https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL"
10
+ @URL_TEST = "https://wswhomo.afip.gov.ar/wsfev1/service.asmx"
11
+
12
+ def initialize(afip)
13
+ super(afip, { "service": "wsfe" })
14
+ end
15
+
16
+ # Create PDF
17
+ def createPDF(data)
18
+ url = URI("https://app.afipsdk.com/api/v1/pdfs")
19
+
20
+ https = Net::HTTP.new(url.host, url.port)
21
+ https.use_ssl = true
22
+
23
+ request = Net::HTTP::Post.new(url)
24
+ request["Content-Type"] = "application/json"
25
+ request["sdk-version-number"] = Afip::VERSION
26
+ request["sdk-library"] = "ruby"
27
+ request["sdk-environment"] = afip.production == true ? "prod" : "dev"
28
+ request["Authorization"] = "Bearer #{afip.access_token}" if afip.access_token
29
+
30
+ request.body = JSON.dump(data)
31
+ response = https.request(request)
32
+
33
+ unless response.is_a? Net::HTTPSuccess
34
+ begin
35
+ raise JSON.parse(response.read_body)
36
+ rescue
37
+ raise response.read_body
38
+ end
39
+ end
40
+
41
+ response_data = JSON.parse(response.read_body)
42
+
43
+ { "file" => response_data["file"], "file_name" => response_data["file_name"] }
44
+ end
45
+
46
+ # Gets last voucher number
47
+ def getLastVoucher(sales_point, type)
48
+ req = {
49
+ "PtoVta": sales_point,
50
+ "CbteTipo": type
51
+ }
52
+
53
+ executeRequest("FECompUltimoAutorizado", req)["CbteNro"]
54
+ end
55
+
56
+ # Create a voucher from AFIP
57
+ def createVoucher(data, return_response = false)
58
+ # Reassign data to avoid modify te original object
59
+ data = JSON.parse(data.to_json)
60
+
61
+ req = {
62
+ "FeCAEReq": {
63
+ "FeCabReq": {
64
+ "CantReg": data["CbteHasta"] - data["CbteDesde"] + 1,
65
+ "PtoVta": data["PtoVta"],
66
+ "CbteTipo": data["CbteTipo"]
67
+ },
68
+ "FeDetReq": {
69
+ "FECAEDetRequest": data
70
+ }
71
+ }
72
+ }
73
+
74
+ data.delete("CantReg")
75
+ data.delete("PtoVta")
76
+ data.delete("CbteTipo")
77
+
78
+ data["Tributos"] = { "Tributo": data["Tributos"] } if data["Tributos"]
79
+ data["Iva"] = { "AlicIva": data["Iva"] } if data["Iva"]
80
+ data["CbtesAsoc"] = { "CbteAsoc": data["CbtesAsoc"] } if data["CbtesAsoc"]
81
+ data["Compradores"] = { "Comprador": data["Compradores"] } if data["Compradores"]
82
+ data["Opcionales"] = { "Opcional": data["Opcionales"] } if data["Opcionales"]
83
+
84
+ results = executeRequest("FECAESolicitar", req)
85
+
86
+ if return_response == true
87
+ results
88
+ else
89
+ if results["FeDetResp"]["FECAEDetResponse"].is_a?(Array)
90
+ results["FeDetResp"]["FECAEDetResponse"] = results["FeDetResp"]["FECAEDetResponse"][0]
91
+ end
92
+
93
+ {
94
+ "CAE" => results["FeDetResp"]["FECAEDetResponse"]["CAE"],
95
+ "CAEFchVto" => formatDate(results["FeDetResp"]["FECAEDetResponse"]["CAEFchVto"])
96
+ }
97
+ end
98
+ end
99
+
100
+ # Create next voucher from AFIP
101
+ def createNextVoucher(data)
102
+ # Stringify keys
103
+ data = JSON.parse(data.to_json)
104
+
105
+ lastVoucher = getLastVoucher(data["PtoVta"], data["CbteTipo"])
106
+
107
+ voucherNumber = lastVoucher + 1
108
+
109
+ data["CbteDesde"] = voucherNumber
110
+ data["CbteHasta"] = voucherNumber
111
+
112
+ res = createVoucher(data)
113
+
114
+ res["voucherNumber"] = voucherNumber
115
+
116
+ res
117
+ end
118
+
119
+ # Get complete voucher information
120
+ def getVoucherInfo(number, sales_point, type)
121
+ req = {
122
+ "FeCompConsReq": {
123
+ "CbteNro": number,
124
+ "PtoVta": sales_point,
125
+ "CbteTipo": type
126
+ }
127
+ }
128
+
129
+ executeRequest("FECompConsultar", req)
130
+ end
131
+
132
+ # Create CAEA
133
+ def createCAEA(period, fortnight)
134
+ req = {
135
+ "Periodo": period,
136
+ "Orden": fortnight
137
+ }
138
+
139
+ executeRequest("FECAEASolicitar", req)["ResultGet"]
140
+ end
141
+
142
+ # Get CAEA
143
+ def getCAEA(period, fortnight)
144
+ req = {
145
+ "Periodo": period,
146
+ "Orden": fortnight
147
+ }
148
+
149
+ executeRequest("FECAEAConsultar", req)["ResultGet"]
150
+ end
151
+
152
+ # Asks to AFIP Servers for available sales points
153
+ def getSalesPoints
154
+ executeRequest("FEParamGetPtosVenta")["ResultGet"]["PtoVenta"]
155
+ end
156
+
157
+ # Asks to AFIP Servers for available voucher types
158
+ def getVoucherTypes
159
+ executeRequest("FEParamGetTiposCbte")["ResultGet"]["CbteTipo"]
160
+ end
161
+
162
+ # Asks to AFIP Servers for voucher concepts availables
163
+ def getConceptTypes
164
+ executeRequest("FEParamGetTiposConcepto")["ResultGet"]["ConceptoTipo"]
165
+ end
166
+
167
+ # Asks to AFIP Servers for document types availables
168
+ def getDocumentTypes
169
+ executeRequest("FEParamGetTiposDoc")["ResultGet"]["DocTipo"]
170
+ end
171
+
172
+ # Asks to AFIP Servers for available aliquotes
173
+ def getAliquotTypes
174
+ executeRequest("FEParamGetTiposIva")["ResultGet"]["IvaTipo"]
175
+ end
176
+
177
+ # Asks to AFIP Servers for available currencies
178
+ def getCurrenciesTypes
179
+ executeRequest("FEParamGetTiposMonedas")["ResultGet"]["Moneda"]
180
+ end
181
+
182
+ # Asks to AFIP Servers for available voucher optional data
183
+ def getOptionsTypes
184
+ executeRequest("FEParamGetTiposOpcional")["ResultGet"]["OpcionalTipo"]
185
+ end
186
+
187
+ # Asks to AFIP Servers for available tax types
188
+ def getTaxTypes
189
+ executeRequest("FEParamGetTiposTributos")["ResultGet"]["TributoTipo"]
190
+ end
191
+
192
+ # Asks to web service for servers status
193
+ def getServerStatus
194
+ executeRequest("FEDummy")
195
+ end
196
+
197
+ # Change date from AFIP used format (yyyymmdd) to yyyy-mm-dd
198
+ def formatDate(date)
199
+ m = /(?<year>\d{4})(?<month>\d{2})(?<day>\d{2})/.match(date.to_s)
200
+
201
+ "#{m[:year]}-#{m[:month]}-#{m[:day]}"
202
+ end
203
+
204
+ # Sends request to AFIP servers
205
+ def executeRequest(operation, params = {})
206
+ params.merge!(getWSInitialRequest(operation))
207
+
208
+ results = super(operation, params)
209
+
210
+ checkErrors(operation, results)
211
+
212
+ results["#{operation}Result"]
213
+ end
214
+
215
+ # Prepare default request parameters for most operations
216
+ def getWSInitialRequest(operation)
217
+ if operation == "FEDummy"
218
+ {}
219
+ else
220
+ ta = getTokenAuthorization
221
+
222
+ {
223
+ "Auth": {
224
+ "Token": ta["token"],
225
+ "Sign": ta["sign"],
226
+ "Cuit": afip.CUIT
227
+ }
228
+ }
229
+ end
230
+ end
231
+
232
+ # Check if occurs an error on Web Service request
233
+ def checkErrors(operation, results)
234
+ res = results["#{operation}Result"]
235
+
236
+ if operation == "FECAESolicitar" && res["FeDetResp"]
237
+ if res["FeDetResp"]["FECAEDetResponse"].is_a?(Array)
238
+ res["FeDetResp"]["FECAEDetResponse"] = res["FeDetResp"]["FECAEDetResponse"][0]
239
+ end
240
+
241
+ if res["FeDetResp"]["FECAEDetResponse"]["Observaciones"] && res["FeDetResp"]["FECAEDetResponse"]["Resultado"] != "A"
242
+ res["Errors"] = { "Err" => res["FeDetResp"]["FECAEDetResponse"]["Observaciones"]["Obs"] }
243
+ end
244
+ end
245
+
246
+ return unless res["Errors"]
247
+
248
+ err = res["Errors"]["Err"].is_a?(Array) ? res["Errors"]["Err"][0] : res["Errors"]["Err"]
249
+
250
+ raise "(#{err["Code"]}) #{err["Msg"]}"
251
+ end
252
+
253
+ private :checkErrors
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afip
4
+ module WebServices
5
+ class RegisterInscriptionProof < Afip::WebService
6
+ @soapv12 = false
7
+ @WSDL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA5?WSDL"
8
+ @URL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA5"
9
+ @WSDL_TEST = "https://awshomo.afip.gov.ar/sr-padron/webservices/personaServiceA5?WSDL"
10
+ @URL_TEST = "https://awshomo.afip.gov.ar/sr-padron/webservices/personaServiceA5"
11
+
12
+ def initialize(afip)
13
+ super(afip, { "service": "ws_sr_constancia_inscripcion" })
14
+ end
15
+
16
+ # Asks to web service for taxpayer details
17
+ def getTaxpayerDetails(identifier)
18
+ # Get token and sign
19
+ ta = getTokenAuthorization
20
+
21
+ # Prepare params
22
+ params = {
23
+ "token": ta["token"],
24
+ "sign": ta["sign"],
25
+ "cuitRepresentada": afip.CUIT,
26
+ "idPersona": identifier
27
+ }
28
+
29
+ executeRequest("getPersona_v2", params)
30
+ end
31
+
32
+ # Asks to web service for taxpayers details
33
+ def getTaxpayersDetails(identifiers)
34
+ # Get token and sign
35
+ ta = getTokenAuthorization
36
+
37
+ # Prepare params
38
+ params = {
39
+ "token": ta["token"],
40
+ "sign": ta["sign"],
41
+ "cuitRepresentada": afip.CUIT,
42
+ "idPersona": identifiers
43
+ }
44
+
45
+ executeRequest("getPersonaList_v2", params)["persona"]
46
+ end
47
+
48
+ # Asks to web service for servers status
49
+ def getServerStatus
50
+ executeRequest("dummy")
51
+ end
52
+
53
+ # Send request to AFIP servers
54
+ def executeRequest(operation, params = {})
55
+ results = super(operation, params)
56
+
57
+ if operation == "getPersona_v2"
58
+ results["personaReturn"]
59
+ elsif operation == "getPersonaList_v2"
60
+ results["personaListReturn"]
61
+ else
62
+ results["return"]
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afip
4
+ module WebServices
5
+ class RegisterScopeTen < Afip::WebService
6
+ @soapv12 = false
7
+ @WSDL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA10?WSDL"
8
+ @URL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA10"
9
+ @WSDL_TEST = "https://awshomo.afip.gov.ar/sr-padron/webservices/personaServiceA10?WSDL"
10
+ @URL_TEST = "https://awshomo.afip.gov.ar/sr-padron/webservices/personaServiceA10"
11
+
12
+ def initialize(afip)
13
+ super(afip, { "service": "ws_sr_padron_a10" })
14
+ end
15
+
16
+ # Asks to web service for taxpayer details
17
+ def getTaxpayerDetails(identifier)
18
+ # Get token and sign
19
+ ta = getTokenAuthorization
20
+
21
+ # Prepare params
22
+ params = {
23
+ "token": ta["token"],
24
+ "sign": ta["sign"],
25
+ "cuitRepresentada": afip.CUIT,
26
+ "idPersona": identifier
27
+ }
28
+
29
+ executeRequest("getPersona", params)
30
+ end
31
+
32
+ # Asks to web service for servers status
33
+ def getServerStatus
34
+ executeRequest("dummy")
35
+ end
36
+
37
+ # Send request to AFIP servers
38
+ def executeRequest(operation, params = {})
39
+ results = super(operation, params)
40
+
41
+ if operation == "getPersona"
42
+ results["personaReturn"]
43
+ else
44
+ results["return"]
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afip
4
+ module WebServices
5
+ class RegisterScopeThirteen < Afip::WebService
6
+ @soapv12 = false
7
+ @WSDL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA13?WSDL"
8
+ @URL = "https://aws.afip.gov.ar/sr-padron/webservices/personaServiceA13"
9
+ @WSDL_TEST = "https://awshomo.afip.gov.ar/sr-padron/webservices/personaServiceA13?WSDL"
10
+ @URL_TEST = "https://awshomo.afip.gov.ar/sr-padron/webservices/personaServiceA13"
11
+
12
+ def initialize(afip)
13
+ super(afip, { "service": "ws_sr_padron_a13" })
14
+ end
15
+
16
+ # Asks to web service for taxpayer details
17
+ def getTaxpayerDetails(identifier)
18
+ # Get token and sign
19
+ ta = getTokenAuthorization
20
+
21
+ # Prepare params
22
+ params = {
23
+ "token": ta["token"],
24
+ "sign": ta["sign"],
25
+ "cuitRepresentada": afip.CUIT,
26
+ "idPersona": identifier
27
+ }
28
+
29
+ executeRequest("getPersona", params)
30
+ end
31
+
32
+ # Asks to web service for tax id by document number
33
+ def getTaxIDByDocument(document_number)
34
+ # Get token and sign
35
+ ta = getTokenAuthorization
36
+
37
+ # Prepare params
38
+ params = {
39
+ "token": ta["token"],
40
+ "sign": ta["sign"],
41
+ "cuitRepresentada": afip.CUIT,
42
+ "documento": document_number
43
+ }
44
+
45
+ executeRequest("getIdPersonaListByDocumento", params)["idPersona"]
46
+ end
47
+
48
+ # Asks to web service for servers status
49
+ def getServerStatus
50
+ executeRequest("dummy")
51
+ end
52
+
53
+ # Send request to AFIP servers
54
+ def executeRequest(operation, params = {})
55
+ results = super(operation, params)
56
+
57
+ if operation == "getPersona"
58
+ results["personaReturn"]
59
+ elsif operation == "getIdPersonaListByDocumento"
60
+ results["idPersonaListReturn"]
61
+ else
62
+ results["return"]
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afip
4
+ VERSION = "1.0.1"
5
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afip
4
+ class WebService
5
+ # Configurable options
6
+ attr_accessor :var, :soapv12, :WSDL, :URL, :WSDL_TEST, :URL_TEST, :afip, :options
7
+
8
+ def initialize(afip, options = {})
9
+ self.afip = afip
10
+ self.options = options
11
+
12
+ self.WSDL = options[:WSDL] if options.key?(:WSDL)
13
+ self.URL = options[:URL] if options.key?(:URL)
14
+ self.WSDL_TEST = options[:WSDL_TEST] if options.key?(:WSDL_TEST)
15
+ self.URL_TEST = options[:URL_TEST] if options.key?(:URL_TEST)
16
+
17
+ return unless options.key?(:generic) && options[:generic] == true
18
+
19
+ raise "service field is required in options" unless options.key?(:service)
20
+
21
+ options[:soapV1_2] = options.key?(:soapV1_2) ? options[:soapV1_2] : false
22
+
23
+ self.soapv12 = options[:soapV1_2]
24
+ end
25
+
26
+ # Gets token authorization for an AFIP Web Service
27
+ #
28
+ # If force is true it forces to create a new TA
29
+ def getTokenAuthorization(force = false)
30
+ afip.getServiceTA(options[:service], force)
31
+ end
32
+
33
+ # Sends request to AFIP servers
34
+ def executeRequest(method, params = {})
35
+ url = URI("https://app.afipsdk.com/api/v1/afip/requests")
36
+
37
+ https = Net::HTTP.new(url.host, url.port)
38
+ https.use_ssl = true
39
+
40
+ request = Net::HTTP::Post.new(url)
41
+ request["Content-Type"] = "application/json"
42
+ request["sdk-version-number"] = Afip::VERSION
43
+ request["sdk-library"] = "ruby"
44
+ request["sdk-environment"] = afip.production == true ? "prod" : "dev"
45
+ request["Authorization"] = "Bearer #{afip.access_token}" if afip.access_token
46
+
47
+ data = {
48
+ "method": method,
49
+ "params": params,
50
+ "environment": afip.production == true ? "prod" : "dev",
51
+ "wsid": options[:service],
52
+ "url": afip.production == true ? self.URL : self.URL_TEST,
53
+ "wsdl": afip.production == true ? self.WSDL : self.WSDL_TEST,
54
+ "soap_v_1_2": soapv12
55
+ }
56
+
57
+ request.body = JSON.dump(data)
58
+ response = https.request(request)
59
+
60
+ unless response.is_a? Net::HTTPSuccess
61
+ begin
62
+ raise JSON.parse(response.read_body)
63
+ rescue
64
+ raise response.read_body
65
+ end
66
+ end
67
+
68
+ JSON.parse(response.read_body)
69
+ end
70
+ end
71
+ end
data/lib/afip.rb ADDED
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "uri"
5
+ require "json"
6
+ require "net/http"
7
+
8
+ require_relative "afip/version"
9
+ require_relative "afip/web_service"
10
+ require_relative "afip/electronic_billing"
11
+ require_relative "afip/register_inscription_proof"
12
+ require_relative "afip/register_scope_ten"
13
+ require_relative "afip/register_scope_thirteen"
14
+
15
+ # AfipSDK is the easyest way to connect with AFIP
16
+ module Afip
17
+ def self.new(options)
18
+ Afip::Instance.new(options)
19
+ end
20
+
21
+ class Instance
22
+ attr_accessor :CUIT,
23
+ :cert,
24
+ :key,
25
+ :production,
26
+ :access_token,
27
+ :ElectronicBilling,
28
+ :RegisterInscriptionProof,
29
+ :RegisterScopeTen,
30
+ :RegisterScopeThirteen
31
+
32
+ def initialize(options)
33
+ raise "CUIT field is required in options" unless options.key?(:CUIT)
34
+
35
+ self.CUIT = options[:CUIT]
36
+ self.production = options.key?(:production) ? options[:production] : false
37
+ self.cert = options[:cert]
38
+ self.key = options[:key]
39
+ self.access_token = options[:access_token]
40
+
41
+ self.ElectronicBilling = Afip::WebServices::ElectronicBilling.new(self)
42
+ self.RegisterInscriptionProof = Afip::WebServices::RegisterInscriptionProof.new(self)
43
+ self.RegisterScopeTen = Afip::WebServices::RegisterScopeTen.new(self)
44
+ self.RegisterScopeThirteen = Afip::WebServices::RegisterScopeThirteen.new(self)
45
+ end
46
+
47
+ # Gets token authorization for an AFIP Web Service
48
+ #
49
+ # If force is true it forces to create a new TA
50
+ def getServiceTA(service, force = false)
51
+ url = URI("https://app.afipsdk.com/api/v1/afip/auth")
52
+
53
+ https = Net::HTTP.new(url.host, url.port)
54
+ https.use_ssl = true
55
+
56
+ request = Net::HTTP::Post.new(url)
57
+ request["Content-Type"] = "application/json"
58
+ request["sdk-version-number"] = Afip::VERSION
59
+ request["sdk-library"] = "ruby"
60
+ request["sdk-environment"] = production == true ? "prod" : "dev"
61
+ request["Authorization"] = "Bearer #{access_token}" if access_token
62
+
63
+ data = {
64
+ "environment": production == true ? "prod" : "dev",
65
+ "tax_id": self.CUIT,
66
+ "wsid": service,
67
+ "force_create": force
68
+ }
69
+
70
+ data["cert"] = cert if cert
71
+ data["key"] = key if key
72
+
73
+ request.body = JSON.dump(data)
74
+ response = https.request(request)
75
+
76
+ unless response.is_a? Net::HTTPSuccess
77
+ begin
78
+ raise JSON.parse(response.read_body)
79
+ rescue
80
+ raise response.read_body
81
+ end
82
+ end
83
+
84
+ JSON.parse(response.read_body)
85
+ end
86
+
87
+ # Get last request and last response XML
88
+ def getLastRequestXML
89
+ url = URI("https://app.afipsdk.com/api/v1/afip/requests/last-xml")
90
+
91
+ https = Net::HTTP.new(url.host, url.port)
92
+ https.use_ssl = true
93
+
94
+ request = Net::HTTP::Get.new(url)
95
+ request["sdk-version-number"] = Afip::VERSION
96
+ request["sdk-library"] = "ruby"
97
+ request["sdk-environment"] = production == true ? "prod" : "dev"
98
+ request["Authorization"] = "Bearer #{access_token}" if access_token
99
+
100
+ data["cert"] = cert if cert
101
+ data["key"] = key if key
102
+
103
+ response = https.request(request)
104
+
105
+ unless response.is_a? Net::HTTPSuccess
106
+ begin
107
+ raise JSON.parse(response.read_body)
108
+ rescue
109
+ raise response.read_body
110
+ end
111
+ end
112
+
113
+ JSON.parse(response.read_body)
114
+ end
115
+
116
+ # Create generic Web Service
117
+ def webService(service, options = {})
118
+ options[:service] = service
119
+ options[:generic] = true
120
+
121
+ Afip::WebService.new(self, options)
122
+ end
123
+ end
124
+ end
data/sig/afip.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Afip
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: afip.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Afip SDK
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-12-26 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: AfipSDK is the easyest way to connect with AFIP
14
+ email:
15
+ - afipsdk@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rubocop.yml"
21
+ - LICENSE.txt
22
+ - README.md
23
+ - Rakefile
24
+ - afip.gemspec
25
+ - lib/afip.rb
26
+ - lib/afip/electronic_billing.rb
27
+ - lib/afip/register_inscription_proof.rb
28
+ - lib/afip/register_scope_ten.rb
29
+ - lib/afip/register_scope_thirteen.rb
30
+ - lib/afip/version.rb
31
+ - lib/afip/web_service.rb
32
+ - sig/afip.rbs
33
+ homepage: https://afipsdk.com
34
+ licenses:
35
+ - MIT
36
+ metadata:
37
+ homepage_uri: https://afipsdk.com
38
+ source_code_uri: https://github.com/AfipSDK/afip.rb
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.3.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.1.2
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Library to connect with AFIP
58
+ test_files: []