apigratis-sdk-ruby 0.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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +27 -0
  3. data/LICENSE +21 -0
  4. data/README.md +330 -0
  5. data/SECURITY.md +32 -0
  6. data/lib/api_brasil/client.rb +252 -0
  7. data/lib/api_brasil/core/env.rb +34 -0
  8. data/lib/api_brasil/core/errors.rb +167 -0
  9. data/lib/api_brasil/core/http_client.rb +342 -0
  10. data/lib/api_brasil/core/retry.rb +69 -0
  11. data/lib/api_brasil/core/transport/faraday_transport.rb +76 -0
  12. data/lib/api_brasil/core/transport/net_http_transport.rb +126 -0
  13. data/lib/api_brasil/core/transport.rb +114 -0
  14. data/lib/api_brasil/generated/catalog.rb +526 -0
  15. data/lib/api_brasil/legacy/service.rb +155 -0
  16. data/lib/api_brasil/services/base_service.rb +49 -0
  17. data/lib/api_brasil/services/data/bulk_service.rb +26 -0
  18. data/lib/api_brasil/services/data/cep_service.rb +58 -0
  19. data/lib/api_brasil/services/data/chip_virtual_service.rb +40 -0
  20. data/lib/api_brasil/services/data/consulta_service.rb +97 -0
  21. data/lib/api_brasil/services/data/correios_service.rb +23 -0
  22. data/lib/api_brasil/services/data/dados_service.rb +30 -0
  23. data/lib/api_brasil/services/data/database_ip_service.rb +19 -0
  24. data/lib/api_brasil/services/data/fipe_service.rb +61 -0
  25. data/lib/api_brasil/services/data/proxies.rb +146 -0
  26. data/lib/api_brasil/services/data/ura_service.rb +26 -0
  27. data/lib/api_brasil/services/data/vehicles_service.rb +46 -0
  28. data/lib/api_brasil/services/device_proxy_service.rb +46 -0
  29. data/lib/api_brasil/services/messaging/evolution_service.rb +38 -0
  30. data/lib/api_brasil/services/messaging/sms_service.rb +40 -0
  31. data/lib/api_brasil/services/messaging/whats_meow_service.rb +30 -0
  32. data/lib/api_brasil/services/messaging/whatsapp_service.rb +120 -0
  33. data/lib/api_brasil/services/platform/account_service.rb +138 -0
  34. data/lib/api_brasil/services/platform/auth_service.rb +204 -0
  35. data/lib/api_brasil/services/platform/bearer_rate_limit_service.rb +29 -0
  36. data/lib/api_brasil/services/platform/catalog_service.rb +111 -0
  37. data/lib/api_brasil/services/platform/devices_service.rb +73 -0
  38. data/lib/api_brasil/services/platform/ip_whitelist_service.rb +73 -0
  39. data/lib/api_brasil/services/platform/payments_service.rb +124 -0
  40. data/lib/api_brasil/services/platform/reports_service.rb +96 -0
  41. data/lib/api_brasil/version.rb +6 -0
  42. data/lib/api_brasil.rb +72 -0
  43. data/lib/apigratis-sdk-ruby.rb +5 -0
  44. data/lib/apigratis.rb +11 -0
  45. metadata +149 -0
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../core/http_client"
4
+
5
+ module ApiBrasil
6
+ # Interface legada da SDK: metodos de classe por servico, sempre com o
7
+ # mesmo contrato (`{ "Bearer" => ..., "DeviceToken" => ..., "body" => {...} }`)
8
+ # e resposta decodificada - erros HTTP nunca levantam excecao, sao
9
+ # devolvidos como o proprio corpo da resposta.
10
+ #
11
+ # @deprecated Prefira `ApiBrasil.new(...)`, que cobre toda a plataforma
12
+ # (WhatsApp, SMS, consultas, pagamentos, relatorios) com metodos
13
+ # dedicados, erros tipados, retry e hooks. Esta classe existe para
14
+ # quem esta migrando das SDKs PHP/Node com o contrato antigo.
15
+ module Legacy
16
+ class Service
17
+ BASE_URI = "https://gateway.apibrasil.io/api/v2"
18
+
19
+ class << self
20
+ # `POST /servers`
21
+ def server(data = {})
22
+ call("servers", data)
23
+ end
24
+
25
+ # `POST /{action}` (ex: `login`, `logout`)
26
+ def auth(action = "", data = {})
27
+ call(action, data)
28
+ end
29
+
30
+ # `POST /plan` (action `me`) ou `POST /plans/{action}`
31
+ def plan(action = "", data = {})
32
+ return call("plan", data) if action.to_s == "me"
33
+
34
+ call(join("plans", action), data)
35
+ end
36
+
37
+ # `POST /profile`
38
+ def profile(data = {})
39
+ call("profile", data)
40
+ end
41
+
42
+ # `POST /devices/{action}`
43
+ def device(action = "", data = {})
44
+ call(join("devices", action), data)
45
+ end
46
+
47
+ # `POST /whatsapp/{action}`
48
+ def whatsapp(action = "", data = {})
49
+ call(join("whatsapp", action), data)
50
+ end
51
+
52
+ # `POST /vehicles/{action}` - normaliza o campo `tipo` como na SDK PHP.
53
+ def vehicles(action = "", data = {})
54
+ normalized = Core::HttpClient.normalize_keys(data)
55
+ action = action.to_s.sub(%r{\A/+}, "")
56
+ body = normalized[:body] || {}
57
+
58
+ body = { "tipo" => normalized[:tipo].to_s }.merge(body) if normalized[:tipo] && !key?(body, "tipo")
59
+ body = normalize_tipo_body(body) if action.start_with?("base/")
60
+
61
+ call(join("vehicles", action), data, {}, body)
62
+ end
63
+
64
+ # `POST /correios/{action}`
65
+ def correios(action = "", data = {})
66
+ call(join("correios", action), data)
67
+ end
68
+
69
+ # `POST /dados/{action}` (mantido com o nome antigo `cnpj`)
70
+ def cnpj(action = "", data = {})
71
+ call(join("dados", action), data)
72
+ end
73
+
74
+ # `POST /cep/{action}`
75
+ def cep(action = "", data = {})
76
+ call(join("cep", action), data)
77
+ end
78
+
79
+ # `POST /holidays/{action}`
80
+ def holidays(action = "", data = {})
81
+ call(join("holidays", action), data)
82
+ end
83
+
84
+ # `POST /ddd/{action}`
85
+ def ddd(action = "", data = {})
86
+ call(join("ddd", action), data)
87
+ end
88
+
89
+ private
90
+
91
+ def join(prefix, action)
92
+ action = action.to_s.sub(%r{\A/+}, "")
93
+ action.empty? ? prefix : "#{prefix}/#{action}"
94
+ end
95
+
96
+ def key?(hash, name)
97
+ hash.is_a?(Hash) && (hash.key?(name) || hash.key?(name.to_sym))
98
+ end
99
+
100
+ # `{ "lista-socios" => { "cnpj" => "..." } }` vira
101
+ # `{ "tipo" => "lista-socios", "cnpj" => "..." }`.
102
+ def normalize_tipo_body(body)
103
+ return body unless body.is_a?(Hash)
104
+ return body if key?(body, "tipo")
105
+ return body unless body.size == 1
106
+
107
+ tipo, payload = body.first
108
+ return body unless tipo.is_a?(String) && !tipo.empty? && payload.is_a?(Hash)
109
+
110
+ { "tipo" => tipo }.merge(payload)
111
+ end
112
+
113
+ def call(path, data = {}, extra_headers = {}, body = nil)
114
+ data = Core::HttpClient.normalize_keys(data)
115
+ method = (data[:method] || "POST").to_s.upcase
116
+ body ||= data[:body] || {}
117
+ body = nil if %w[GET HEAD].include?(method)
118
+
119
+ client(data).request(method, path, body, request_options(data, path, extra_headers))
120
+ rescue Core::Errors::ApiBrasilError => e
121
+ e.response.nil? ? { "error" => true, "message" => e.message } : e.response
122
+ end
123
+
124
+ def client(data)
125
+ Core::HttpClient.new(
126
+ base_url: data[:base_uri] || BASE_URI,
127
+ bearer_token: data[:bearer],
128
+ device_token: data[:device_token],
129
+ timeout: timeout_ms(data),
130
+ retry: false,
131
+ transport: data[:transport]
132
+ )
133
+ end
134
+
135
+ def request_options(data, path, extra_headers)
136
+ options = { headers: extra_headers || {} }
137
+ options[:secret_key] = data[:secret_key] if data[:secret_key]
138
+ options[:query] = data[:query] if data[:query].is_a?(Hash)
139
+ # Paridade com a SDK PHP: a rota crua `qrcode` devolve o conteudo
140
+ # sem decodificar (`whatsapp/qrcode` continua sendo JSON).
141
+ options[:response_type] = "raw" if path.to_s.split("?").first.to_s.gsub(%r{\A/+|/+\z}, "") == "qrcode"
142
+
143
+ options
144
+ end
145
+
146
+ # A interface antiga recebe segundos; o cliente novo usa milissegundos.
147
+ def timeout_ms(data)
148
+ seconds = data[:timeout] || 300
149
+
150
+ (seconds.to_f * 1000).to_i
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiBrasil
4
+ module Services
5
+ # Base de todos os servicos - guarda o cliente HTTP compartilhado e
6
+ # expoe os atalhos por verbo.
7
+ class BaseService
8
+ # @return [ApiBrasil::Core::HttpClient]
9
+ attr_reader :http
10
+
11
+ # @param http [ApiBrasil::Core::HttpClient]
12
+ def initialize(http)
13
+ @http = http
14
+ end
15
+
16
+ # @return [Object]
17
+ def get(path, options = {})
18
+ http.get(path, options)
19
+ end
20
+
21
+ # @return [Object]
22
+ def post(path, body = nil, options = {})
23
+ http.post(path, body, options)
24
+ end
25
+
26
+ # @return [Object]
27
+ def put(path, body = nil, options = {})
28
+ http.put(path, body, options)
29
+ end
30
+
31
+ # @return [Object]
32
+ def patch(path, body = nil, options = {})
33
+ http.patch(path, body, options)
34
+ end
35
+
36
+ # @return [Object]
37
+ def delete(path, body = nil, options = {})
38
+ http.delete(path, body, options)
39
+ end
40
+
41
+ # Baixa os bytes crus de uma rota (PDF, imagens...).
42
+ #
43
+ # @return [String]
44
+ def download(path, options = {})
45
+ http.get(path, { response_type: "raw" }.merge(options))
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # Execucao em lote: `/bulk/direct/{action}` e `/bulk/queue/{action}`.
9
+ class BulkService < BaseService
10
+ # Executa um lote de forma sincrona: `POST /bulk/direct/{action}`.
11
+ #
12
+ # @return [Object]
13
+ def direct(action, body, options = {})
14
+ post("/bulk/direct/#{action.to_s.sub(%r{\A/+}, "")}", body, options)
15
+ end
16
+
17
+ # Enfileira um lote: `POST /bulk/queue/{action}`.
18
+ #
19
+ # @return [Object]
20
+ def queue(action, body, options = {})
21
+ post("/bulk/queue/#{action.to_s.sub(%r{\A/+}, "")}", body, options)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../device_proxy_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # CEP + geolocalizacao (device-based): `/cep/{action}`.
9
+ class CepService < DeviceProxyService
10
+ def initialize(http)
11
+ super(http, "cep")
12
+ end
13
+
14
+ # Consulta um CEP: `POST /cep/cep` body `{"cep" => ...}`.
15
+ #
16
+ # @return [Object]
17
+ def cep(body, options = {})
18
+ request("cep", body, options)
19
+ end
20
+
21
+ # Bairros de uma cidade: `POST /cep/bairros`.
22
+ #
23
+ # @return [Object]
24
+ def bairros(body, options = {})
25
+ request("bairros", body, options)
26
+ end
27
+
28
+ # Cidades de um estado: `POST /cep/cidades`.
29
+ #
30
+ # @return [Object]
31
+ def cidades(body, options = {})
32
+ request("cidades", body, options)
33
+ end
34
+
35
+ # Cidades por DDD: `POST /cep/cidadesPorDDD`.
36
+ #
37
+ # @return [Object]
38
+ def cidades_por_ddd(body, options = {})
39
+ request("cidadesPorDDD", body, options)
40
+ end
41
+
42
+ # Estados: `POST /cep/estados`.
43
+ #
44
+ # @return [Object]
45
+ def estados(body = nil, options = {})
46
+ request("estados", body, options)
47
+ end
48
+
49
+ # Distancia entre CEPs: `POST /cep/distancia/calcular`.
50
+ #
51
+ # @return [Object]
52
+ def distancia(body, options = {})
53
+ request("distancia/calcular", body, options)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # Chip virtual: `/chip/virtual/*`.
9
+ class ChipVirtualService < BaseService
10
+ # Lista operadoras: `POST /chip/virtual/operators`.
11
+ #
12
+ # @return [Object]
13
+ def operators(body = nil, options = {})
14
+ post("/chip/virtual/operators", body, options)
15
+ end
16
+
17
+ # Compra um numero: `POST /chip/virtual/buy`.
18
+ #
19
+ # @return [Object]
20
+ def buy(body, options = {})
21
+ post("/chip/virtual/buy", body, options)
22
+ end
23
+
24
+ # Consulta ativacao: `POST /chip/virtual/activation`.
25
+ #
26
+ # @return [Object]
27
+ def activation(body, options = {})
28
+ post("/chip/virtual/activation", body, options)
29
+ end
30
+
31
+ # Lista servicos: `POST /chip/virtual/services`.
32
+ #
33
+ # @return [Object]
34
+ def services(body = nil, options = {})
35
+ post("/chip/virtual/services", body, options)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # Consultas por credito (`/consulta/{servico}/credits` e afins).
9
+ #
10
+ # Nao usam `DeviceToken` - debitam o saldo/creditos da conta.
11
+ # O campo `tipo` do body define o produto consultado (ex: `lista-socios`,
12
+ # `serasa-score-pf`, `spc-serasa`) - a lista completa esta em
13
+ # `ApiBrasil::Generated::Catalog::CONSULTA_TIPOS`. Use `homolog: true`
14
+ # para sandbox.
15
+ class ConsultaService < BaseService
16
+ # Consulta generica: `POST /consulta/{service}/credits`.
17
+ #
18
+ # @return [Object]
19
+ def generic(service, body = {}, options = {})
20
+ post("/consulta/#{service}/credits", body, options)
21
+ end
22
+
23
+ # Creditos disponiveis de um servico: `GET /consulta/{service}/credits`.
24
+ #
25
+ # @return [Object]
26
+ def credits(service, options = {})
27
+ get("/consulta/#{service}/credits", options)
28
+ end
29
+
30
+ # Consulta CPF: `POST /consulta/cpf/credits`.
31
+ #
32
+ # @return [Object]
33
+ def cpf(body, options = {})
34
+ generic("cpf", body, options)
35
+ end
36
+
37
+ # Consulta CNPJ: `POST /consulta/cnpj/credits` (ex: `tipo: "lista-socios"`).
38
+ #
39
+ # @return [Object]
40
+ def cnpj(body, options = {})
41
+ generic("cnpj", body, options)
42
+ end
43
+
44
+ # Consulta CNH: `POST /consulta/cnh/credits`.
45
+ #
46
+ # @return [Object]
47
+ def cnh(body, options = {})
48
+ generic("cnh", body, options)
49
+ end
50
+
51
+ # Consulta CEP: `POST /consulta/cep/credits`.
52
+ #
53
+ # @return [Object]
54
+ def cep(body, options = {})
55
+ generic("cep", body, options)
56
+ end
57
+
58
+ # Consulta veicular: `POST /consulta/veiculos/credits`.
59
+ #
60
+ # @return [Object]
61
+ def veiculos(body, options = {})
62
+ generic("veiculos", body, options)
63
+ end
64
+
65
+ # Consulta operadora de telefone: `POST /consulta/telefone/credits`.
66
+ #
67
+ # @return [Object]
68
+ def telefone(body, options = {})
69
+ generic("telefone", body, options)
70
+ end
71
+
72
+ # Consulta veicular nas bases dedicadas:
73
+ # `POST /vehicles/base/000/dados` | `POST /vehicles/base/000/fipe`.
74
+ #
75
+ # @param base [String] `dados` ou `fipe`
76
+ # @return [Object]
77
+ def veiculos_base(base, body, options = {})
78
+ post("/vehicles/base/000/#{base}", body, options)
79
+ end
80
+
81
+ # Distancia entre CEPs: `POST /cep/distancia/calcular`.
82
+ #
83
+ # @return [Object]
84
+ def cep_distancia(body, options = {})
85
+ post("/cep/distancia/calcular", body, options)
86
+ end
87
+
88
+ # Proxy seller: `POST /proxy/seller/credits`.
89
+ #
90
+ # @return [Object]
91
+ def proxy_seller(body = {}, options = {})
92
+ post("/proxy/seller/credits", body, options)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../device_proxy_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # Correios (device-based): `/correios/{action}`.
9
+ class CorreiosService < DeviceProxyService
10
+ def initialize(http)
11
+ super(http, "correios")
12
+ end
13
+
14
+ # Rastreio de encomendas: `POST /correios/rastreio` body `{"code" => ...}`.
15
+ #
16
+ # @return [Object]
17
+ def rastreio(body, options = {})
18
+ request("rastreio", body, options)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../device_proxy_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # Dados cadastrais (device-based): `/dados/{action}`.
9
+ class DadosService < DeviceProxyService
10
+ def initialize(http)
11
+ super(http, "dados")
12
+ end
13
+
14
+ # Consulta CNPJ: `POST /dados/cnpj` body `{"cnpj" => ...}`.
15
+ #
16
+ # @return [Object]
17
+ def cnpj(body, options = {})
18
+ request("cnpj", body, options)
19
+ end
20
+
21
+ # Consulta CPF: `POST /dados/cpf` body `{"cpf" => ...}`.
22
+ #
23
+ # @return [Object]
24
+ def cpf(body, options = {})
25
+ request("cpf", body, options)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # GeoIP (device-based): `POST /database/ip`.
9
+ class DatabaseIpService < BaseService
10
+ # Consulta a base de IPs: `POST /database/ip` body `{"ip" => ...}`.
11
+ #
12
+ # @return [Object]
13
+ def ip(body = nil, options = {})
14
+ post("/database/ip", body, options)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../device_proxy_service"
4
+
5
+ module ApiBrasil
6
+ module Services
7
+ module Data
8
+ # Tabela FIPE (device-based): `/fipe/{action}` (marcas, modelos, anos, preco...).
9
+ #
10
+ # As actions documentadas estao em
11
+ # `ApiBrasil::Generated::Catalog.service_actions("fipe")`.
12
+ class FipeService < DeviceProxyService
13
+ def initialize(http)
14
+ super(http, "fipe")
15
+ end
16
+
17
+ # Tabela de referencia: `POST /fipe/ConsultarTabelaDeReferencia`.
18
+ #
19
+ # @return [Object]
20
+ def tabela_referencia(body = nil, options = {})
21
+ request("ConsultarTabelaDeReferencia", body, options)
22
+ end
23
+
24
+ # Marcas: `POST /fipe/ConsultarMarcas`.
25
+ #
26
+ # @return [Object]
27
+ def marcas(body, options = {})
28
+ request("ConsultarMarcas", body, options)
29
+ end
30
+
31
+ # Modelos: `POST /fipe/ConsultarModelos`.
32
+ #
33
+ # @return [Object]
34
+ def modelos(body, options = {})
35
+ request("ConsultarModelos", body, options)
36
+ end
37
+
38
+ # Anos de um modelo: `POST /fipe/ConsultarAnoModelo`.
39
+ #
40
+ # @return [Object]
41
+ def ano_modelo(body, options = {})
42
+ request("ConsultarAnoModelo", body, options)
43
+ end
44
+
45
+ # Modelos de um ano: `POST /fipe/ConsultarModelosAtravesDoAno`.
46
+ #
47
+ # @return [Object]
48
+ def modelos_por_ano(body, options = {})
49
+ request("ConsultarModelosAtravesDoAno", body, options)
50
+ end
51
+
52
+ # Valor com todos os parametros: `POST /fipe/ConsultarValorComTodosParametros`.
53
+ #
54
+ # @return [Object]
55
+ def valor(body, options = {})
56
+ request("ConsultarValorComTodosParametros", body, options)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end