starkbank 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.
- checksums.yaml +7 -0
- data/lib/boleto/boleto.rb +186 -0
- data/lib/boleto/log.rb +86 -0
- data/lib/error.rb +44 -0
- data/lib/key.rb +32 -0
- data/lib/ledger/balance.rb +60 -0
- data/lib/ledger/transaction.rb +116 -0
- data/lib/payment/boleto/boleto.rb +152 -0
- data/lib/payment/boleto/log.rb +82 -0
- data/lib/payment/utility/log.rb +81 -0
- data/lib/payment/utility/utility.rb +152 -0
- data/lib/starkbank.rb +22 -0
- data/lib/transfer/log.rb +85 -0
- data/lib/transfer/transfer.rb +143 -0
- data/lib/user/project.rb +32 -0
- data/lib/user/user.rb +24 -0
- data/lib/utils/api.rb +50 -0
- data/lib/utils/cache.rb +10 -0
- data/lib/utils/case.rb +21 -0
- data/lib/utils/checks.rb +81 -0
- data/lib/utils/environment.rb +13 -0
- data/lib/utils/request.rb +77 -0
- data/lib/utils/resource.rb +32 -0
- data/lib/utils/rest.rb +111 -0
- data/lib/utils/url.rb +26 -0
- data/lib/webhook/event.rb +174 -0
- data/lib/webhook/webhook.rb +104 -0
- metadata +96 -0
data/lib/utils/cache.rb
ADDED
data/lib/utils/case.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StarkBank
|
4
|
+
module Utils
|
5
|
+
module Case
|
6
|
+
def self.camel_to_snake(camel)
|
7
|
+
camel.to_s.gsub(/([a-z])([A-Z\d])/, '\1_\2').downcase
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.snake_to_camel(snake)
|
11
|
+
camel = snake.to_s.split('_').map(&:capitalize).join
|
12
|
+
camel[0] = camel[0].downcase
|
13
|
+
camel
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.camel_to_kebab(camel)
|
17
|
+
camel_to_snake(camel).tr('_', '-')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/utils/checks.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('starkbank-ecdsa')
|
4
|
+
require('date')
|
5
|
+
require_relative('../user/user')
|
6
|
+
require_relative('environment')
|
7
|
+
|
8
|
+
module StarkBank
|
9
|
+
module Utils
|
10
|
+
class Checks
|
11
|
+
def self.check_user(user)
|
12
|
+
return user if user.is_a?(StarkBank::User)
|
13
|
+
|
14
|
+
user = user.nil? ? StarkBank.user : user
|
15
|
+
raise(ArgumentError, 'A user is required to access our API. Check our README: https://github.com/starkbank/sdk-ruby/') if user.nil?
|
16
|
+
|
17
|
+
user
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.check_environment(environment)
|
21
|
+
environments = StarkBank::Utils::Environment.constants(false).map { |c| StarkBank::Utils::Environment.const_get(c) }
|
22
|
+
raise(ArgumentError, "Select a valid environment: #{environments.join(', ')}") unless environments.include?(environment)
|
23
|
+
|
24
|
+
environment
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.check_private_key(pem)
|
28
|
+
EllipticCurve::PrivateKey.fromPem(pem)
|
29
|
+
pem
|
30
|
+
rescue
|
31
|
+
raise(ArgumentError, 'Private-key must be a valid secp256k1 ECDSA string in pem format')
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.check_datetime(data)
|
35
|
+
return if data.nil?
|
36
|
+
|
37
|
+
return data if data.is_a?(Time) || data.is_a?(DateTime)
|
38
|
+
|
39
|
+
return Time.new(data.year, data.month, data.day) if data.is_a?(Date)
|
40
|
+
|
41
|
+
check_datetime_string(data)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.check_date(data)
|
45
|
+
return if data.nil?
|
46
|
+
|
47
|
+
return Date.new(data.year, data.month, data.day) if data.is_a?(Time) || data.is_a?(DateTime)
|
48
|
+
|
49
|
+
return data if data.is_a?(Date)
|
50
|
+
|
51
|
+
data = check_datetime_string(data)
|
52
|
+
|
53
|
+
Date.new(data.year, data.month, data.day)
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
private
|
58
|
+
|
59
|
+
def check_datetime_string(data)
|
60
|
+
data = data.to_s
|
61
|
+
|
62
|
+
begin
|
63
|
+
return DateTime.strptime(data, '%Y-%m-%dT%H:%M:%S.%L+00:00')
|
64
|
+
rescue ArgumentError
|
65
|
+
end
|
66
|
+
|
67
|
+
begin
|
68
|
+
return DateTime.strptime(data, '%Y-%m-%dT%H:%M:%S+00:00')
|
69
|
+
rescue ArgumentError
|
70
|
+
end
|
71
|
+
|
72
|
+
begin
|
73
|
+
return DateTime.strptime(data, '%Y-%m-%d')
|
74
|
+
rescue ArgumentError
|
75
|
+
raise(ArgumentError, 'invalid datetime string ' + data)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('json')
|
4
|
+
require('starkbank-ecdsa')
|
5
|
+
require('net/http')
|
6
|
+
require_relative('url')
|
7
|
+
require_relative('checks')
|
8
|
+
require_relative('../error')
|
9
|
+
|
10
|
+
module StarkBank
|
11
|
+
module Utils
|
12
|
+
module Request
|
13
|
+
class Response
|
14
|
+
attr_reader :status, :content
|
15
|
+
def initialize(status, content)
|
16
|
+
@status = status
|
17
|
+
@content = content
|
18
|
+
end
|
19
|
+
|
20
|
+
def json
|
21
|
+
JSON.parse(@content)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.fetch(method:, path:, payload: nil, query: nil, user: nil)
|
26
|
+
user = Checks.check_user(user)
|
27
|
+
|
28
|
+
base_url = {
|
29
|
+
Environment::PRODUCTION => 'https://api.starkbank.com/',
|
30
|
+
Environment::SANDBOX => 'https://sandbox.api.starkbank.com/'
|
31
|
+
}[user.environment] + 'v2'
|
32
|
+
|
33
|
+
url = "#{base_url}/#{path}#{StarkBank::Utils::URL.urlencode(query)}"
|
34
|
+
uri = URI(url)
|
35
|
+
|
36
|
+
access_time = Time.now.to_i
|
37
|
+
body = payload.nil? ? '' : payload.to_json
|
38
|
+
message = "#{user.access_id}:#{access_time}:#{body}"
|
39
|
+
signature = EllipticCurve::Ecdsa.sign(message, user.private_key).toBase64
|
40
|
+
|
41
|
+
case method
|
42
|
+
when 'GET'
|
43
|
+
req = Net::HTTP::Get.new(uri)
|
44
|
+
when 'DELETE'
|
45
|
+
req = Net::HTTP::Delete.new(uri)
|
46
|
+
when 'POST'
|
47
|
+
req = Net::HTTP::Post.new(uri)
|
48
|
+
req.body = body
|
49
|
+
when 'PATCH'
|
50
|
+
req = Net::HTTP::Patch.new(uri)
|
51
|
+
req.body = body
|
52
|
+
when 'PUT'
|
53
|
+
req = Net::HTTP::Put.new(uri)
|
54
|
+
req.body = body
|
55
|
+
else
|
56
|
+
raise(ArgumentError, 'unknown HTTP method ' + method)
|
57
|
+
end
|
58
|
+
|
59
|
+
req['Access-Id'] = user.access_id
|
60
|
+
req['Access-Time'] = access_time
|
61
|
+
req['Access-Signature'] = signature
|
62
|
+
req['Content-Type'] = 'application/json'
|
63
|
+
req['User-Agent'] = "Ruby-#{RUBY_VERSION}-SDK-0.0.1"
|
64
|
+
|
65
|
+
request = Net::HTTP.start(uri.hostname, use_ssl: true) { |http| http.request(req) }
|
66
|
+
|
67
|
+
response = Response.new(Integer(request.code, 10), request.body)
|
68
|
+
|
69
|
+
raise(StarkBank::Error::InternalServerError) if response.status == 500
|
70
|
+
raise(StarkBank::Error::InputErrors, response.json['errors']) if response.status == 400
|
71
|
+
raise(StarkBank::Error::UnknownError, response.content) unless response.status == 200
|
72
|
+
|
73
|
+
response
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StarkBank
|
4
|
+
module Utils
|
5
|
+
class Resource
|
6
|
+
attr_reader :id
|
7
|
+
def initialize(id = nil)
|
8
|
+
@id = id
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
string_vars = []
|
13
|
+
instance_variables.each do |key|
|
14
|
+
value = instance_variable_get(key).to_s.lines.map(&:chomp).join("\n ")
|
15
|
+
string_vars << "#{key[1..-1]}: #{value}"
|
16
|
+
end
|
17
|
+
fields = string_vars.join(",\n ")
|
18
|
+
"#{class_name}(\n #{fields}\n)"
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"#{class_name}[#{@id}]"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def class_name
|
28
|
+
self.class.name.split('::').last.downcase
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/utils/rest.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('request')
|
4
|
+
require_relative('api')
|
5
|
+
|
6
|
+
module StarkBank
|
7
|
+
module Utils
|
8
|
+
module Rest
|
9
|
+
def self.get_list(resource_name:, resource_maker:, user: nil, **query)
|
10
|
+
limit = query[:limit]
|
11
|
+
query[:limit] = limit.nil? ? limit : [limit, 100].min
|
12
|
+
|
13
|
+
Enumerator.new do |enum|
|
14
|
+
loop do
|
15
|
+
json = StarkBank::Utils::Request.fetch(
|
16
|
+
method: 'GET',
|
17
|
+
path: StarkBank::Utils::API.endpoint(resource_name),
|
18
|
+
query: query,
|
19
|
+
user: user
|
20
|
+
).json
|
21
|
+
entities = json[StarkBank::Utils::API.last_name_plural(resource_name)]
|
22
|
+
|
23
|
+
entities.each do |entity|
|
24
|
+
enum << StarkBank::Utils::API.from_api_json(resource_maker, entity)
|
25
|
+
end
|
26
|
+
|
27
|
+
unless limit.nil?
|
28
|
+
limit -= 100
|
29
|
+
query[:limit] = [limit, 100].min
|
30
|
+
end
|
31
|
+
|
32
|
+
cursor = json['cursor']
|
33
|
+
query['cursor'] = cursor
|
34
|
+
|
35
|
+
break if cursor.nil? || (!limit.nil? && limit <= 0)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.get_id(resource_name:, resource_maker:, id:, user: nil)
|
41
|
+
json = StarkBank::Utils::Request.fetch(
|
42
|
+
method: 'GET',
|
43
|
+
path: "#{StarkBank::Utils::API.endpoint(resource_name)}/#{id}",
|
44
|
+
user: user
|
45
|
+
).json
|
46
|
+
entity = json[StarkBank::Utils::API.last_name(resource_name)]
|
47
|
+
StarkBank::Utils::API.from_api_json(resource_maker, entity)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.get_pdf(resource_name:, resource_maker:, id:, user: nil)
|
51
|
+
StarkBank::Utils::Request.fetch(
|
52
|
+
method: 'GET',
|
53
|
+
path: "#{StarkBank::Utils::API.endpoint(resource_name)}/#{id}/pdf",
|
54
|
+
user: user
|
55
|
+
).content
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.post(resource_name:, resource_maker:, entities:, user: nil)
|
59
|
+
jsons = []
|
60
|
+
entities.each do |entity|
|
61
|
+
jsons << StarkBank::Utils::API.api_json(entity)
|
62
|
+
end
|
63
|
+
payload = { StarkBank::Utils::API.last_name_plural(resource_name) => jsons }
|
64
|
+
json = StarkBank::Utils::Request.fetch(
|
65
|
+
method: 'POST',
|
66
|
+
path: StarkBank::Utils::API.endpoint(resource_name),
|
67
|
+
payload: payload,
|
68
|
+
user: user
|
69
|
+
).json
|
70
|
+
returned_jsons = json[StarkBank::Utils::API.last_name_plural(resource_name)]
|
71
|
+
entities = []
|
72
|
+
returned_jsons.each do |returned_json|
|
73
|
+
entities << StarkBank::Utils::API.from_api_json(resource_maker, returned_json)
|
74
|
+
end
|
75
|
+
entities
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.post_single(resource_name:, resource_maker:, entity:, user: nil)
|
79
|
+
json = StarkBank::Utils::Request.fetch(
|
80
|
+
method: 'POST',
|
81
|
+
path: StarkBank::Utils::API.endpoint(resource_name),
|
82
|
+
payload: StarkBank::Utils::API.api_json(entity),
|
83
|
+
user: user
|
84
|
+
).json
|
85
|
+
entity_json = json[StarkBank::Utils::API.last_name(resource_name)]
|
86
|
+
StarkBank::Utils::API.from_api_json(resource_maker, entity_json)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.delete_id(resource_name:, resource_maker:, id:, user: nil)
|
90
|
+
json = StarkBank::Utils::Request.fetch(
|
91
|
+
method: 'DELETE',
|
92
|
+
path: "#{StarkBank::Utils::API.endpoint(resource_name)}/#{id}",
|
93
|
+
user: user
|
94
|
+
).json
|
95
|
+
entity = json[StarkBank::Utils::API.last_name(resource_name)]
|
96
|
+
StarkBank::Utils::API.from_api_json(resource_maker, entity)
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.patch_id(resource_name:, resource_maker:, id:, user: nil, **payload)
|
100
|
+
json = StarkBank::Utils::Request.fetch(
|
101
|
+
method: 'PATCH',
|
102
|
+
path: "#{StarkBank::Utils::API.endpoint(resource_name)}/#{id}",
|
103
|
+
user: user,
|
104
|
+
payload: StarkBank::Utils::API.cast_json_to_api_format(payload)
|
105
|
+
).json
|
106
|
+
entity = json[StarkBank::Utils::API.last_name(resource_name)]
|
107
|
+
StarkBank::Utils::API.from_api_json(resource_maker, entity)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/utils/url.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StarkBank
|
4
|
+
module Utils
|
5
|
+
module URL
|
6
|
+
# generates query string from hash
|
7
|
+
def self.urlencode(params)
|
8
|
+
return '' if params.nil?
|
9
|
+
|
10
|
+
params = StarkBank::Utils::API.cast_json_to_api_format(params)
|
11
|
+
return '' if params.empty?
|
12
|
+
|
13
|
+
string_params = {}
|
14
|
+
params.each do |key, value|
|
15
|
+
string_params[key] = value.is_a?(Array) ? value.join(',') : value
|
16
|
+
end
|
17
|
+
|
18
|
+
query_list = []
|
19
|
+
string_params.each do |key, value|
|
20
|
+
query_list << "#{key}=#{value}"
|
21
|
+
end
|
22
|
+
'?' + query_list.join('&')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('json')
|
4
|
+
require('starkbank-ecdsa')
|
5
|
+
require_relative('../utils/resource')
|
6
|
+
require_relative('../utils/rest')
|
7
|
+
require_relative('../utils/checks')
|
8
|
+
require_relative('../utils/cache')
|
9
|
+
require_relative('../error')
|
10
|
+
require_relative('../boleto/log')
|
11
|
+
require_relative('../transfer/log')
|
12
|
+
require_relative('../payment/boleto/log')
|
13
|
+
require_relative('../payment/utility/log')
|
14
|
+
|
15
|
+
module StarkBank
|
16
|
+
# # Webhook Event object
|
17
|
+
#
|
18
|
+
# An Event is the notification received from the subscription to the Webhook.
|
19
|
+
# Events cannot be created, but may be retrieved from the Stark Bank API to
|
20
|
+
# list all generated updates on entities.
|
21
|
+
#
|
22
|
+
# ## Attributes:
|
23
|
+
# - id [string]: unique id returned when the log is created. ex: "5656565656565656"
|
24
|
+
# - log [Log]: a Log object from one the subscription services (TransferLog, BoletoLog, BoletoPaymentlog or UtilityPaymentLog)
|
25
|
+
# - created [DateTime]: creation datetime for the notification event. ex: DateTime.new(2020, 3, 10, 10, 30, 0, 0)
|
26
|
+
# - is_delivered [bool]: true if the event has been successfully delivered to the user url. ex: False
|
27
|
+
# - subscription [string]: service that triggered this event. ex: "transfer", "utility-payment"
|
28
|
+
class Event < StarkBank::Utils::Resource
|
29
|
+
attr_reader :id, :log, :created, :is_delivered, :subscription
|
30
|
+
def initialize(id:, log:, created:, is_delivered:, subscription:)
|
31
|
+
super(id)
|
32
|
+
@created = StarkBank::Utils::Checks.check_datetime(created)
|
33
|
+
@is_delivered = is_delivered
|
34
|
+
@subscription = subscription
|
35
|
+
|
36
|
+
maker = {
|
37
|
+
'transfer': StarkBank::Transfer::Log.resource,
|
38
|
+
'boleto': StarkBank::Boleto::Log.resource,
|
39
|
+
'boleto-payment': StarkBank::BoletoPayment::Log.resource,
|
40
|
+
'utility-payment': StarkBank::UtilityPayment::Log.resource
|
41
|
+
}[subscription.to_sym][:resource_maker]
|
42
|
+
|
43
|
+
@log = StarkBank::Utils::API.from_api_json(maker, log)
|
44
|
+
end
|
45
|
+
|
46
|
+
# # Retrieve a specific notification Event
|
47
|
+
#
|
48
|
+
# Receive a single notification Event object previously created in the Stark Bank API by passing its id
|
49
|
+
#
|
50
|
+
# ## Parameters (required):
|
51
|
+
# - id [string]: object unique id. ex: "5656565656565656"
|
52
|
+
#
|
53
|
+
# ## Parameters (optional):
|
54
|
+
# - user [Project object]: Project object. Not necessary if StarkBank.user was set before function call
|
55
|
+
#
|
56
|
+
# ## Return:
|
57
|
+
# - Event object with updated attributes
|
58
|
+
def self.get(id:, user: nil)
|
59
|
+
StarkBank::Utils::Rest.get_id(id: id, user: user, **resource)
|
60
|
+
end
|
61
|
+
|
62
|
+
# # Retrieve notification Events
|
63
|
+
#
|
64
|
+
# Receive a generator of notification Event objects previously created in the Stark Bank API
|
65
|
+
#
|
66
|
+
# ## Parameters (optional):
|
67
|
+
# - limit [integer, default nil]: maximum number of objects to be retrieved. Unlimited if nil. ex: 35
|
68
|
+
# - is_delivered [bool, default nil]: bool to filter successfully delivered events. ex: True or False
|
69
|
+
# - after [Date, default nil]: date filter for objects created only after specified date. ex: Date.new(2020, 3, 10)
|
70
|
+
# - before [Date, default nil]: date filter for objects only before specified date. ex: Date.new(2020, 3, 10)
|
71
|
+
# - user [Project object, default nil]: Project object. Not necessary if StarkBank.user was set before function call
|
72
|
+
#
|
73
|
+
# ## Return:
|
74
|
+
# - generator of Event objects with updated attributes
|
75
|
+
def self.query(limit: nil, is_delivered: nil, after: nil, before: nil, user: nil)
|
76
|
+
after = StarkBank::Utils::Checks.check_date(after)
|
77
|
+
before = StarkBank::Utils::Checks.check_date(before)
|
78
|
+
StarkBank::Utils::Rest.get_list(user: user, limit: limit, is_delivered: is_delivered, after: after, before: before, **resource)
|
79
|
+
end
|
80
|
+
|
81
|
+
# # Delete a notification Event
|
82
|
+
#
|
83
|
+
# Delete a of notification Event entity previously created in the Stark Bank API by its ID
|
84
|
+
#
|
85
|
+
# ## Parameters (required):
|
86
|
+
# - id [string]: Event unique id. ex: "5656565656565656"
|
87
|
+
#
|
88
|
+
# ## Parameters (optional):
|
89
|
+
# - user [Project object]: Project object. Not necessary if StarkBank.user was set before function call
|
90
|
+
#
|
91
|
+
# ## Return:
|
92
|
+
# - deleted Event with updated attributes
|
93
|
+
def self.delete(id:, user: nil)
|
94
|
+
StarkBank::Utils::Rest.delete_id(id: id, user: user, **resource)
|
95
|
+
end
|
96
|
+
|
97
|
+
# # Update notification Event entity
|
98
|
+
#
|
99
|
+
# Update notification Event by passing id.
|
100
|
+
# If is_delivered is True, the event will no longer be returned on queries with is_delivered=False.
|
101
|
+
#
|
102
|
+
# ## Parameters (required):
|
103
|
+
# - id [list of strings]: Event unique ids. ex: "5656565656565656"
|
104
|
+
# - is_delivered [bool]: If True and event hasn't been delivered already, event will be set as delivered. ex: True
|
105
|
+
#
|
106
|
+
# ## Parameters (optional):
|
107
|
+
# - user [Project object]: Project object. Not necessary if StarkBank.user was set before function call
|
108
|
+
#
|
109
|
+
# ## Return:
|
110
|
+
# - target Event with updated attributes
|
111
|
+
def self.update(id:, is_delivered:, user: nil)
|
112
|
+
StarkBank::Utils::Rest.patch_id(id: id, user: user, is_delivered: is_delivered, **resource)
|
113
|
+
end
|
114
|
+
|
115
|
+
# # Create single notification Event from a content string
|
116
|
+
#
|
117
|
+
# Create a single Event object received from event listening at subscribed user endpoint.
|
118
|
+
# If the provided digital signature does not check out with the StarkBank public key, a
|
119
|
+
# starkbank.exception.InvalidSignatureException will be raised.
|
120
|
+
#
|
121
|
+
# ## Parameters (required):
|
122
|
+
# - content [string]: response content from request received at user endpoint (not parsed)
|
123
|
+
# - signature [string]: base-64 digital signature received at response header "Digital-Signature"
|
124
|
+
#
|
125
|
+
# ## Parameters (optional):
|
126
|
+
# - user [Project object]: Project object. Not necessary if StarkBank.user was set before function call
|
127
|
+
#
|
128
|
+
# ## Return:
|
129
|
+
# - Parsed Event object
|
130
|
+
def self.parse(content:, signature:, user: nil)
|
131
|
+
event = StarkBank::Utils::API.from_api_json(resource[:resource_maker], JSON.parse(content)['event'])
|
132
|
+
|
133
|
+
return event if verify_signature(content: content, signature: signature, user: user)
|
134
|
+
|
135
|
+
return event if verify_signature(content: content, signature: signature, user: user, refresh: true)
|
136
|
+
|
137
|
+
raise(StarkBank::Error::InvalidSignatureError, 'The provided signature and content do not match the Stark Bank public key')
|
138
|
+
end
|
139
|
+
|
140
|
+
class << self
|
141
|
+
private
|
142
|
+
|
143
|
+
def verify_signature(content:, signature:, user:, refresh: false)
|
144
|
+
signature = EllipticCurve::Signature.fromBase64(signature)
|
145
|
+
public_key = StarkBank::Utils::Cache.starkbank_public_key
|
146
|
+
if public_key.nil? || refresh
|
147
|
+
pem = get_public_key_pem(user)
|
148
|
+
public_key = EllipticCurve::PublicKey.fromPem(pem)
|
149
|
+
StarkBank::Utils::Cache.starkbank_public_key = public_key
|
150
|
+
end
|
151
|
+
EllipticCurve::Ecdsa.verify(content, signature, public_key)
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_public_key_pem(user)
|
155
|
+
StarkBank::Utils::Request.fetch(method: 'GET', path: 'public-key', query: {limit: 1}, user: user).json['publicKeys'][0]['content']
|
156
|
+
end
|
157
|
+
|
158
|
+
def resource
|
159
|
+
{
|
160
|
+
resource_name: 'Event',
|
161
|
+
resource_maker: proc { |json|
|
162
|
+
Event.new(
|
163
|
+
id: json['id'],
|
164
|
+
log: json['log'],
|
165
|
+
created: json['created'],
|
166
|
+
is_delivered: json['is_delivered'],
|
167
|
+
subscription: json['subscription']
|
168
|
+
)
|
169
|
+
}
|
170
|
+
}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative('../utils/resource')
|
4
|
+
require_relative('../utils/rest')
|
5
|
+
require_relative('../utils/checks')
|
6
|
+
|
7
|
+
module StarkBank
|
8
|
+
# # Webhook subscription object
|
9
|
+
#
|
10
|
+
# A Webhook is used to subscribe to notification events on a user-selected endpoint.
|
11
|
+
# Currently available services for subscription are transfer, boleto, boleto-payment,
|
12
|
+
# and utility-payment
|
13
|
+
#
|
14
|
+
# ## Parameters (required):
|
15
|
+
# - url [string]: Url that will be notified when an event occurs.
|
16
|
+
# - subscriptions [list of strings]: list of any non-empty combination of the available services. ex: ["transfer", "boleto-payment"]
|
17
|
+
#
|
18
|
+
# ## Attributes:
|
19
|
+
# - id [string, default nil]: unique id returned when the log is created. ex: "5656565656565656"
|
20
|
+
class Webhook < StarkBank::Utils::Resource
|
21
|
+
attr_reader :url, :subscriptions, :id
|
22
|
+
def initialize(url:, subscriptions:, id: nil)
|
23
|
+
super(id)
|
24
|
+
@url = url
|
25
|
+
@subscriptions = subscriptions
|
26
|
+
end
|
27
|
+
|
28
|
+
# # Create Webhook subscription
|
29
|
+
#
|
30
|
+
# Send a single Webhook subscription for creation in the Stark Bank API
|
31
|
+
#
|
32
|
+
# ## Parameters (required):
|
33
|
+
# - url [string]: url to which notification events will be sent to. ex: "https://webhook.site/60e9c18e-4b5c-4369-bda1-ab5fcd8e1b29"
|
34
|
+
# - subscriptions [list of strings]: list of any non-empty combination of the available services. ex: ["transfer", "boleto-payment"]
|
35
|
+
#
|
36
|
+
# ## Parameters (optional):
|
37
|
+
# - user [Project object]: Project object. Not necessary if StarkBank.user was set before function call
|
38
|
+
#
|
39
|
+
# ## Return:
|
40
|
+
# - Webhook object with updated attributes
|
41
|
+
def self.create(url:, subscriptions:, id: nil, user: nil)
|
42
|
+
StarkBank::Utils::Rest.post_single(entity: Webhook.new(url: url, subscriptions: subscriptions), user: user, **resource)
|
43
|
+
end
|
44
|
+
|
45
|
+
# # Retrieve a specific Webhook subscription
|
46
|
+
#
|
47
|
+
# Receive a single Webhook subscription object previously created in the Stark Bank API by passing its id
|
48
|
+
#
|
49
|
+
# ## Parameters (required):
|
50
|
+
# - id [string]: object unique id. ex: "5656565656565656"
|
51
|
+
#
|
52
|
+
# ## Parameters (optional):
|
53
|
+
# - user [Project object]: Project object. Not necessary if StarkBank.user was set before function call
|
54
|
+
#
|
55
|
+
# ## Return:
|
56
|
+
# - Webhook object with updated attributes
|
57
|
+
def self.get(id:, user: nil)
|
58
|
+
StarkBank::Utils::Rest.get_id(id: id, user: user, **resource)
|
59
|
+
end
|
60
|
+
|
61
|
+
# # Retrieve Webhook subcriptions
|
62
|
+
#
|
63
|
+
# Receive a generator of Webhook subcription objects previously created in the Stark Bank API
|
64
|
+
#
|
65
|
+
# ## Parameters (optional):
|
66
|
+
# - limit [integer, default nil]: maximum number of objects to be retrieved. Unlimited if nil. ex: 35
|
67
|
+
# - user [Project object, default nil]: Project object. Not necessary if StarkBank.user was set before function call
|
68
|
+
#
|
69
|
+
# ## Return:
|
70
|
+
# - generator of Webhook objects with updated attributes
|
71
|
+
def self.query(limit: nil, user: nil)
|
72
|
+
StarkBank::Utils::Rest.get_list(user: user, limit: limit, **resource)
|
73
|
+
end
|
74
|
+
|
75
|
+
# # Delete a Webhook entity
|
76
|
+
#
|
77
|
+
# Delete a Webhook entity previously created in the Stark Bank API
|
78
|
+
#
|
79
|
+
# ## Parameters (required):
|
80
|
+
# - id [string]: Webhook unique id. ex: "5656565656565656"
|
81
|
+
#
|
82
|
+
# ## Parameters (optional):
|
83
|
+
# - user [Project object]: Project object. Not necessary if StarkBank.user was set before function call
|
84
|
+
#
|
85
|
+
# ## Return:
|
86
|
+
# - deleted Webhook with updated attributes
|
87
|
+
def self.delete(id:, user: nil)
|
88
|
+
StarkBank::Utils::Rest.delete_id(id: id, user: user, **resource)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.resource
|
92
|
+
{
|
93
|
+
resource_name: 'Webhook',
|
94
|
+
resource_maker: proc { |json|
|
95
|
+
Webhook.new(
|
96
|
+
id: json['id'],
|
97
|
+
url: json['url'],
|
98
|
+
subscriptions: json['subscriptions']
|
99
|
+
)
|
100
|
+
}
|
101
|
+
}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|