bs2_api 1.2.2 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 175c6176282d4442f464f85434429c42278b5fd0553cd2a4ac03fc65fe813096
4
- data.tar.gz: 6a5edaca9bc8aefcebd1a00699faaf0615c44816290cf0c87e4d14a4a4d74bc9
3
+ metadata.gz: 9bd1ef702376f17fa811965d2f0d46551dcbfba7743ed8c35557c81c719d07db
4
+ data.tar.gz: deed5c8e1e0df62bade820bafa7adb7603d3a377ffb1b9ba5319e97ffe056bf4
5
5
  SHA512:
6
- metadata.gz: 11ed0de57717ada3d4cc18e9859c8d323eca009fea97086bbee877e1052ced9bc8c2e014cb9cd1c7478a0a61852653e1c7c563a8cbfd518a8a81e6e45dfed6db
7
- data.tar.gz: e95bc5444784271372d3d2be1e3246ac47cf81a9667cbe7c3fe668490fa5171234dbbf69ab02c95fe54b5cf5a3113d7561684dc64977779408cbc24b3c19326b
6
+ metadata.gz: d100b1a6e5336ae4f56cecc5c3bd01b2e91b97238260c4ad9d6138f1335c7ddf3c09f963ad7bb76f9696fc3693ff342e2a6a7b2b6c8759af3add3286569f98b4
7
+ data.tar.gz: 7f9d349b5416f0230f1e5cd416f0f18fb0a57c4aeac52e8963f8f504e5feafa1ba81ffc8a6a8cf7e3556018a70bfc7b3adada7aba97c4f53d56b1a254fa7d1de
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /vendor/
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
@@ -13,5 +14,9 @@
13
14
  *.gem
14
15
 
15
16
  .env.test
17
+ .env.*.local
16
18
 
17
- /.idea/
19
+ /.idea/
20
+ *.swp
21
+ *.swo
22
+ .byebug_history
data/Gemfile CHANGED
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
- gemspec
5
+ group :development, :test do
6
+ gem 'factory_bot', '~> 6.1'
7
+ gem 'pry-byebug', '~> 3.7'
8
+ end
9
+
10
+ gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bs2_api (1.2.1)
4
+ bs2_api (1.4.1)
5
5
  activesupport
6
6
  builder
7
7
  bundler
@@ -26,6 +26,8 @@ GEM
26
26
  rexml
27
27
  diff-lcs (1.4.4)
28
28
  dotenv (2.7.6)
29
+ factory_bot (6.2.1)
30
+ activesupport (>= 5.0.0)
29
31
  hashdiff (1.0.1)
30
32
  httparty (0.18.1)
31
33
  mime-types (~> 3.0)
@@ -80,7 +82,8 @@ PLATFORMS
80
82
  DEPENDENCIES
81
83
  bs2_api!
82
84
  dotenv (~> 2.7, >= 2.7.6)
83
- pry-byebug (~> 3.9)
85
+ factory_bot (~> 6.1)
86
+ pry-byebug (~> 3.7)
84
87
  rspec (~> 3.10)
85
88
  uuid (~> 2.3, >= 2.3.9)
86
89
  vcr (~> 6.0)
data/README.md CHANGED
@@ -147,6 +147,46 @@ payment.class
147
147
  => Bs2Api::Entities::Payment
148
148
  ```
149
149
 
150
+
151
+ ### Async API
152
+ Add initial asyc BS2 API implementation.
153
+
154
+ The API allows to pass multiple request all at once. In order to do so you must:
155
+ 1. Create `Bs2Api::Payment::Async`
156
+ 2. Create one or more PIX keys
157
+ 3. For each PIX key create `Bs2Api::Entities::AsyncRequest` passing in the PIX key, internal identifier and the value of the transaction
158
+ 4. Add each async request to the async payment via `Bs2Api::Payment::Async#add_request`
159
+ 5. When all requests are added call `Bs2Api::Payment::Async#call`
160
+ 6. In the response you will get list of payments of type `Bs2Api::Entities::AsyncResponse` whose confirmation will be sent via webhook
161
+ 6.1 If even one of the requests has invalid data, the response will be 400 and we won't get anything via webhook
162
+ 7. If the response from 6 was 202 but we don't get a webhook notification we should start polling the response manually. This is done by calling `Bs2Api::Payment::Async::check_payment_status`. It has one parameter the `Bs2Api::Entities::AsyncResponse#request_id`.The result from this will be `Bs2Api::Entities::AsyncStatus`, using it you can check if the payment was rejected or confirmed.
163
+
164
+ ```ruby
165
+ pix_key = Bs2Api::Entities::PixKey.new(
166
+ key: 'joao@gmail.com',
167
+ type: 'EMAIL'
168
+ )
169
+
170
+ async_request = Bs2Api::Entities::AsyncRequest.new(
171
+ pix_key: pix_key,
172
+ value: 10.0,
173
+ identificator: 'payment1'
174
+ )
175
+
176
+ async_payment = Bs2Api::Payment::Async.new
177
+ async_payment.add_request(async_request)
178
+
179
+ response_list = async_payment.call
180
+
181
+ # Wait for webhook if notification does not arrive (for example for the first item)
182
+ response_status = Bs2Api::Payment::Async.check_payment_status(response_list[0].request_id)
183
+
184
+ # Check the status
185
+ if response_status.rejected?
186
+ puts response_status.rejection_description
187
+ end
188
+ ```
189
+
150
190
  ### Classes de erros:
