figo 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 390163889160a8aefcb91f1f8b4f99e18c84efb9
4
- data.tar.gz: 2a24495ecbb097b1659dbb29f8ad697b082d24a2
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDMwM2ExN2I1ZDEzOGFlNGM3ZGRlY2I2ODljMTEyZTE2ZGE2MDg2OQ==
5
+ data.tar.gz: !binary |-
6
+ ODQzNGViYjA3ZTM3NzI2ZmMxMmNiN2IxNWQ2Zjg2YmZkZmIwMDRmYw==
5
7
  SHA512:
6
- metadata.gz: e0c1cc2c14a9b6db75c5724b949ec2d0b7d496103247bd4bdcd72993e549d6371465dcd1222105ca939d7837c99ee44d2f6937efe56b606cffb40982641eb52f
7
- data.tar.gz: b5401f6d092be459e5165bb86564d4180e7529cfd750261604865e17d5fcac0e0b44c3ecc311b435b194fcb4dc0d3ffd936be1840ba9dda2c5e012a48de97f2a
8
+ metadata.gz: !binary |-
9
+ NjhiZDlhYzY5NWY0ZjQ3YzEzY2YyYTQ1MjNkYjJlOTU2NDk2Y2YxNWQ5MjA3
10
+ YTJjODk1NTYzNDNmOGNmZWZiZTBmYmZkMmVlZDQ1MjY3MjY3NDAxNDE4MTc2
11
+ Y2I0MDdiZDhiNmE1YmI3MTQ0MTYyYzRhNGY2ODRmNjY0ZDczYTc=
12
+ data.tar.gz: !binary |-
13
+ NjEzZDg0MDdjNzg0MjVkYzNkZGQ0ZTliMzE4ZDlkMzAyMTgzZjU3OTI1MDU5
14
+ M2Y3NjVhMGUxZTg3OGE2Nzc4NjZiODc5Y2MxNDE1OTllZmQ1YTE5MmY0M2E1
15
+ Mjk4YWI2MWJmYmVkMTZhNTdkNzI3NzYyMzBlZGNkMTk0YzM1MTg=
data/.travis.yml CHANGED
@@ -4,11 +4,3 @@ rvm:
4
4
  - 2.0.0
5
5
  - 2.1.1
6
6
  - ruby-head
