biro 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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +21 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +72 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +11 -0
  11. data/bin/setup +8 -0
  12. data/biro.gemspec +34 -0
  13. data/lib/biro/configuration.rb +28 -0
  14. data/lib/biro/gateways/bacen/request.rb +54 -0
  15. data/lib/biro/gateways/bacen/response.rb +109 -0
  16. data/lib/biro/gateways/bacen.rb +2 -0
  17. data/lib/biro/gateways/base_request.rb +30 -0
  18. data/lib/biro/gateways/base_response.rb +5 -0
  19. data/lib/biro/gateways/bvs/builders/base_builder.rb +17 -0
  20. data/lib/biro/gateways/bvs/builders/debits_request_builder.rb +26 -0
  21. data/lib/biro/gateways/bvs/builders/debits_response_builder.rb +45 -0
  22. data/lib/biro/gateways/bvs/builders/score_request_builder.rb +24 -0
  23. data/lib/biro/gateways/bvs/builders/score_response_builder.rb +93 -0
  24. data/lib/biro/gateways/bvs/request.rb +71 -0
  25. data/lib/biro/gateways/bvs/response.rb +56 -0
  26. data/lib/biro/gateways/bvs.rb +7 -0
  27. data/lib/biro/gateways/cred_defense/request.rb +69 -0
  28. data/lib/biro/gateways/cred_defense/response.rb +131 -0
  29. data/lib/biro/gateways/cred_defense.rb +2 -0
  30. data/lib/biro/gateways/midia100/request.rb +59 -0
  31. data/lib/biro/gateways/midia100/response.rb +166 -0
  32. data/lib/biro/gateways/midia100.rb +2 -0
  33. data/lib/biro/gateways/ph3a/builders/login_builder.rb +15 -0
  34. data/lib/biro/gateways/ph3a/request.rb +72 -0
  35. data/lib/biro/gateways/ph3a/response.rb +340 -0
  36. data/lib/biro/gateways/ph3a.rb +3 -0
  37. data/lib/biro/gateways/spc/request.rb +59 -0
  38. data/lib/biro/gateways/spc/response.rb +190 -0
  39. data/lib/biro/gateways/spc.rb +2 -0
  40. data/lib/biro/gateways.rb +8 -0
  41. data/lib/biro/response.rb +15 -0
  42. data/lib/biro/utils/soap.rb +27 -0
  43. data/lib/biro/utils.rb +11 -0
  44. data/lib/biro/version.rb +3 -0
  45. data/lib/biro.rb +31 -0
  46. metadata +206 -0