151
191
  ```ruby
152
192
  # Todos erros herdam de:
@@ -166,4 +206,4 @@ Bs2Api::Errors::Unauthorized
166
206
 
167
207
  ### Observações
168
208
  - Método `call` retorna o próprio objeto
169
- - Em caso de retorno diferente de sucesso na comunicação com a API do Bs2, um erro sempre será lançado.
209
+ - Em caso de retorno diferente de sucesso na comunicação com a API do Bs2, um erro sempre será lançado.
@@ -14,4 +14,4 @@ class Configuration
14
14
 
15
15
  true
16
16
  end
17
- end
17
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs2Api
4
+ module Entities
5
+ # Used by Bs2Api::Payment::Async. This class stores
6
+ # PIX key, user defined identificador for the key and
7
+ # the value to be transfered. Bs2Api::Payment::Async
8
+ # sends a bucket of AsyncRequest and in the response
9
+ # we get a list of passed payments. The identificador
10
+ # can be used to keep track of the transactino in the
11
+ # response.
12
+ class AsyncRequest
13
+ attr_accessor :identificator, :pix_key, :value
14
+
15
+ ALLOWED_PIX_KEY_TYPES = %w[
16
+ CPF
17
+ CNPJ
18
+ EMAIL
19
+ EVP
20
+ ].freeze
21
+
22
+ def initialize(args = {})
23
+ @pix_key = args[:pix_key]
24
+ raise Errors::InvalidPixKey unless ALLOWED_PIX_KEY_TYPES.include? @pix_key.type
25
+
26
+ @identificator = args.fetch(:identificator)
27
+ @value = args[:value]
28
+ end
29
+
30
+ def to_hash
31
+ ActiveSupport::HashWithIndifferentAccess.new(
32
+ {
33
+ identificador: @identificator,
34
+ chave: @pix_key.to_hash,
35
+ valor: @value
36
+ }
37
+ )
38
+ end
39
+
40
+ def to_json(*)
41
+ to_hash.to_json
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs2Api
4
+ module Entities
5
+ # After we send async payment request via calling Bs2Api::Payment::Async#call
6
+ # the API is expected to return array of JSON objects describing each payment
7
+ # this class is used to wrap those JSON objects
8
+ # identificator is optional and is for internal purposes it won't be sent via
9
+ # the webhook when the payment confirmation is done.
10
+ # request_id is the id of the payment which the bank will send via webhook
11
+ class AsyncResponse
12
+ attr_accessor :identificator, :pix_key, :value, :error, :request_id
13
+
14
+ class << self
15
+ def from_response(input_hash)
16
+ pix_key = PixKey.new(
17
+ key: input_hash['chave']['valor'],
18
+ type: input_hash['chave']['tipo']
19
+ )
20
+ AsyncResponse.new(
21
+ identificator: input_hash['identificador'],
22
+ pix_key: pix_key,
23
+ value: input_hash['valor'],
24
+ error: input_hash['erros'],
25
+ request_id: input_hash['solicitacaoId']
26
+ )
27
+ end
28
+ end
29
+
30
+ def initialize(args = {})
31
+ @identificator = args.fetch(:identificator, '')
32
+ @pix_key = args[:pix_key]
33
+ @value = args[:value]
34
+ @error = args[:error]
35
+ @request_id = args[:request_id]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs2Api
4
+ module Entities
5
+ # Used with Bs2Api::Payment::Async. When we call
6
+ # Bs2Api::Payment::Async#call we expect to get data for each
7
+ # item in the bucket via webhook. If we don't get webhooks in
8
+ # a few seconds (roughly about 10s) we should start polling the
9
+ # status of the payment by calling # Bs2Api::Payment::Async::check_payment_status.
10
+ # The following # class is used to wrap the result of
11
+ # Bs2Api::Payment::Async::check_payment_status
12
+ class AsyncStatus
13
+ attr_accessor :request_id, :payment_id, :end_to_end_id, :status,
14
+ :agency, :number, :pix_key, :value, :free_field,
15
+ :rejection_description, :error_description
16
+
17
+ class << self
18
+ # Parses the has from the response body of
19
+ # Bs2Api::Payment::Async::check_payment_status
20
+ # @param[Hash] The response body as a hash with string keys
21
+ def from_response(hash)
22
+ new(
23
+ request_id: hash['solicitacaoId'],
24
+ payment_id: hash['pagamentoId'],
25
+ end_to_end_id: hash['endToEndId'],
26
+ status: STATUS[hash['status']],
27
+ agency: hash['agencia'],
28
+ number: hash['numero'],
29
+ pix_key: Bs2Api::Entities::PixKey.from_response(hash['chave']),
30
+ value: hash['valor'],
31
+ free_field: hash['campoLivre'],
32
+ rejection_description: hash['rejeitadoDescricao'],
33
+ error_description: hash['erroDescricao']
34
+ )
35
+ end
36
+ end
37
+
38
+ STATUS = {
39
+ 'Realizado' => :awaiting_validation,
40
+ 'Iniciado' => :in_process,
41
+ 'Confirmado' => :confirmed,
42
+ 'Rejeitado' => :rejected,
43
+ 'Erro' => :error
44
+ }.freeze
45
+
46
+ def initialize(args = {})
47
+ @request_id = args[:request_id]
48
+ @payment_id = args[:payment_id]
49
+ @end_to_end_id = args[:end_to_end_id]
50
+ @status = args[:status]
51
+ @agency = args[:agency]
52
+ @number = args[:number]
53
+ @pix_key = args[:pix_key]
54
+ @value = args[:value]
55
+ @free_field = args[:free_field]
56
+ @rejection_description = args[:rejection_description]
57
+ @error_description = args[:error_description]
58
+ end
59
+
60
+ def rejected?
61
+ @status == :rejected
62
+ end
63
+
64
+ def confirmed?
65
+ @status == :confirmed
66
+ end
67
+
68
+ def error?
69
+ @status == :error
70
+ end
71
+ end
72
+ end
73
+ end
@@ -11,7 +11,7 @@ module Bs2Api
11
11
  phone: 'PHONE',
12
12
  email: 'EMAIL',
13
13
  random: 'EVP'
14
- }
14
+ }.freeze
15
15
 
16
16
  def initialize(args = {})
17
17
  @key = args.fetch(:key, nil)
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs2Api
4
+ module Payment
5
+ # Class used to store a bucket of requests which will be sent
6
+ # altogether.
7
+ class Async < Base
8
+ attr_reader :requests
9
+
10
+ class << self
11
+ # Check the status of a request manually. Usually we will be notified
12
+ # via webhook, but in case we do not get notification for a specific
13
+ # payment we need to start to poll the BS2 API manually.
14
+ #
15
+ # @param[String] request_id The id (SolicitacaoId) for the payment
16
+ # returned by Bs2Api::Payment::Async#call
17
+ # @param[String] client_id ID of the client issued by BS2 used for
18
+ # authorizatino. Optional, if not passed the default will be used
19
+ # @param[String] client_secret The password for the account with
20
+ # id client_id. Optional, if not passed the default will be used.
21
+ def check_payment_status(
22
+ request_id,
23
+ client_id: Bs2Api.configuration.client_id,
24
+ client_secret: Bs2Api.configuration.client_secret
25
+ )
26
+ url = request_status_url(request_id)
27
+ bearer_token = Bs2Api::Request::Auth.token(
28
+ client_id: client_id,
29
+ client_secret: client_secret
30
+ )
31
+ headers = { 'Authorization': "Bearer #{bearer_token}" }
32
+ response = HTTParty.get(url, headers: headers)
33
+ Bs2Api::Entities::AsyncStatus.from_response response.parsed_response
34
+ end
35
+
36
+ private
37
+
38
+ # The url where one can manually check the status of an async request
39
+ #
40
+ # @param[String] request_id The id (SolicitacaoId) for the payment
41
+ # returned by Bs2Api::Payment::Async#call
42
+ def request_status_url(request_id)
43
+ "#{Bs2Api.endpoint}/pix/direto/forintegration/v1/pagamentos/chave/solicitacoes/#{request_id}"
44
+ end
45
+ end
46
+
47
+ def initialize(
48
+ client_id: Bs2Api.configuration.client_id,
49
+ client_secret: Bs2Api.configuration.client_secret
50
+ )
51
+ @client_id = client_id
52
+ @client_secret = client_secret
53
+ @requests = []
54
+ end
55
+
56
+ # Push request into the request bucker. This will not send the request.
57
+ # When Bs2Api::Payment::Async#call is called all requeststs from the bucket
58
+ # will be sent simultaneously
59
+ #
60
+ # @param[Bs2Api::Entities::AsyncRequest] The async request which is going
61
+ # to be placed in the bucket
62
+ def add_request(request)
63
+ @requests << request
64
+ end
65
+
66
+ # Get the size of the bucket list
67
+ def requests_count
68
+ @requests.length
69
+ end
70
+
71
+ # The response from call differs from Payment::Base#call because
72
+ # for the async method we get 202 and a list of payment transactions IDs
73
+ # Later on we will notified via webhook for all payments transactions
74
+ # which were successful.
75
+ #
76
+ # @important The API call will fail if even one of the bucket items has
77
+ # data (PIX key, value, etc).
78
+ #
79
+ # @return[Hash] List of payments which we should expect to be confirmed via
80
+ # webhook. The response will contain field "SolicitacaoId" genreated by BS2
81
+ # this ID is used to match the payment in the webhook
82
+ def call
83
+ response = post_request
84
+ raise Bs2Api::Errors::BadRequest, ::Util::Response.parse_error(response) unless response.code == 202
85
+
86
+ response.parsed_response.map do |async_response|
87
+ Bs2Api::Entities::AsyncResponse.from_response(async_response)
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ # The url which will be called in order to send the bucket request for processing
94
+ def url
95
+ "#{Bs2Api.endpoint}/pix/direto/forintegration/v1/pagamentos/chave/solicitacoes"
96
+ end
97
+
98
+ def payload
99
+ {
100
+ "solicitacoes": @requests
101
+ }
102
+ end
103
+ end
104
+ end
105
+ end
@@ -16,29 +16,33 @@ module Bs2Api
16
16
  end
17
17
 
18
18
  private
19
- def post_request
20
- HTTParty.post(url, headers: headers, body: payload.to_json)
21
- end
22
-
23
- def headers
24
- {
25
- "Content-Type": "application/json",
26
- "Accept": "application/json",
27
- "Authorization": "Bearer #{bearer_token}"
28
- }
29
- end
30
-
31
- def bearer_token
32
- Bs2Api::Request::Auth.token
33
- end
34
-
35
- def payload
36
- raise NoMethodError, "Missing #{__method__} to #{self.class}"
37
- end
38
-
39
- def url
40
- raise NoMethodError, "Missing #{__method__} to #{self.class}"
41
- end
19
+
20
+ def post_request
21
+ HTTParty.post(url, headers: headers, body: payload.to_json)
22
+ end
23
+
24
+ def headers
25
+ {
26
+ 'Content-Type': 'application/json',
27
+ 'Accept': 'application/json',
28
+ 'Authorization': "Bearer #{bearer_token}"
29
+ }
30
+ end
31
+
32
+ def bearer_token
33
+ Bs2Api::Request::Auth.token(
34
+ client_id: @client_id || Bs2Api.configuration.client_id,
35
+ client_secret: @client_secret || Bs2Api.configuration.client_secret
36
+ )
37
+ end
38
+
39
+ def payload
40
+ raise NoMethodError, "Missing #{__method__} to #{self.class}"
41
+ end
42
+
43
+ def url
44
+ raise NoMethodError, "Missing #{__method__} to #{self.class}"
45
+ end
42
46
  end
43
47
  end
44
48
  end
@@ -3,7 +3,13 @@ module Bs2Api
3
3
  class Detail < Base
4
4
  attr_reader :success
5
5
 
6
- def initialize payment_id
6
+ def initialize(
7
+ payment_id,
8
+ client_id: Bs2Api.configuration.client_id,
9
+ client_secret: Bs2Api.configuration.client_secret
10
+ )
11
+ @client_id = client_id
12
+ @client_secret = client_secret
7
13
  @payment_id = payment_id
8
14
  end
9
15
 
@@ -15,13 +21,21 @@ module Bs2Api
15
21
  end
16
22
 
17
23
  private
18
- def url
19
- "#{Bs2Api.endpoint}/pix/direto/forintegration/v1/pagamentos/#{@payment_id}"
20
- end
21
24
 
22
- def detail_request
23
- HTTParty.get(url, headers: headers)
24
- end
25
+ def url
26
+ "#{Bs2Api.endpoint}/pix/direto/forintegration/v1/pagamentos/#{@payment_id}"
27
+ end
28
+
29
+ def detail_request
30
+ HTTParty.get(url, headers: headers)
31
+ end
32
+
33
+ def bearer_token
34
+ Bs2Api::Request::Auth.token(
35
+ client_id: @client_id,
36
+ client_secret: @client_secret
37
+ )
38
+ end
25
39
  end
26
40
  end
27
41
  end
@@ -0,0 +1,51 @@
1
+ module Bs2Api
2
+ module Pix
3
+ class Detail
4
+ def initialize(
5
+ client_id:,
6
+ client_secret:,
7
+ end_to_end_id:,
8
+ time_range:,
9
+ transaction_id: nil,
10
+ proxy: nil
11
+ )
12
+ @client_id = client_id
13
+ @client_secret = client_secret
14
+ @end_to_end_id = end_to_end_id
15
+ @time_range = time_range
16
+ @transaction_id = transaction_id
17
+ @proxy = proxy
18
+ end
19
+
20
+ def call
21
+ url = "#{Bs2Api.endpoint}/pix/direto/forintegration/v1/recebimentos/#{@end_to_end_id}/recebimento"
22
+ access_token = Bs2Api::Request::Auth.token(
23
+ client_id: @client_id,
24
+ client_secret: @client_secret
25
+ )
26
+
27
+ response = HTTParty.get(
28
+ url,
29
+ http_proxyaddr: @proxy&.host,
30
+ http_proxyport: @proxy&.port,
31
+ http_proxyuser: @proxy&.user,
32
+ http_proxypass: @proxy&.password,
33
+ headers: {
34
+ 'Content-Type' => 'application/json',
35
+ 'Accept' => 'application/json',
36
+ 'Authorization' => "Bearer #{access_token}",
37
+ },
38
+ query: {
39
+ Inicio: @time_range.begin.iso8601,
40
+ Fim: @time_range.end.iso8601,
41
+ TxId: @transaction_id,
42
+ }
43
+ )
44
+
45
+ raise response.body unless response.success?
46
+
47
+ response.body
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs2Api
4
+ module Refund
5
+ module Pix
6
+ class Create
7
+ def initialize(
8
+ client_id:,
9
+ client_secret:,
10
+ end_to_end_id:,
11
+ transaction_id:,
12
+ value:,
13
+ proxy: nil
14
+ )
15
+ @client_id = client_id
16
+ @client_secret = client_secret
17
+ @end_to_end_id = end_to_end_id
18
+ @transaction_id = transaction_id
19
+ @value = value
20
+ @proxy = proxy
21
+ end
22
+
23
+ # https://devs.bs2.com/manual/pix-clientes/#tag/Devolucoes-Cliente/paths/~1pix~1direto~1forintegration~1v1~1pix~1{e2eid}~1devolucao~1{idExterno}/put
24
+ def call
25
+ url = "#{Bs2Api.endpoint}/pix/direto/forintegration/v1/pix/#{@end_to_end_id}/devolucao/#{@transaction_id}"
26
+
27
+ access_token = Bs2Api::Request::Auth.token(
28
+ client_id: @client_id,
29
+ client_secret: @client_secret
30
+ )
31
+
32
+ response = HTTParty.put(
33
+ url,
34
+ http_proxyaddr: @proxy&.host,
35
+ http_proxyport: @proxy&.port,
36
+ http_proxyuser: @proxy&.user,
37
+ http_proxypass: @proxy&.password,
38
+ headers: {
39
+ 'Content-Type' => 'application/json',
40
+ 'Accept' => 'application/json',
41
+ 'Authorization' => "Bearer #{access_token}",
42
+ },
43
+ body: {
44
+ valor: @value
45
+ }.to_json
46
+ )
47
+
48
+ raise response.body unless response.success?
49
+
50
+ response.body
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,58 @@
1
+ module Bs2Api
2
+ module Refund
3
+ module Pix
4
+ class Detail
5
+ STATUSES = {
6
+ 'EM_PROCESSAMENTO' => :processing,
7
+ 'DEVOLVIDO' => :refunded,
8
+ 'NAO_REALIZADO' => :not_achieved,
9
+ }.transform_keys(&:downcase).freeze
10
+
11
+ def initialize(
12
+ client_id:,
13
+ client_secret:,
14
+ end_to_end_id:,
15
+ transaction_id:,
16
+ proxy: nil
17
+ )
18
+ @client_id = client_id
19
+ @client_secret = client_secret
20
+ @end_to_end_id = end_to_end_id
21
+ @transaction_id = transaction_id
22
+ @proxy = proxy
23
+ end
24
+
25
+ # https://devs.bs2.com/manual/pix-clientes/#tag/Devolucoes-Cliente/paths/~1pix~1direto~1forintegration~1v1~1pix~1{e2eid}~1devolucao~1{idExterno}/get
26
+ def call
27
+ url = "#{Bs2Api.endpoint}/pix/direto/forintegration/v1/pix/#{@end_to_end_id}/devolucao/#{@transaction_id}"
28
+
29
+ access_token = Bs2Api::Request::Auth.token(
30
+ client_id: @client_id,
31
+ client_secret: @client_secret
32
+ )
33
+
34
+ response = HTTParty.get(
35
+ url,
36
+ http_proxyaddr: @proxy&.host,
37
+ http_proxyport: @proxy&.port,
38
+ http_proxyuser: @proxy&.user,
39
+ http_proxypass: @proxy&.password,
40
+ headers: {
41
+ 'Content-Type' => 'application/json',
42
+ 'Accept' => 'application/json',
43
+ 'Authorization' => "Bearer #{access_token}",
44
+ }
45
+ )
46
+
47
+ raise response.body unless response.success?
48
+
49
+ response.body
50
+ end
51
+
52
+ def status
53
+ @status ||= STATUSES.fetch(call.fetch('status'))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -3,28 +3,55 @@
3
3
  module Bs2Api
4
4
  module Request
5
5
  class Auth
6
+ # TODO: See which scopes are required.
7
+ SCOPES = [
8
+ 'saldo',
9
+ 'extrato',
10
+ 'pagamento',
11
+ 'transferencia',
12
+ 'cobv.write',
13
+ 'cobv.read',
14
+ 'comprovante',
15
+ 'webhook-mov-conta',
16
+ 'aprovacoes',
17
+ 'pagamento-tributo',
18
+ 'webhook-conclusao-transf',
19
+ 'webhook-conclusao-pag',
20
+ 'cob.write',
21
+ 'cob.read',
22
+ 'pix.write',
23
+ 'pix.read',
24
+ 'dict.write',
25
+ 'dict.read',
26
+ 'webhook.read',
27
+ 'webhook.write',
28
+ ].freeze
29
+
6
30
  class << self
7
- def token
31
+ def token(
32
+ client_id: Bs2Api.configuration.client_id,
33
+ client_secret: Bs2Api.configuration.client_secret
34
+ )
8
35
  Bs2Api.configuration.valid?
9
36
 
10
- response = create_session
37
+ response = create_session(client_id, client_secret)
11
38
 
12
- raise Bs2Api::Errors::Unauthorized, response["error_description"] if response.unauthorized?
13
- raise Bs2Api::Errors::BadRequest, response["error_description"] if response.bad_request?
14
- raise Bs2Api::Errors::ServerError, response.body if !response.success?
39
+ raise Bs2Api::Errors::Unauthorized, response['error_description'] if response.unauthorized?
40
+ raise Bs2Api::Errors::BadRequest, response['error_description'] if response.bad_request?
41
+ raise Bs2Api::Errors::ServerError, response.body unless response.success?
15
42
 
16
- response["access_token"]
43
+ response['access_token']
17
44
  end
18
45
 
19
46
  private
20
- def create_session
47
+ def create_session(client_id, client_secret)
21
48
  HTTParty.post(
22
49
  auth_url,
23
50
  headers: headers,
24
51
  body: body,
25
52
  basic_auth: {
26
- username: Bs2Api.configuration.client_id,
27
- password: Bs2Api.configuration.client_secret
53
+ username: client_id,
54
+ password: client_secret
28
55
  }
29
56
  )
30
57
  end
@@ -39,14 +66,14 @@ module Bs2Api
39
66
  def body
40
67
  {
41
68
  grant_type: "client_credentials",
42
- scope: "pix.write pix.read"
69
+ scope: SCOPES.join("\s")
43
70
  }.to_query
44
71
  end
45
72
 
46
73
  def auth_url
47
74
  "#{Bs2Api.endpoint}/auth/oauth/v2/token"
48
75
  end
49
- end
76
+ end
50
77
  end
51
78
  end
52
79
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bs2Api
4
- VERSION = "1.2.2"
4
+ VERSION = '1.4.2'
5
5
  end
data/lib/bs2_api.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require "httparty"
3
- require "active_support/core_ext/hash/indifferent_access"
4
- require "active_support/core_ext/hash/except"
5
- require "active_support/core_ext/object/to_query"
6
- require "active_support/core_ext/object/blank"
2
+
3
+ require 'httparty'
4
+ require 'active_support/core_ext/hash/indifferent_access'
5
+ require 'active_support/core_ext/hash/except'
6
+ require 'active_support/core_ext/object/to_query'
7
+ require 'active_support/core_ext/object/blank'
7
8
 
8
9
  require 'bs2_api/version'
9
10
  require 'bs2_api/configuration'
@@ -26,20 +27,29 @@ require 'bs2_api/entities/bank'
26
27
  require 'bs2_api/entities/customer'
27
28
  require 'bs2_api/entities/payment'
28
29
  require 'bs2_api/entities/pix_key'
30
+ require 'bs2_api/entities/async_request'
31
+ require 'bs2_api/entities/async_response'
32
+ require 'bs2_api/entities/async_status'
33
+
34
+ require 'bs2_api/pix/detail'
29
35
 
30
36
  require 'bs2_api/payment/base'
31
37
  require 'bs2_api/payment/key'
32
38
  require 'bs2_api/payment/manual'
33
39
  require 'bs2_api/payment/confirmation'
34
40
  require 'bs2_api/payment/detail'
41
+ require 'bs2_api/payment/async'
35
42
 
36
43
  require 'bs2_api/request/auth'
37
44
 
45
+ require 'bs2_api/refund/pix/create'
46
+ require 'bs2_api/refund/pix/detail'
47
+
38
48
  module Bs2Api
39
49
  ENDPOINT = {
40
50
  production: 'https://api.bs2.com',
41
51
  sandbox: 'https://apihmz.bancobonsucesso.com.br'
42
- }
52
+ }.freeze
43
53
 
44
54
  class << self
45
55
  attr_writer :configuration
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bs2_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kim Pastro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-27 00:00:00.000000000 Z
11
+ date: 2022-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: builder
@@ -201,6 +201,9 @@ files:
201
201
  - lib/bs2_api.rb
202
202
  - lib/bs2_api/configuration.rb
203
203
  - lib/bs2_api/entities/account.rb
204
+ - lib/bs2_api/entities/async_request.rb
205
+ - lib/bs2_api/entities/async_response.rb
206
+ - lib/bs2_api/entities/async_status.rb
204
207
  - lib/bs2_api/entities/bank.rb
205
208
  - lib/bs2_api/entities/customer.rb
206
209
  - lib/bs2_api/entities/payment.rb
@@ -215,11 +218,15 @@ files:
215
218
  - lib/bs2_api/errors/missing_configuration.rb
216
219
  - lib/bs2_api/errors/server_error.rb
217
220
  - lib/bs2_api/errors/unauthorized.rb
221
+ - lib/bs2_api/payment/async.rb
218
222
  - lib/bs2_api/payment/base.rb
219
223
  - lib/bs2_api/payment/confirmation.rb
220
224
  - lib/bs2_api/payment/detail.rb
221
225
  - lib/bs2_api/payment/key.rb
222
226
  - lib/bs2_api/payment/manual.rb
227
+ - lib/bs2_api/pix/detail.rb
228
+ - lib/bs2_api/refund/pix/create.rb
229
+ - lib/bs2_api/refund/pix/detail.rb
223
230
  - lib/bs2_api/request/auth.rb
224
231
  - lib/bs2_api/util/response.rb
225
232
  - lib/bs2_api/version.rb