bs2_api 1.2.2 → 1.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 175c6176282d4442f464f85434429c42278b5fd0553cd2a4ac03fc65fe813096
4
- data.tar.gz: 6a5edaca9bc8aefcebd1a00699faaf0615c44816290cf0c87e4d14a4a4d74bc9
3
+ metadata.gz: 7ba55ce23aae59313a798b0b5d983e29b7a5ef279810d795b513b99888196811
4
+ data.tar.gz: c61832cf0382e1d9b1be22615963303d6f3c4e8bfdf2fe217cd2292e4082a5a3
5
5
  SHA512:
6
- metadata.gz: 11ed0de57717ada3d4cc18e9859c8d323eca009fea97086bbee877e1052ced9bc8c2e014cb9cd1c7478a0a61852653e1c7c563a8cbfd518a8a81e6e45dfed6db
7
- data.tar.gz: e95bc5444784271372d3d2be1e3246ac47cf81a9667cbe7c3fe668490fa5171234dbbf69ab02c95fe54b5cf5a3113d7561684dc64977779408cbc24b3c19326b
6
+ metadata.gz: 9b5a00b54f7c859977f81041da155713e625988f5432c76e6f3d8d6c5f1448594685e6c7933690cabae03c5cec08a35c4f22a07fec4e7908ab5d0226fca9e746
7
+ data.tar.gz: 9c74747a9be8e1f0b064e46de4a8a8345c1f162417e7c155fabeab98f3c00999f0e712bb942c2f4599d0e584c33c3d92e675df0beb71a015d37f6a71b270681e
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.3.2)
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.
@@ -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,52 @@
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
+
23
+ access_token = Bs2Api::Request::Auth.token(
24
+ client_id: @client_id,
25
+ client_secret: @client_secret
26
+ )
27
+
28
+ response = HTTParty.get(
29
+ url,
30
+ http_proxyaddr: @proxy&.host,
31
+ http_proxyport: @proxy&.port,
32
+ http_proxyuser: @proxy&.user,
33
+ http_proxypass: @proxy&.password,
34
+ headers: {
35
+ 'Content-Type' => 'application/json',
36
+ 'Accept' => 'application/json',
37
+ 'Authorization' => "Bearer #{access_token}",
38
+ },
39
+ query: {
40
+ Inicio: @time_range.begin.iso8601,
41
+ Fim: @time_range.end.iso8601,
42
+ TxId: @transaction_id,
43
+ }
44
+ )
45
+
46
+ raise response.body unless response.success?
47
+
48
+ response.body
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,56 @@
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
+ # TODO: is PUT the right method?
33
+ response = HTTParty.put(
34
+ url,
35
+ http_proxyaddr: @proxy&.host,
36
+ http_proxyport: @proxy&.port,
37
+ http_proxyuser: @proxy&.user,
38
+ http_proxypass: @proxy&.password,
39
+ headers: {
40
+ 'Content-Type' => 'application/json',
41
+ 'Accept' => 'application/json',
42
+ 'Authorization' => "Bearer #{access_token}",
43
+ },
44
+ body: {
45
+ valor: value
46
+ }.to_json
47
+ )
48
+
49
+ raise response.body unless response.success?
50
+
51
+ response.body
52
+ end
53
+ end
54
+ end
55
+ end
56
+ 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.0'
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,28 @@ 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'
29
33
 
30
34
  require 'bs2_api/payment/base'
31
35
  require 'bs2_api/payment/key'
32
36
  require 'bs2_api/payment/manual'
33
37
  require 'bs2_api/payment/confirmation'
34
38
  require 'bs2_api/payment/detail'
39
+ require 'bs2_api/payment/async'
35
40
 
36
41
  require 'bs2_api/request/auth'
37
42
 
43
+
44
+ require 'bs2_api/refund/pix/create'
45
+ require 'bs2_api/refund/pix/detail'
46
+
38
47
  module Bs2Api
39
48
  ENDPOINT = {
40
49
  production: 'https://api.bs2.com',
41
50
  sandbox: 'https://apihmz.bancobonsucesso.com.br'
42
- }
51
+ }.freeze
43
52
 
44
53
  class << self
45
54
  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.0
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-29 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