@@ -0,0 +1,71 @@
1
+ require 'rest_client'
2
+
3
+ module Biro
4
+ module Bvs
5
+ class Request < BaseRequest
6
+ def production_url
7
+ "https://bvsntt.bvsnet.com.br/cgi-bin/db2www/netpo028.mbr/string?consulta="
8
+ end
9
+
10
+ def development_url
11
+ "http://localhost:8900/"
12
+ end
13
+
14
+ def required_params
15
+ [:username, :password]
16
+ end
17
+
18
+ def find(document, options = {})
19
+ bvs_results = {}
20
+ bvs_results[:score] = score(document) if options.keys.include?(:score)
21
+ bvs_results[:debits] = debits(document) if options.keys.include?(:debits)
22
+
23
+ get_response(bvs_results)
24
+ end
25
+
26
+ private
27
+
28
+ def get_response(result)
29
+ response = Response.new result
30
+
31
+ raise DocumentNotFoundError.new("BVS Error: Document not found - SCORE: #{response.score_error_message} - DEBITS: #{response.debits_error_message}" ) if auth_error?(response)
32
+ raise AuthenticationError.new("BVS Error: Invalid user or password - SCORE: #{response.score_error_message} - DEBITS: #{response.debits_error_message}" ) if document_error?(response)
33
+ raise StandardError.new("Error at BVS Request: SCORE: #{response.score_error_message} - DEBITS: #{response.debits_error_message}" ) unless response.score_error_message.blank? && response.debits_error_message.blank?
34
+
35
+ response
36
+ end
37
+
38
+ def document_error?(response)
39
+ response.score_error_message == "SENHA INVALIDA" || response.debits_error_message == "SENHA INVALIDA"
40
+ end
41
+
42
+ def auth_error?(response)
43
+ response.score_error_message == "DOCUMENTO INVALIDO" || response.debits_error_message == "DOCUMENTO INVALIDO"
44
+ end
45
+
46
+ def score(document)
47
+ params = ScoreRequestBuilder.new(document, @username, @password).build
48
+
49
+ begin
50
+ response = RestClient::Request.execute(url: url + URI.encode(params), method: :get, verify_ssl: false)
51
+ return response
52
+ rescue => e
53
+ Biro.log(:warn, "Unable to process BVS score request")
54
+ raise StandardError.new("Error at BVS score request: #{e.message}")
55
+ end
56
+ end
57
+
58
+ def debits(document)
59
+ params = DebitsRequestBuilder.new(document, @username, @password).build
60
+
61
+ begin
62
+ response = RestClient::Request.execute(url: url + URI.encode(params), method: :get, verify_ssl: false)
63
+ return response
64
+ rescue => e
65
+ Biro.log(:warn, "Unable to process BVS debits request")
66
+ raise StandardError.new("Error at BVS debits request: #{e.message}")
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,56 @@
1
+ require 'rest_client'
2
+
3
+ module Biro
4
+ module Bvs
5
+ class Response < BaseResponse
6
+ attr_reader :body
7
+
8
+ def initialize(responses)
9
+ @body = { }
10
+ [:score, :debits].each { |r| @body[r] = responses[r].body if responses[r] }
11
+ end
12
+
13
+ def returning_score?
14
+ score_body.return_code == "0"
15
+ end
16
+
17
+ def returning_debits?
18
+ debits_body.return_code == "0"
19
+ end
20
+
21
+ def name
22
+ score_body.response_text_name.strip
23
+ end
24
+
25
+ def document
26
+ score_body.response_text_document.to_i
27
+ end
28
+
29
+ def scores
30
+ score_body.response_text_result_score.to_i
31
+ end
32
+
33
+ def debits?
34
+ debits_body.debits_info == 'S'
35
+ end
36
+
37
+ def debits_error_message
38
+ debits_body.error_message.strip unless returning_debits?
39
+ end
40
+
41
+ def score_error_message
42
+ score_body.error_message.strip unless returning_score?
43
+ end
44
+
45
+ private
46
+
47
+ def score_body
48
+ ScoreResponseBuilder.new @body[:score]
49
+ end
50
+
51
+ def debits_body
52
+ DebitsResponseBuilder.new @body[:debits]
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'bvs/request'
2
+ require_relative 'bvs/response'
3
+ require_relative 'bvs/builders/base_builder'
4
+ require_relative 'bvs/builders/debits_request_builder'
5
+ require_relative 'bvs/builders/score_request_builder'
6
+ require_relative 'bvs/builders/debits_response_builder'
7
+ require_relative 'bvs/builders/score_response_builder'
@@ -0,0 +1,69 @@
1
+ require 'rest_client'
2
+
3
+ module Biro
4
+ module CredDefense
5
+ class Request < BaseRequest
6
+
7
+ def production_url
8
+ 'https://www.creddefense.com/index.php/api/v2'
9
+ end
10
+
11
+ def development_url
12
+ 'https://test.creddefense.com/index.php/api/v2'
13
+ end
14
+
15
+ def required_params
16
+ [:username, :password]
17
+ end
18
+
19
+ def find(document)
20
+ params = {
21
+ authentication: { token: token },
22
+ advancedsearch: { identifier_code: document }
23
+ }
24
+
25
+ begin
26
+ response = RestClient.post(search_path, params.to_json, headers)
27
+ Response.new(response)
28
+ rescue => e
29
+ Biro.log(:warn, "Unable to process CredDefense request")
30
+ raise "Error at CredDefense request: #{e.message}"
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def login_path
37
+ url + '/login'
38
+ end
39
+
40
+ def search_path
41
+ url + '/advancedsearch'
42
+ end
43
+
44
+ def token
45
+ @token ||= get_token
46
+ end
47
+
48
+ def get_token
49
+ auth = { authentication: { username: @username, password: @password } }
50
+ response = JSON.parse(RestClient.post(login_path, auth.to_json, headers).body)
51
+
52
+ raise AuthenticationError.new('Invalid authentication credentials') unless success?(response)
53
+
54
+ response.dig('authentication', 'token')
55
+ end
56
+
57
+ def success?(response)
58
+ response['result'] == 'success'
59
+ end
60
+
61
+ def headers
62
+ {
63
+ 'Accept' => 'application/json',
64
+ 'Content-Type' => 'application/json'
65
+ }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,131 @@
1
+ require 'active_support/core_ext/array'
2
+
3
+ module Biro
4
+ module CredDefense
5
+ class Response < BaseResponse
6
+ def initialize(response)
7
+ @body = response.body
8
+ end
9
+
10
+ def cpf
11
+ text('nrcpf').gsub(/\D/, '')
12
+ end
13
+
14
+ def birthdate
15
+ text('dtnascimento')
16
+ end
17
+
18
+ def mothers_name
19
+ text('nomae')
20
+ end
21
+
22
+ def name
23
+ text('nopessoa')
24
+ end
25
+
26
+ def income
27
+ text('nrrenda')
28
+ end
29
+
30
+ def profession
31
+ text('nrcbo')
32
+ end
33
+
34
+ def emails
35
+ email = text('noemail')
36
+ Array.wrap(email)
37
+ end
38
+
39
+ def receita_federal
40
+ rf = data.dig('dmcomprovantereceita')&.first
41
+
42
+ return nil unless rf
43
+
44
+ { name: rf.dig('nopessoa'), status: rf.dig('nosituacao'), date: rf.dig('dhprocessamento'), death: text('boobito') }
45
+ end
46
+
47
+ def equities
48
+ data.dig('dmlistaparticipacaosocietaria')&.map do |e|
49
+ cpf = e.dig('nrdocumentosocio')&.gsub(/\D/, '')
50
+ cnpj = e.dig('nrcnpj')&.gsub(/\D/, '')
51
+ name = e.dig('nosocio')&.strip
52
+ company = e.dig('norazaosocial')&.strip
53
+ shares = e.dig('qtpercentualcapitalsocial')
54
+ position = e.dig('noqualificacaosocio')&.strip
55
+ since = e.dig('dtentradasociedade')&.strip
56
+
57
+ {
58
+ cpf: cpf,
59
+ cnpj: cnpj,
60
+ name: name,
61
+ company: company,
62
+ shares: shares,
63
+ position: position,
64
+ since: since,
65
+ }
66
+ end
67
+ end
68
+
69
+ def addresses
70
+ data.fetch('dmlistaenderecos', nil).map do |a|
71
+ parts = a['nologradouro'].split('-')
72
+ street = parts[0]&.split[0..-2].join(' ')
73
+ number = parts[0]&.split&.pop
74
+ city_parts = a['cdibgemunicipio']&.split('/')
75
+ city = city_parts && city_parts[0]
76
+ state = city_parts && city_parts[1]
77
+
78
+
79
+ {
80
+ street: street,
81
+ number: number,
82
+ complement: parts[1]&.strip,
83
+ city: city,
84
+ state: state,
85
+ zipcode: a['nrcep']
86
+ }
87
+ end
88
+ end
89
+
90
+ def phones
91
+ data.fetch('dmlistatelefones', nil).map do |p|
92
+ parts = p['nrtelefone']&.split(' ')
93
+ ddd = parts&.fetch(0, nil)&.gsub(/\D/, '')
94
+ number = parts&.fetch(1)
95
+ kind = (number.to_s[0] == '9' ? :mobile : :landline) if number
96
+
97
+ {
98
+ ddd: ddd,
99
+ number: number,
100
+ kind: kind
101
+ }
102
+ end
103
+
104
+ end
105
+
106
+ def success?
107
+ error.blank?
108
+ end
109
+
110
+ def error
111
+ if json['result'] == 'error'
112
+ json['messages']&.first
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ def text(field)
119
+ data.dig('dmlistapessoafisica', field).strip
120
+ end
121
+
122
+ def data
123
+ json.dig('advancedsearch')
124
+ end
125
+
126
+ def json
127
+ JSON.parse(@body)
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'cred_defense/request'
2
+ require_relative 'cred_defense/response'
@@ -0,0 +1,59 @@
1
+ module Biro
2
+ module Midia100
3
+ class Request < BaseRequest
4
+ include Utils::Soap
5
+
6
+ def production_url
7
+ 'http://177.70.121.160/WSSisconsulta/consulta.asmx?wsdl'
8
+ end
9
+
10
+ def required_params
11
+ [:username, :password]
12
+ end
13
+
14
+ def find(document, options = {})
15
+ responses = { registration: soap.call(:consultar, message: params(document)) }
16
+ verify_response responses
17
+
18
+ [:rf, :equity, :job, :default].each do |i|
19
+ if options.keys.include?("include_#{i}".to_sym)
20
+ begin
21
+ responses[i] = soap.call(:consultar, message: params(document, SearchType.by(i)))
22
+ rescue
23
+ Biro.log(:warn, "Unable to process Midia100 #{i} request")
24
+ raise StandardError.new("Error at Midia100 request: #{e.message}")
25
+ end
26
+ end
27
+ end
28
+
29
+ Response.new(responses)
30
+ end
31
+
32
+ private
33
+
34
+ def verify_response responses
35
+ raise AuthenticationError.new("Error at Midia100 request: #{responses[:registration].body[:consultar_response][:consultar_result]}") if responses[:registration]&.body[:consultar_response][:consultar_result]&.include? "Usuário ou Senha Estão Incorretos"
36
+ raise DocumentNotFoundError.new("Error at Midia100 request: #{responses[:registration].body[:consultar_response][:consultar_result]}") if responses[:registration]&.body[:consultar_response][:consultar_result]&.include? "Cpf Inválido"
37
+ raise StandardError.new("Error at Midia100 request: #{responses[:registration].body[:consultar_response][:consultar_result]}") if responses[:registration]&.body[:consultar_response][:consultar_result]&.include? "<ERRO>"
38
+ end
39
+
40
+ def params(document, search_type = SearchType.by(:registration))
41
+ { 'usuario' => @username, 'senha' => @password, 'CodConsulta' => search_type, 'parametros' => document }
42
+ end
43
+ end
44
+
45
+ module SearchType
46
+ TYPES = {
47
+ registration: 2004,
48
+ rf: 2076,
49
+ equity: 2010,
50
+ job: 2017,
51
+ default: 2075
52
+ }
53
+
54
+ def self.by(type)
55
+ TYPES[type.to_sym]
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,166 @@
1
+ require 'active_support/core_ext/array'
2
+
3
+ module Biro
4
+ module Midia100
5
+ class Response < BaseResponse
6
+ def initialize(responses)
7
+ @body = { registration: responses[:registration].body }
8
+
9
+ [:rf, :equity, :job, :default].each { |r| @body[r] = responses[r].body if responses[r] }
10
+ end
11
+
12
+ def cpf
13
+ text('Cpf')&.gsub(/\D/, '')
14
+ end
15
+
16
+ def birthdate
17
+ text('DtNasc')
18
+ end
19
+
20
+ def marital_status
21
+ text('EstadoCivil')
22
+ end
23
+
24
+ def pis
25
+ text('Pis')
26
+ end
27
+
28
+ def mothers_name
29
+ text('NomeMae')
30
+ end
31
+
32
+ def income
33
+ text('RendaPresumida')
34
+ end
35
+
36
+ def profession
37
+ text('IdProfissao')
38
+ end
39
+
40
+ def education
41
+ text('Escolaridade')
42
+ end
43
+
44
+ def name
45
+ text('Nome')
46
+ end
47
+
48
+ def gender
49
+ text('Sexo')
50
+ end
51
+
52
+ def receita_federal
53
+ return nil unless rf
54
+
55
+ data = rf['Receita_x0020_Federal_x0020_Pf']
56
+
57
+ { name: data.dig('Nome'), status: data.dig('Situacao'), date: data.dig('DataPesquisa'), death: data.dig('Obito') }
58
+ end
59
+
60
+ def jobs
61
+ Array.wrap(job&.fetch('Funcionarios', nil)).map do |j|
62
+ {
63
+ cnpj: j['Cnpj']&.gsub(/[\s\.\-\/]/, ''),
64
+ company: j['Empresa']&.strip,
65
+ }
66
+ end
67
+ end
68
+
69
+ def defaults
70
+ Array.wrap(default&.fetch('spc', nil)).map do |d|
71
+ {
72
+ bureau: :spc,
73
+ company: d['nomeassociado']&.strip,
74
+ created_at: d['datainclusao'],
75
+ due_at: d['datavencimento'],
76
+ value: d['valor'],
77
+ city: d['nome'],
78
+ state: d['siglauf'],
79
+ phone: { ddd: d['numeroddd'], number: d['numero'] },
80
+ contract: d['contrato']
81
+ }
82
+ end
83
+ end
84
+
85
+ def success?
86
+ error.blank?
87
+ end
88
+
89
+ def error
90
+ return nil unless registration.keys.first =~ /Erro/
91
+
92
+ error = registration.flatten
93
+ "#{error[0]} - #{error[1]['Mensagem']}"
94
+ end
95
+
96
+ def addresses
97
+ Array.wrap(registration&.fetch('Enderecos', nil)).map do |e|
98
+ {
99
+ street: e['Logradouro']&.strip,
100
+ number: e['Numero']&.strip,
101
+ complement: e['Complemento']&.strip,
102
+ city: e['Cidade']&.strip,
103
+ state: e['Uf']&.strip,
104
+ zipcode: e['Cep']&.strip
105
+ }
106
+ end
107
+ end
108
+
109
+ def emails
110
+ Array.wrap(registration&.fetch('Emails', nil)).map do |e|
111
+ e['EMail']&.strip
112
+ end
113
+ end
114
+
115
+ def phones
116
+ landline_phones.to_a + mobile_phones.to_a
117
+ end
118
+
119
+ def landline_phones
120
+ Array.wrap(registration&.fetch('Telefones', nil)).map do |t|
121
+ {
122
+ ddd: t['Ddd'],
123
+ number: t['Fone'],
124
+ kind: :landline
125
+ }
126
+ end
127
+ end
128
+
129
+ def mobile_phones
130
+ Array.wrap(registration&.fetch('Celulares', nil)).map do |c|
131
+ {
132
+ ddd: c['Ddd'],
133
+ number: c['Fone'],
134
+ kind: :mobile
135
+ }
136
+ end
137
+ end
138
+
139
+ private
140
+
141
+ def text(field)
142
+ registration.dig('Pf', field)&.strip
143
+ end
144
+
145
+ def rf
146
+ result(@body[:rf])
147
+ end
148
+
149
+ def default
150
+ result(@body[:default])
151
+ end
152
+
153
+ def job
154
+ result(@body[:job])
155
+ end
156
+
157
+ def registration
158
+ result(@body[:registration])
159
+ end
160
+
161
+ def result(data)
162
+ Nori.new.parse(data[:consultar_response][:consultar_result])['NewDataSet'] unless data.nil?
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'midia100/request'
2
+ require_relative 'midia100/response'
@@ -0,0 +1,15 @@
1
+ require 'active_support/core_ext/array'
2
+
3
+ class LoginBuilder
4
+ def initialize response
5
+ @body = response.body
6
+ end
7
+
8
+ def token
9
+ login_result.dig(:token)
10
+ end
11
+
12
+ def login_result
13
+ @body.dig(:login_response).dig(:login_result)
14
+ end
15
+ end
@@ -0,0 +1,72 @@
1
+ module Biro
2
+ module Ph3a
3
+ class Request < BaseRequest
4
+ include Utils::Soap
5
+
6
+ def development_url
7
+ 'https://ws.databusca.com.br/DataHistory.svc?wsdl'
8
+ end
9
+
10
+ def production_url
11
+ 'https://ws.databusca.com.br/DataHistory.svc?wsdl'
12
+ end
13
+
14
+ def required_params
15
+ [:username, :password, :domain]
16
+ end
17
+
18
+ def find(document)
19
+ raise AuthenticationError.new('Invalid authentication credentials') if token.blank?
20
+
21
+ begin
22
+ params = {}
23
+ get_parameters params, document
24
+ response = soap.call(:get_person_data, message: params)
25
+ Response.new(response)
26
+ rescue => e
27
+ Biro.log(:warn, "Unable to process Ph3a request")
28
+ raise StandardError.new("Error at PH3A request: #{e.message}")
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def token
35
+ @token ||= get_token
36
+ end
37
+
38
+ def get_token
39
+ login_params = {}
40
+ get_login_parameters login_params
41
+
42
+ begin
43
+ response = soap.call(:login, message: login_params)
44
+ rescue
45
+ raise AuthenticationError.new('Authentication Error')
46
+ end
47
+
48
+ LoginBuilder.new(response).token
49
+ end
50
+
51
+ def get_login_parameters login_params
52
+ login_params['tns:user'] = {}
53
+ login_params['tns:user']['ph3a:DomainId'] = @domain
54
+ login_params['tns:user']['ph3a:Password'] = @password
55
+ login_params['tns:user']['ph3a:UserName'] = @username
56
+ end
57
+
58
+ def get_parameters params, document
59
+ params['tns:token'] = token
60
+ params['tns:document'] = document
61
+ end
62
+
63
+ def savon_options
64
+ { namespaces: {
65
+ "xmlns:soapenv"=>"http://schemas.xmlsoap.org/soap/envelope/",
66
+ "xmlns:tem"=>"http://tempuri.org/",
67
+ "xmlns:ph3a"=>"http://schemas.datacontract.org/2004/07/PH3A.Viper.Web.PortalService.Models"
68
+ }}
69
+ end
70
+ end
71
+ end
72
+ end