bunq-client 0.6.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rspec.yml +40 -0
- data/.rubocop.yml +212 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -0
- data/README.md +6 -4
- data/Rakefile +7 -3
- data/bunq-client.gemspec +22 -20
- data/lib/bunq/attachment.rb +15 -0
- data/lib/bunq/attachment_public.rb +13 -0
- data/lib/bunq/attachment_public_content.rb +4 -2
- data/lib/bunq/attachment_publics.rb +20 -0
- data/lib/bunq/attachments.rb +20 -0
- data/lib/bunq/avatar.rb +15 -0
- data/lib/bunq/avatars.rb +15 -0
- data/lib/bunq/bunq.rb +2 -0
- data/lib/bunq/bunqme_tab.rb +17 -0
- data/lib/bunq/bunqme_tabs.rb +21 -0
- data/lib/bunq/card.rb +2 -0
- data/lib/bunq/cards.rb +3 -1
- data/lib/bunq/certificate_pinned.rb +10 -6
- data/lib/bunq/client.rb +74 -51
- data/lib/bunq/device_servers.rb +5 -4
- data/lib/bunq/draft_share_invite_bank.rb +2 -0
- data/lib/bunq/draft_share_invite_banks.rb +3 -1
- data/lib/bunq/encryptor.rb +6 -7
- data/lib/bunq/errors.rb +10 -3
- data/lib/bunq/header.rb +20 -0
- data/lib/bunq/installation.rb +2 -0
- data/lib/bunq/installations.rb +4 -2
- data/lib/bunq/monetary_account.rb +17 -0
- data/lib/bunq/monetary_account_bank.rb +17 -0
- data/lib/bunq/monetary_account_banks.rb +21 -0
- data/lib/bunq/monetary_accounts.rb +3 -1
- data/lib/bunq/notification_filter_url.rb +4 -2
- data/lib/bunq/paginated.rb +14 -3
- data/lib/bunq/payment.rb +2 -0
- data/lib/bunq/payments.rb +3 -1
- data/lib/bunq/qr_code_content.rb +5 -3
- data/lib/bunq/resource.rb +34 -16
- data/lib/bunq/session_servers.rb +5 -2
- data/lib/bunq/signature.rb +31 -8
- data/lib/bunq/user.rb +17 -0
- data/lib/bunq/user_company.rb +2 -0
- data/lib/bunq/user_person.rb +2 -0
- data/lib/bunq/users.rb +17 -0
- data/lib/bunq/version.rb +3 -1
- metadata +53 -20
- data/.travis.yml +0 -5
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Bunq
|
6
|
+
class AttachmentPublics
|
7
|
+
def initialize(client)
|
8
|
+
@resource = Bunq::Resource.new(client, '/v1/attachment-public')
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(binary_payload, description, mime_type)
|
12
|
+
custom_headers = {
|
13
|
+
Bunq::Header::CONTENT_TYPE => mime_type,
|
14
|
+
Bunq::Header::ATTACHMENT_DESCRIPTION => description,
|
15
|
+
}
|
16
|
+
payload = Base64.decode64(binary_payload)
|
17
|
+
@resource.with_session { @resource.post(payload, custom_headers: custom_headers) }['Response']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Bunq
|
6
|
+
class Attachments
|
7
|
+
def initialize(parent_resource)
|
8
|
+
@resource = parent_resource.append('/attachment')
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(binary_payload, description, mime_type)
|
12
|
+
custom_headers = {
|
13
|
+
Bunq::Header::CONTENT_TYPE => mime_type,
|
14
|
+
Bunq::Header::ATTACHMENT_DESCRIPTION => description,
|
15
|
+
}
|
16
|
+
payload = Base64.decode64(binary_payload)
|
17
|
+
@resource.with_session { @resource.post(payload, custom_headers: custom_headers) }['Response']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/bunq/avatar.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'resource'
|
4
|
+
|
5
|
+
module Bunq
|
6
|
+
class Avatar
|
7
|
+
def initialize(client, id)
|
8
|
+
@resource = Bunq::Resource.new(client, "/v1/avatar/#{id}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
@resource.with_session { @resource.get }['Response']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/bunq/avatars.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'resource'
|
4
|
+
|
5
|
+
module Bunq
|
6
|
+
class Avatars
|
7
|
+
def initialize(client)
|
8
|
+
@resource = Bunq::Resource.new(client, '/v1/avatar')
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(attachment_public_uuid)
|
12
|
+
@resource.with_session { @resource.post({attachment_public_uuid: attachment_public_uuid}) }['Response']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/bunq/bunq.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bunq
|
4
|
+
class BunqmeTab
|
5
|
+
def initialize(parent_resource, id)
|
6
|
+
@resource = parent_resource.append("/bunqme-tab/#{id}")
|
7
|
+
end
|
8
|
+
|
9
|
+
def show
|
10
|
+
@resource.with_session { @resource.get }['Response']
|
11
|
+
end
|
12
|
+
|
13
|
+
def update(attributes)
|
14
|
+
@resource.with_session { @resource.put(attributes) }['Response']
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'paginated'
|
4
|
+
|
5
|
+
module Bunq
|
6
|
+
class BunqmeTabs
|
7
|
+
def initialize(parent_resource)
|
8
|
+
@resource = parent_resource.append('/bunqme-tab')
|
9
|
+
end
|
10
|
+
|
11
|
+
def index(count: 200, older_id: nil, newer_id: nil)
|
12
|
+
Bunq::Paginated
|
13
|
+
.new(@resource)
|
14
|
+
.paginate(count: count, older_id: older_id, newer_id: newer_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create(attributes)
|
18
|
+
@resource.with_session { @resource.post(attributes) }['Response']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/bunq/card.rb
CHANGED
data/lib/bunq/cards.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bunq
|
2
4
|
##
|
3
5
|
# https://doc.bunq.com/api/1/call/certificate-pinned
|
4
6
|
class CertificatePinned
|
5
7
|
def initialize(parent_resource)
|
6
|
-
@resource = parent_resource.append(
|
8
|
+
@resource = parent_resource.append('/certificate-pinned')
|
7
9
|
end
|
8
10
|
|
9
11
|
##
|
10
12
|
# https://doc.bunq.com/api/1/call/certificate-pinned/method/post
|
11
13
|
def create(pem_certificate)
|
12
14
|
@resource.with_session do
|
13
|
-
@resource.post(
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
@resource.post(
|
16
|
+
{
|
17
|
+
certificate_chain: [
|
18
|
+
{certificate: pem_certificate},
|
19
|
+
],
|
20
|
+
},
|
21
|
+
)
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
data/lib/bunq/client.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
require 'base64'
|
3
5
|
require 'thread_safe'
|
4
6
|
|
5
7
|
require_relative './version'
|
8
|
+
require_relative './header'
|
6
9
|
require_relative './resource'
|
7
10
|
|
11
|
+
require_relative './attachment_publics'
|
12
|
+
require_relative './attachment_public'
|
13
|
+
require_relative './avatars'
|
14
|
+
require_relative './avatar'
|
8
15
|
require_relative './installations'
|
9
16
|
require_relative './installation'
|
10
17
|
require_relative './device_servers'
|
@@ -18,7 +25,7 @@ require_relative './monetary_accounts'
|
|
18
25
|
require_relative './payment'
|
19
26
|
require_relative './payments'
|
20
27
|
require_relative './signature'
|
21
|
-
require_relative './attachment_public_content
|
28
|
+
require_relative './attachment_public_content'
|
22
29
|
|
23
30
|
##
|
24
31
|
# Usage
|
@@ -53,7 +60,8 @@ module Bunq
|
|
53
60
|
# Returns a new instance of +Client+ with the current +configuration+.
|
54
61
|
#
|
55
62
|
def client
|
56
|
-
fail
|
63
|
+
fail 'No configuration! Call Bunq.configure first.' unless configuration
|
64
|
+
|
57
65
|
Client.new(configuration.dup)
|
58
66
|
end
|
59
67
|
end
|
@@ -112,40 +120,40 @@ module Bunq
|
|
112
120
|
|
113
121
|
# Base url for the bunq api. Defaults to +PRODUCTION_BASE_URL+
|
114
122
|
attr_accessor :base_url,
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
123
|
+
# Flag to set to connect to sandbox. Defaults to +false+.
|
124
|
+
# If set to +true+ you must also specify +sandbox_user+
|
125
|
+
# and +sandbox_password+
|
126
|
+
:sandbox,
|
127
|
+
# The username for connecting to the sandbox
|
128
|
+
:sandbox_user,
|
129
|
+
# The password for connecting to the sandbox
|
130
|
+
:sandbox_password,
|
131
|
+
# Your installation token obtained from bunq
|
132
|
+
:installation_token,
|
133
|
+
# Your api key obtained from bunq
|
134
|
+
:api_key,
|
135
|
+
# Your language. Defaults to +DEFAULT_LANGUAGE+
|
136
|
+
:language,
|
137
|
+
# Your region. Defaults to +DEFAULT_REGION+
|
138
|
+
:region,
|
139
|
+
# Your geolocation. Defaults to +DEFAULT_GEOLOCATION+
|
140
|
+
:geolocation,
|
141
|
+
# Arbitrary user agent to connect to bunq. Defaults to +DEFAULT_USER_AGENT+
|
142
|
+
:user_agent,
|
143
|
+
# Flag to set when you want to disable the signature
|
144
|
+
# retrieved from bunq. Mainly useful for testing.
|
145
|
+
# Defaults to +false+
|
146
|
+
:disable_response_signature_verification,
|
147
|
+
# The private key for signing the request
|
148
|
+
:private_key,
|
149
|
+
# The public key of this installation for verifying the response
|
150
|
+
:server_public_key,
|
151
|
+
# Timeout in seconds to wait for bunq api. Defaults to +DEFAULT_TIMEOUT+
|
152
|
+
:timeout,
|
153
|
+
# Cache to retrieve current session from. Defaults to +DEFAULT_SESSION_CACHE+,
|
154
|
+
# which will create a new session per `Bunq.client` instance.
|
155
|
+
# See +ThreadSafeSessionCache+ for more advanced use.
|
156
|
+
:session_cache
|
149
157
|
|
150
158
|
def initialize
|
151
159
|
@sandbox = false
|
@@ -165,14 +173,33 @@ module Bunq
|
|
165
173
|
#
|
166
174
|
# An instance of a +Client+ can be obtained via +Bunq.client+
|
167
175
|
class Client
|
176
|
+
APPLICATION_JSON = 'application/json'
|
177
|
+
|
168
178
|
attr_accessor :current_session
|
169
179
|
attr_reader :configuration
|
170
180
|
|
171
181
|
def initialize(configuration)
|
172
|
-
fail ArgumentError
|
182
|
+
fail ArgumentError, 'configuration is required' unless configuration
|
183
|
+
|
173
184
|
@configuration = configuration
|
174
185
|
end
|
175
186
|
|
187
|
+
def attachment_publics
|
188
|
+
Bunq::AttachmentPublics.new(self)
|
189
|
+
end
|
190
|
+
|
191
|
+
def attachment_public(id)
|
192
|
+
Bunq::AttachmentPublic.new(self, id)
|
193
|
+
end
|
194
|
+
|
195
|
+
def avatars
|
196
|
+
Bunq::Avatars.new(self)
|
197
|
+
end
|
198
|
+
|
199
|
+
def avatar(id)
|
200
|
+
Bunq::Avatar.new(self, id)
|
201
|
+
end
|
202
|
+
|
176
203
|
def installations
|
177
204
|
Bunq::Installations.new(self)
|
178
205
|
end
|
@@ -226,7 +253,7 @@ module Bunq
|
|
226
253
|
end
|
227
254
|
|
228
255
|
def ensure_session!
|
229
|
-
@current_session ||= configuration.session_cache.get { create_session }
|
256
|
+
@current_session ||= configuration.session_cache.get { create_session } # rubocop:disable Naming/MemoizedInstanceVariableName
|
230
257
|
end
|
231
258
|
|
232
259
|
def create_session
|
@@ -254,21 +281,17 @@ module Bunq
|
|
254
281
|
|
255
282
|
def headers
|
256
283
|
{
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
284
|
+
Bunq::Header::ACCEPT => APPLICATION_JSON,
|
285
|
+
Bunq::Header::CACHE_CONTROL => 'no-cache',
|
286
|
+
Bunq::Header::CONTENT_TYPE => APPLICATION_JSON,
|
287
|
+
Bunq::Header::USER_AGENT => configuration.user_agent,
|
288
|
+
Bunq::Header::LANGUAGE => configuration.language,
|
289
|
+
Bunq::Header::GEOLOCATION => configuration.geolocation,
|
290
|
+
Bunq::Header::REGION => configuration.region,
|
264
291
|
}.tap do |h|
|
265
|
-
if configuration.installation_token
|
266
|
-
h[:'X-Bunq-Client-Authentication'] = configuration.installation_token
|
267
|
-
end
|
292
|
+
h[Bunq::Header::CLIENT_AUTH] = configuration.installation_token if configuration.installation_token
|
268
293
|
|
269
|
-
if current_session
|
270
|
-
h[:'X-Bunq-Client-Authentication'] = current_session[1]['Token']['token']
|
271
|
-
end
|
294
|
+
h[Bunq::Header::CLIENT_AUTH] = current_session[1]['Token']['token'] if current_session
|
272
295
|
end
|
273
296
|
end
|
274
297
|
|
data/lib/bunq/device_servers.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bunq
|
2
4
|
##
|
3
5
|
# See https://doc.bunq.com/api/1/call/device-server
|
4
6
|
class DeviceServers
|
5
|
-
|
6
7
|
##
|
7
8
|
# +client+ an instance of +Bunq::Client+
|
8
9
|
#
|
9
10
|
def initialize(client)
|
10
|
-
@resource = Bunq::Resource.new(client,
|
11
|
+
@resource = Bunq::Resource.new(client, '/v1/device-server')
|
11
12
|
@client = client
|
12
13
|
end
|
13
14
|
|
@@ -20,10 +21,10 @@ module Bunq
|
|
20
21
|
# @param description [String] The description of this device server.
|
21
22
|
# @param permitted_ips [Array|nil] Array of permitted IP addresses.
|
22
23
|
def create(description, permitted_ips: nil)
|
23
|
-
fail ArgumentError
|
24
|
+
fail ArgumentError, 'description is required' unless description
|
24
25
|
fail 'Cannot create session, please add the api_key to your configuration' unless @client.configuration.api_key
|
25
26
|
|
26
|
-
params = {
|
27
|
+
params = {description: description, secret: @client.configuration.api_key}
|
27
28
|
params[:permitted_ips] = permitted_ips if permitted_ips
|
28
29
|
|
29
30
|
@resource.post(params)['Response']
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'qr_code_content'
|
2
4
|
|
3
5
|
module Bunq
|
4
6
|
class DraftShareInviteBanks
|
5
7
|
def initialize(parent_resource)
|
6
|
-
@resource = parent_resource.append(
|
8
|
+
@resource = parent_resource.append('/draft-share-invite-bank')
|
7
9
|
end
|
8
10
|
|
9
11
|
def create(invite)
|
data/lib/bunq/encryptor.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bunq
|
2
4
|
class Encryptor
|
3
|
-
HEADER_CLIENT_ENCRYPTION_HMAC = 'X-Bunq-Client-Encryption-Hmac'
|
4
|
-
HEADER_CLIENT_ENCRYPTION_IV = 'X-Bunq-Client-Encryption-Iv'
|
5
|
-
HEADER_CLIENT_ENCRYPTION_KEY = 'X-Bunq-Client-Encryption-Key'
|
6
5
|
AES_ENCRYPTION_METHOD = 'aes-256-cbc'
|
7
6
|
HMAC_ALGORITHM = 'sha1'
|
8
7
|
|
9
8
|
def initialize(server_public_key)
|
10
|
-
fail ArgumentError
|
9
|
+
fail ArgumentError, 'server_public_key is mandatory' unless server_public_key
|
11
10
|
|
12
11
|
@server_public_key = OpenSSL::PKey::RSA.new(server_public_key)
|
13
12
|
end
|
@@ -17,13 +16,13 @@ module Bunq
|
|
17
16
|
|
18
17
|
iv, key, encrypted_body = encrypt_body(body)
|
19
18
|
|
20
|
-
headers[
|
19
|
+
headers[Bunq::Header::CLIENT_ENCRYPTION_IV] = Base64.strict_encode64(iv)
|
21
20
|
|
22
21
|
encrypted_key = server_public_key.public_encrypt(key)
|
23
|
-
headers[
|
22
|
+
headers[Bunq::Header::CLIENT_ENCRYPTION_KEY] = Base64.strict_encode64(encrypted_key)
|
24
23
|
|
25
24
|
digest = hmac(key, iv + encrypted_body)
|
26
|
-
headers[
|
25
|
+
headers[Bunq::Header::CLIENT_ENCRYPTION_HMAC] = Base64.strict_encode64(digest)
|
27
26
|
|
28
27
|
[encrypted_body, headers]
|
29
28
|
end
|