afip.rb 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []