biro 0.2.0

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