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 +4 -4
- data/.gitignore +6 -1
- data/Gemfile +7 -2
- data/Gemfile.lock +5 -2
- data/README.md +41 -1
- data/lib/bs2_api/entities/async_request.rb +45 -0
- data/lib/bs2_api/entities/async_response.rb +39 -0
- data/lib/bs2_api/entities/async_status.rb +73 -0
- data/lib/bs2_api/entities/pix_key.rb +1 -1
- data/lib/bs2_api/payment/async.rb +105 -0
- data/lib/bs2_api/payment/base.rb +27 -23
- data/lib/bs2_api/payment/detail.rb +21 -7
- data/lib/bs2_api/pix/detail.rb +52 -0
- data/lib/bs2_api/refund/pix/create.rb +56 -0
- data/lib/bs2_api/refund/pix/detail.rb +58 -0
- data/lib/bs2_api/request/auth.rb +38 -11
- data/lib/bs2_api/version.rb +1 -1
- data/lib/bs2_api.rb +15 -6
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ba55ce23aae59313a798b0b5d983e29b7a5ef279810d795b513b99888196811
|
4
|
+
data.tar.gz: c61832cf0382e1d9b1be22615963303d6f3c4e8bfdf2fe217cd2292e4082a5a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b5a00b54f7c859977f81041da155713e625988f5432c76e6f3d8d6c5f1448594685e6c7933690cabae03c5cec08a35c4f22a07fec4e7908ab5d0226fca9e746
|
7
|
+
data.tar.gz: 9c74747a9be8e1f0b064e46de4a8a8345c1f162417e7c155fabeab98f3c00999f0e712bb942c2f4599d0e584c33c3d92e675df0beb71a015d37f6a71b270681e
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bs2_api (1.2
|
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
|
-
|
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
|
@@ -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
|
data/lib/bs2_api/payment/base.rb
CHANGED
@@ -16,29 +16,33 @@ module Bs2Api
|
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
}
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
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
|
-
|
23
|
-
|
24
|
-
|
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
|
data/lib/bs2_api/request/auth.rb
CHANGED
@@ -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[
|
13
|
-
raise Bs2Api::Errors::BadRequest, response[
|
14
|
-
raise Bs2Api::Errors::ServerError, response.body
|
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[
|
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:
|
27
|
-
password:
|
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:
|
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
|
-
|
76
|
+
end
|
50
77
|
end
|
51
78
|
end
|
52
79
|
end
|
data/lib/bs2_api/version.rb
CHANGED
data/lib/bs2_api.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
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.
|
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-
|
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
|