7
- - rbx-2.1.1
8
- - rbx
9
- - jruby-19mode # JRuby in 1.9 mode
10
- - jruby-head
11
- matrix:
12
- allow_failures:
13
- - rvm: jruby-19mode
14
- - rvm: jruby-head
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- ruby-figo [![Build Status](https://secure.travis-ci.org/figo-connect/ruby-figo.png)](https://travis-ci.org/figo-connect/ruby-figo)
1
+ ruby-figo [![Build Status](https://secure.travis-ci.org/figo-connect/ruby-figo.png)](https://travis-ci.org/figo-connect/ruby-figo) [![Gem Version](http://img.shields.io/gem/v/figo.svg)](http://rubygems.org/gems/figo)
2
2
  =========
3
3
 
4
- Ruby bindings for the figo Connect API: http://developer.figo.me
4
+ Ruby bindings for the figo Connect API: http://docs.figo.io
5
5
 
6
6
  Usage
7
7
  =====
@@ -57,7 +57,7 @@ def process_redirect(authorization_code, state)
57
57
 
58
58
  # Start session.
59
59
  session = Figo::Session.new(token_hash["access_token"])
60
-
60
+
61
61
  # Print out list of account numbers.
62
62
  session.accounts.each do |account|
63
63
  puts account.account_number
@@ -67,7 +67,11 @@ end
67
67
 
68
68
  You can find more documentation at http://rubydoc.info/github/figo-connect/ruby-figo/master/frames
69
69
 
70
+ Demos
71
+ -----
72
+ In this repository you can also have a look at a simple console(`console_demo.rb`) and web demo(`web_demo`). While the console demo simply accesses the figo API, the web demo implements the full OAuth flow.
73
+
70
74
  Requirements
71
- ============
75
+ ------------
72
76
 
73
77
  This gem requires Ruby 1.9.
data/console_demo.rb ADDED
@@ -0,0 +1,14 @@
1
+ require_relative "lib/figo"
2
+
3
+ session = Figo::Session.new("ASHWLIkouP2O6_bgA2wWReRhletgWKHYjLqDaqb0LFfamim9RjexTo22ujRIP_cjLiRiSyQXyt2kM1eXU2XLFZQ0Hro15HikJQT_eNeT_9XQ")
4
+
5
+ # Print out list of account numbers and balances.
6
+ session.accounts.each do |account|
7
+ puts account.account_number
8
+ puts account.balance.balance
9
+ end
10
+
11
+ # Print out the list of all transaction originators/recipients of a specific account.
12
+ session.get_account("A1.1").transactions.each do |transaction|
13
+ puts transaction.name
14
+ end
data/figo.gemspec CHANGED
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "figo"
3
- s.version = "1.1.1"
4
- s.authors = ["Stefan Richter", "Michael Haller"]
5
- s.email = ["stefan.richter@figo.me", "michael.haller@figo.me"]
3
+ s.version = "1.2.0"
4
+ s.authors = ["Stefan Richter"]
5
+ s.email = ["stefan.richter@figo.me"]
6
6
  s.homepage = "https://github.com/figo-connect/ruby-figo"
7
7
  s.license = "MIT"
8
8
  s.summary = %q{API wrapper for figo Connect.}
9
- s.description = %q{Library to easily use the API of http://www.figo.me}
9
+ s.description = %q{Library to easily use the API of http://figo.io}
10
10
 
11
11
  s.files = `git ls-files`.split("\n")
12
12
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
data/lib/figo.rb CHANGED
@@ -1,16 +1,16 @@
1
1
  #
2
2
  # Copyright (c) 2013 figo GmbH
3
- #
3
+ #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
6
6
  # in the Software without restriction, including without limitation the rights
7
7
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
8
  # copies of the Software, and to permit persons to whom the Software is
9
9
  # furnished to do so, subject to the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be included in
12
12
  # all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
15
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
16
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -18,7 +18,7 @@
18
18
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
19
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
20
  # THE SOFTWARE.
21
- #
21
+ #
22
22
 
23
23
  require "json"
24
24
  require "net/http/persistent"
@@ -28,14 +28,13 @@ require_relative "models.rb"
28
28
 
29
29
  # Ruby bindings for the figo Connect API: http://developer.figo.me
30
30
  module Figo
31
-
32
31
  $api_endpoint = "api.figo.me"
33
32
 
34
- $valid_fingerprints = ["3A:62:54:4D:86:B4:34:38:EA:34:64:4E:95:10:A9:FF:37:27:69:C0"]
33
+ $valid_fingerprints = ["3A:62:54:4D:86:B4:34:38:EA:34:64:4E:95:10:A9:FF:37:27:69:C0",
34
+ "CF:C1:BC:7F:6A:16:09:2B:10:83:8A:B0:22:4F:3A:65:D2:70:D7:3E"]
35
35
 
36
36
  # Base class for all errors transported via the figo Connect API.
37
37
  class Error < RuntimeError
38
-
39
38
  # Initialize error object.
40
39
  #
41
40
  # @param error [String] the error code
@@ -51,12 +50,10 @@ module Figo
51
50
  def to_s
52
51
  return @error_description
53
52
  end
54
-
55
53
  end
56
54
 
57
55
  # HTTPS class with certificate authentication and enhanced error handling.
58
56
  class HTTPS < Net::HTTP::Persistent
59
-
60
57
  # Overwrite `initialize` method from `Net::HTTP::Persistent`.
61
58
  #
62
59
  # Verify fingerprints of server SSL/TLS certificates.
@@ -110,7 +107,6 @@ module Figo
110
107
  #
111
108
  # It's main purpose is to let user login via OAuth 2.0.
112
109
  class Connection
113
-
114
110
  # Create connection object with client credentials.
115
111
  #
116
112
  # @param client_id [String] the client ID
@@ -149,32 +145,32 @@ module Figo
149
145
 
150
146
  # Get the URL a user should open in the web browser to start the login process.
151
147
  #
152
- # When the process is completed, the user is redirected to the URL provided to
153
- # the constructor and passes on an authentication code. This code can be converted
148
+ # When the process is completed, the user is redirected to the URL provided to
149
+ # the constructor and passes on an authentication code. This code can be converted
154
150
  # into an access token for data access.
155
151
  #
156
- # @param state [String] this string will be passed on through the complete login
157
- # process and to the redirect target at the end. It should be used to
152
+ # @param state [String] this string will be passed on through the complete login
153
+ # process and to the redirect target at the end. It should be used to
158
154
  # validated the authenticity of the call to the redirect URL
159
- # @param scope [String] optional scope of data access to ask the user for,
155
+ # @param scope [String] optional scope of data access to ask the user for,
160
156
  # e.g. `accounts=ro`
161
157
  # @return [String] the URL to be opened by the user.
162
158
  def login_url(state, scope = nil)
163
159
  data = { "response_type" => "code", "client_id" => @client_id, "state" => state }
164
160
  data["redirect_uri"] = @redirect_uri unless @redirect_uri.nil?
165
161
  data["scope"] = scope unless scope.nil?
166
- return "https://#{$api_endpoint}/auth/code?" + URI.encode_www_form(data)
162
+ return "https://#{$api_endpoint}/auth/code?" + URI.encode_www_form(data)
167
163
  end
168
164
 
169
165
 
170
166
  # Exchange authorization code or refresh token for access token.
171
167
  #
172
- # @param authorization_code_or_refresh_token [String] either the authorization
173
- # code received as part of the call to the redirect URL at the end of the
168
+ # @param authorization_code_or_refresh_token [String] either the authorization
169
+ # code received as part of the call to the redirect URL at the end of the
174
170
  # logon process, or a refresh token
175
- # @param scope [String] optional scope of data access to ask the user for,
171
+ # @param scope [String] optional scope of data access to ask the user for,
176
172
  # e.g. `accounts=ro`
177
- # @return [Hash] object with the keys `access_token`, `refresh_token` and
173
+ # @return [Hash] object with the keys `access_token`, `refresh_token` and
178
174
  # `expires`, as documented in the figo Connect API specification.
179
175
  def obtain_access_token(authorization_code_or_refresh_token, scope = nil)
180
176
  # Authorization codes always start with "O" and refresh tokens always start with "R".
@@ -200,6 +196,18 @@ module Figo
200
196
  return nil
201
197
  end
202
198
 
199
+ # Create a new figo Account
200
+ #
201
+ # @param name [String] First and last name
202
+ # @param email [String] Email address; It must obey the figo username & password policy
203
+ # @param password [String] New figo Account password; It must obey the figo username & password policy
204
+ # @param language [String] Two-letter code of preferred language
205
+ # @param send_newsletter [Boolean] This flag indicates whether the user has agreed to be contacted by email
206
+ # @return [Hash] object with the key `recovery_password` as documented in the figo Connect API specification
207
+ def create_user(name, email, password, language='de', send_newsletter=True)
208
+ data = { 'name' => name, 'email' => email, 'password' => password, 'language' => language, 'send_newsletter' => send_newsletter, 'affiliate_client_id' => @client_id}
209
+ return query_api("/auth/user", data)
210
+ end
203
211
  end
204
212
 
205
213
  # Represents a user-bound connection to the figo Connect API and allows access to the user's data.
@@ -244,116 +252,239 @@ module Figo
244
252
  response = @https.request(uri, request)
245
253
 
246
254
  # Evaluate HTTP response.
247
- if response.nil?
248
- return nil
249
- elsif response.body.nil?
250
- return nil
251
- else
252
- return response.body == "" ? nil : JSON.parse(response.body)
253
- end
255
+ return nil if response.nil?
256
+ return nil if response.body.nil?
257
+ return response.body == "" ? nil : JSON.parse(response.body)
258
+ end
259
+
260
+ def query_api_object(type, path, data=nil, method="GET", array_name=nil) # :nodoc:
261
+ response = query_api path, data, method
262
+ return nil if response.nil?
263
+ return type.new(self, response) if array_name.nil?
264
+ return response[array_name].map {|entry| type.new(self, entry)}
265
+ end
266
+
267
+ # Retrieve current User
268
+ #
269
+ # @return [User] the current user
270
+ def user
271
+ query_api_object User, "/rest/user"
272
+ end
273
+
274
+ # Modify the current user
275
+ #
276
+ # @param user [User] the modified user object to be saved
277
+ # @return [User] the modified user returned
278
+ def modify_user(user)
279
+ query_api_object User, "/rest/user", user.dump(), "PUT"
254
280
  end
255
281
 
256
- # Request list of accounts.
282
+ # Remove the current user
283
+ # Note: this has immidiate effect and you wont be able to interact with the user after this call
284
+ def remove_user
285
+ query_api "/rest/user", nil, "DELETE"
286
+ end
287
+
288
+ # Retrieve all accounts
257
289
  #
258
290
  # @return [Array] an array of `Account` objects, one for each account the user has granted the app access
259
291
  def accounts
260
- response = query_api("/rest/accounts")
261
- return response["accounts"].map {|account| Account.new(self, account)}
292
+ query_api_object Account, "/rest/accounts", nil, "GET", "accounts"
262
293
  end
263
294
 
264
- # Request specific account.
295
+ # Retrieve specific account.
265
296
  #
266
297
  # @param account_id [String] ID of the account to be retrieved.
267
298
  # @return [Account] account object
268
299
  def get_account(account_id)
269
- response = query_api("/rest/accounts/#{account_id}")
270
- return response.nil? ? nil : Account.new(self, response)
300
+ query_api_object Account, "/rest/accounts/#{account_id}"
301
+ end
302
+
303
+ # Modify specific account
304
+ #
305
+ # @param account [Account] modified account to be saved
306
+ # @return [Account] modified account returned by the server
307
+ def modify_account(account)
308
+ query_api_object Account, "/rest/accounts/#{account.account_id}", account.dump(), "PUT"
309
+ end
310
+
311
+ # Remove specific account
312
+ #
313
+ # @param account [Account, String] the account to be removed or its ID
314
+ def remove_account(account)
315
+ query_api account.is_a?(String) ? "/rest/accounts/#{account}" : "/rest/accounts/#{account.account_id}", nil, "DELETE"
271
316
  end
272
317
 
273
- # Request list of transactions.
318
+ # Retrieve balance of an account.
274
319
  #
320
+ # @return [AccountBalance] account balance object
321
+ def get_account_balance(account_id)
322
+ query_api_object AccountBalance, "/rest/accounts/#{account_id}/balance"
323
+ end
324
+
325
+ # Modify balance or account limits
326
+ #
327
+ # @param account_id [String] ID of the account which balance should be modified
328
+ # @param account_balance [AccountBalance] modified AccountBalance to be saved
329
+ # @return [AccountBalance] modified AccountBalance returned by server
330
+ def modify_account_balance(account_id, account_balance)
331
+ query_api_object AccountBalance, "/rest/accounts/#{account_id}/balance", account_balance.dump(), "PUT"
332
+ end
333
+
334
+ # Retrieve specific bank
335
+ #
336
+ # @return [Bank] bank object
337
+ def get_bank(bank_id)
338
+ query_api_object Bank, "/rest/banks/#{bank_id}"
339
+ end
340
+
341
+ # Modify bank
342
+ #
343
+ # @param bank [Bank] modified bank object
344
+ # @return [Bank] modified bank object returned by server
345
+ def modify_bank(bank)
346
+ query_api_object Bank, "/rest/banks/#{bank.bank_id}", bank.dump(), "PUT"
347
+ end
348
+
349
+ # Remove stored PIN from bank
350
+ #
351
+ # @param bank [Bank, String] the bank whose stored PIN should be removed or its ID
352
+ # @return [nil]
353
+ def remove_bank_pin(bank)
354
+ query_app bank.is_a?(String) ? "/rest/banks/#{bank}/submit": "/rest/banks/#{bank.bank_id}/submit", nil, "POST"
355
+ end
356
+
357
+ # Retrieve list of transactions (on all or a specific account)
358
+ #
359
+ # @param account_id [String] ID of the account for which to list the transactions
275
360
  # @param since [String, Date] this parameter can either be a transaction ID or a date
276
361
  # @param start_id [String] do only return transactions which were booked after the start transaction ID
277
362
  # @param count [Integer] limit the number of returned transactions
278
- # @param include_pending [Boolean] this flag indicates whether pending transactions should be included
279
- # in the response; pending transactions are always included as a complete set, regardless of
363
+ # @param include_pending [Boolean] this flag indicates whether pending transactions should be included
364
+ # in the response; pending transactions are always included as a complete set, regardless of
280
365
  # the `since` parameter
281
366
  # @return [Array] an array of `Transaction` objects, one for each transaction of the user
282
- def transactions(since = nil, start_id = nil, count = 1000, include_pending = false)
283
- data = {}
284
- data["since"] = (since.is_a?(Date) ? since.to_s : since) unless since.nil?
367
+ def transactions(account_id = nil, since = nil, start_id = nil, count = 1000, include_pending = false)
368
+ data = {"count" => count.to_s, "include_pending" => include_pending ? "1" : "0"}
369
+ data["since"] = ((since.is_a?(Date) ? since.to_s : since) unless since.nil?)
285
370
  data["start_id"] = start_id unless start_id.nil?
286
- data["count"] = count.to_s
287
- data["include_pending"] = include_pending ? "1" : "0"
288
- response = query_api("/rest/transactions?" + URI.encode_www_form(data))
289
- return response["transactions"].map {|transaction| Transaction.new(self, transaction)}
371
+
372
+ query_api_object Transaction, (account_id.nil? ? "/rest/transactions?" : "/rest/accounts/#{account_id}/transactions?") + URI.encode_www_form(data), nil, "GET", "transactions"
290
373
  end
291
374
 
292
- # Request the URL a user should open in the web browser to start the synchronization process.
375
+ # Retrieve a specific transaction
376
+ #
377
+ # @param account_id [String] ID of the account on which the transaction occured
378
+ # @param transaction_id [String] ID of the transaction to be retrieved
379
+ # @return [Transaction] transaction object
380
+ def get_transaction(account_id, transaction_id)
381
+ query_api_object Transaction, "/rest/accounts/#{account_id}/transactions/#{transaction_id}"
382
+ end
383
+
384
+ # Retrieve the URL a user should open in the web browser to start the synchronization process.
293
385
  #
294
386
  # @param redirect_uri [String] the user will be redirected to this URL after the process completes
295
- # @param state [String] this string will be passed on through the complete synchronization process
296
- # and to the redirect target at the end. It should be used to validated the authenticity of
387
+ # @param state [String] this string will be passed on through the complete synchronization process
388
+ # and to the redirect target at the end. It should be used to validated the authenticity of
297
389
  # the call to the redirect URL
298
- # @param disable_notifications [Booleon] this flag indicates whether notifications should be sent
299
- # @param if_not_synced_since [Integer] if this parameter is set, only those accounts will be
390
+ # @param if_not_synced_since [Integer] if this parameter is set, only those accounts will be
300
391
  # synchronized, which have not been synchronized within the specified number of minutes.
301
392
  # @return [String] the URL to be opened by the user.
302
- def sync_url(redirect_uri, state, disable_notifications = false, if_not_synced_since = 0)
303
- data = { "redirect_uri" => redirect_uri, "state" => state, "disable_notifications" => disable_notifications, "if_not_synced_since" => if_not_synced_since }
304
- response = query_api("/rest/sync", data, "POST")
393
+ def sync_url(redirect_uri, state, if_not_synced_since = 0)
394
+ response = query_api "/rest/sync", {"redirect_uri" => redirect_uri, "state" => state, "if_not_synced_since" => if_not_synced_since}, "POST"
305
395
  return "https://#{$api_endpoint}/task/start?id=#{response["task_token"]}"
306
396
  end
307
397
 
308
- # Request list of registered notifications.
398
+ # Retrieve list of registered notifications.
309
399
  #
310
400
  # @return [Notification] an array of `Notification` objects, one for each registered notification
311
401
  def notifications
312
- response = query_api("/rest/notifications")
313
- return response["notifications"].map {|notification| Notification.new(self, notification)}
402
+ query_api_object Notification, "/rest/notifications", nil, "GET", "notifications"
314
403
  end
315
404
 
316
- # Request specific notification.
405
+ # Retrieve specific notification.
317
406
  #
318
407
  # @param notification_id [String] ID of the notification to be retrieved
319
408
  # @return [Notification] `Notification` object for the respective notification
320
409
  def get_notification(notification_id)
321
- response = query_api("/rest/notifications/#{notification_id}")
322
- return response.nil? ? nil : Notification.new(self, response)
410
+ query_api_object Notification, "/rest/notifications/#{notification_id}"
323
411
  end
324
412
 
325
- # Register notification.
413
+ # Register a new notification.
326
414
  #
327
- # @param observe_key [String] one of the notification keys specified in the figo Connect API
328
- # specification
329
- # @param notify_uri [String] notification messages will be sent to this URL
330
- # @param state [String] any kind of string that will be forwarded in the notification message
415
+ # @param notification [Notification] notification to be crated. It should not have a notification_id set.
331
416
  # @return [Notification] newly created `Notification` object
332
- def add_notification(observe_key, notify_uri, state)
333
- data = { "observe_key" => observe_key, "notify_uri" => notify_uri, "state" => state }
334
- response = query_api("/rest/notifications", data, "POST")
335
- return Notification.new(self, response)
417
+ def add_notification(notification)
418
+ query_api_object Notification, "/rest/notifications", notification.dump(), "POST"
336
419
  end
337
420
 
338
421
  # Modify notification.
339
422
  #
340
423
  # @param notification [Notification] modified notification object
341
- # @return [nil]
424
+ # @return [Notification] modified notification returned by server
342
425
  def modify_notification(notification)
343
- data = { "observe_key" => notification.observe_key, "notify_uri" => notification.notify_uri, "state" => notification.state }
344
- query_api("/rest/notifications/#{notification.notification_id}", data, "PUT")
345
- return nil
426
+ query_api_object Notification, "/rest/notifications/#{notification.notification_id}", notification.dump(), "PUT"
346
427
  end
347
428
 
348
429
  # Unregister notification.
349
430
  #
350
- # @param notification [Notification] notification object which should be deleted
351
- # @return [nil]
431
+ # @param notification [Notification, String] notification object which should be deleted or its ID
352
432
  def remove_notification(notification)
353
- query_api("/rest/notifications/#{notification.notification_id}", nil, "DELETE")
354
- return nil
433
+ query_api notification.is_a?(String) ? "/rest/notifications/#{notification}" : "/rest/notifications/#{notification.notification_id}", nil, "DELETE"
355
434
  end
356
435
 
357
- end
436
+ # Retrieve list of all payments (on all accounts or one)
437
+ #
438
+ # @param account_id [String] ID of the account for whicht to list the payments
439
+ # @return [Payment] an array of `Payment` objects, one for each payment
440
+ def payments(account_id = nil)
441
+ query_api_object Payment, account_id.nil? ? "/rest/payments" : "/rest/accounts/#{account_id}/payments", nil, "GET", "payments"
442
+ end
358
443
 
444
+ # Retrieve specific payment.
445
+ #
446
+ # @param account_id [String] ID for the account on which the payment to be retrieved was created
447
+ # @param payment_id [String] ID of the notification to be retrieved
448
+ # @return [Payment] `Payment` object for the respective payment
449
+ def get_payment(account_id, payment_id)
450
+ query_api_object Payment, "/rest/accounts/#{account_id}/payments/#{payment_id}"
451
+ end
452
+
453
+ # Create new payment
454
+ #
455
+ # @param payment [Payment] payment object to be created. It should not have a payment_id set.
456
+ # @return [Payment] newly created `Payment` object
457
+ def add_payment(payment)
458
+ query_api_object Payment, "/rest/accounts/#{payment.account_id}/payments", payment.dump(), "POST"
459
+ end
460
+
461
+ # Modify payment
462
+ #
463
+ # @param payment [Payment] modified payment object
464
+ # @return [Payment] modified payment object
465
+ def modify_payment(payment)
466
+ query_api_object Payment, "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}", payment.dump(), "PUT"
467
+ end
468
+
469
+ # Submit payment
470
+ #
471
+ # @param tan_scheme_id [String] TAN scheme ID of user-selected TAN scheme
472
+ # @param state [String] Any kind of string that will be forwarded in the callback response message
473
+ # @param redirect_uri [String] At the end of the submission process a response will be sent to this callback URL
474
+ # @return [String] the URL to be opened by the user for the TAN process
475
+ def submit_payment(payment, tan_scheme_id, state, redirect_uri = nil)
476
+ params = {"tan_scheme_id" => tan_scheme_id, "state" => state}
477
+ params['redirect_uri'] = redirect_uri unless redirect_uri.nil?
478
+
479
+ response = query_api "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}/submit", params, "POST"
480
+ return "https://#{$api_endpoint}/task/start?id=#{response["task_token"]}"
481
+ end
482
+
483
+ # Remove payment
484
+ #
485
+ # @param payment [Payment, String] payment object which should be removed
486
+ def remove_payment(payment)
487
+ query_api "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}", nil, "DELETE"
488
+ end
489
+ end
359
490
  end