figo 1.2.5 → 1.3.3

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/config.yml +4 -0
  4. data/console_demo.rb +1 -1
  5. data/figo.gemspec +3 -3
  6. data/lib/account/api_call.rb +55 -0
  7. data/lib/account/model.rb +122 -0
  8. data/lib/account_balance/api_call.rb +18 -0
  9. data/lib/account_balance/model.rb +31 -0
  10. data/lib/authentification/api_call.rb +88 -0
  11. data/lib/bank/api_call.rb +49 -0
  12. data/lib/bank/model.rb +23 -0
  13. data/lib/base.rb +56 -0
  14. data/lib/cacert.pem +0 -0
  15. data/lib/figo.rb +54 -380
  16. data/lib/helpers/error.rb +20 -0
  17. data/lib/helpers/https.rb +52 -0
  18. data/lib/notification/api_call.rb +40 -0
  19. data/lib/notification/model.rb +27 -0
  20. data/lib/payment/api_call.rb +71 -0
  21. data/lib/payment/model.rb +75 -0
  22. data/lib/process/api_call.rb +17 -0
  23. data/lib/process/model.rb +34 -0
  24. data/lib/security/api_call.rb +59 -0
  25. data/lib/security/model.rb +83 -0
  26. data/lib/standing_order/api_call.rb +24 -0
  27. data/lib/standing_order/model.rb +75 -0
  28. data/lib/synchronization_status/api_call.rb +27 -0
  29. data/lib/synchronization_status/model.rb +23 -0
  30. data/lib/task/api_call.rb +37 -0
  31. data/lib/task/model.rb +43 -0
  32. data/lib/transaction/api_call.rb +57 -0
  33. data/lib/transaction/model.rb +75 -0
  34. data/lib/user/api_call.rb +46 -0
  35. data/lib/user/model.rb +55 -0
  36. data/test/config.yml +7 -0
  37. data/test/test_account_sync_and_setup.rb +67 -0
  38. data/test/test_accounts.rb +106 -0
  39. data/test/test_authentififcation.rb +68 -0
  40. data/test/test_business_processes.rb +43 -0
  41. data/test/test_figo.rb +5 -86
  42. data/test/test_notifications.rb +83 -0
  43. data/test/test_payments.rb +106 -0
  44. data/test/test_securities.rb +70 -0
  45. data/test/test_standing_orders.rb +49 -0
  46. data/test/test_transactions.rb +87 -0
  47. data/test/test_user_management.rb +91 -0
  48. metadata +64 -14
  49. data/lib/models.rb +0 -466
File without changes
@@ -21,102 +21,35 @@
21
21
  #
22
22
 
23
23
  require "json"
24
- require "net/http/persistent"
25
- require "digest/sha1"
26
- require_relative "models.rb"
24
+ require "yaml"
27
25
 
26
+ require_relative "./helpers/https.rb"
27
+ require_relative "./helpers/error.rb"
28
+
29
+ require_relative "./authentification/api_call.rb"
28
30
 
29
31
  # Ruby bindings for the figo Connect API: http://developer.figo.me
30
32
  module Figo
31
- $api_endpoint = "api.figo.me"
32
-
33
- $valid_fingerprints = ["38:AE:4A:32:6F:16:EA:15:81:33:8B:B0:D8:E4:A6:35:E7:27:F1:07",
34
- "CF:C1:BC:7F:6A:16:09:2B:10:83:8A:B0:22:4F:3A:65:D2:70:D7:3E"]
35
-
36
- # Base class for all errors transported via the figo Connect API.
37
- class Error < RuntimeError
38
- # Initialize error object.
39
- #
40
- # @param error [String] the error code
41
- # @param error_description [String] the error description
42
- def initialize(error, error_description)
43
- @error = error
44
- @error_description = error_description
45
- end
46
-
47
- # Convert error object to string.
48
- #
49
- # @return [String] the error description
50
- def to_s
51
- return @error_description
52
- end
53
- end
54
-
55
- # HTTPS class with certificate authentication and enhanced error handling.
56
- class HTTPS < Net::HTTP::Persistent
57
- # Overwrite `initialize` method from `Net::HTTP::Persistent`.
58
- #
59
- # Verify fingerprints of server SSL/TLS certificates.
60
- def initialize(name = nil, proxy = nil)
61
- super(name, proxy)
62
-
63
- # Attribute ca_file must be set, otherwise verify_callback would never be called.
64
- @ca_file = "lib/cacert.pem"
65
- @verify_callback = proc do |preverify_ok, store_context|
66
- if preverify_ok and store_context.error == 0
67
- certificate = OpenSSL::X509::Certificate.new(store_context.chain[0])
68
- fingerprint = Digest::SHA1.hexdigest(certificate.to_der).upcase.scan(/../).join(":")
69
- $valid_fingerprints.include?(fingerprint)
70
- else
71
- false
72
- end
73
- end
74
- end
75
-
76
- # Overwrite `request` method from `Net::HTTP::Persistent`.
77
- #
78
- # Raise error when a REST API error is returned.
79
- def request(uri, req = nil, &block)
80
- response = super(uri, req, &block)
81
-
82
- # Evaluate HTTP response.
83
- case response
84
- when Net::HTTPSuccess
85
- return response
86
- when Net::HTTPBadRequest
87
- hash = JSON.parse(response.body)
88
- raise Error.new(hash["error"], hash["error_description"])
89
- when Net::HTTPUnauthorized
90
- raise Error.new("unauthorized", "Missing, invalid or expired access token.")
91
- when Net::HTTPForbidden
92
- raise Error.new("forbidden", "Insufficient permission.")
93
- when Net::HTTPNotFound
94
- return nil
95
- when Net::HTTPMethodNotAllowed
96
- raise Error.new("method_not_allowed", "Unexpected request method.")
97
- when Net::HTTPServiceUnavailable
98
- raise Error.new("service_unavailable", "Exceeded rate limit.")
99
- else
100
- raise Error.new("internal_server_error", "We are very sorry, but something went wrong.")
101
- end
102
- end
103
-
104
- end
33
+ $config = YAML.load_file(File.join(__dir__, '../config.yml'))
34
+ $api_endpoint = $config["API_ENDPOINT"]
35
+ $valid_fingerprints = $config["FINGER_PRINTS"]
105
36
 
106
37
  # Represents a non user-bound connection to the figo Connect API.
107
38
  #
108
39
  # It's main purpose is to let user login via OAuth 2.0.
109
40
  class Connection
41
+ include Figo
110
42
  # Create connection object with client credentials.
111
43
  #
112
44
  # @param client_id [String] the client ID
113
45
  # @param client_secret [String] the client secret
114
46
  # @param redirect_uri [String] optional redirect URI
115
- def initialize(client_id, client_secret, redirect_uri = nil)
47
+ def initialize(client_id, client_secret, redirect_uri = nil, fingerprints = $valid_fingerprints, api_endpoint = $api_endpoint)
116
48
  @client_id = client_id
117
49
  @client_secret = client_secret
118
50
  @redirect_uri = redirect_uri
119
- @https = HTTPS.new("figo-#{client_id}")
51
+ @https = HTTPS.new("figo-#{client_id}", nil, fingerprints)
52
+ @api_endpoint = api_endpoint
120
53
  end
121
54
 
122
55
  # Helper method for making a OAuth 2.0 request.
@@ -125,14 +58,14 @@ module Figo
125
58
  # @param data [Hash] this optional object will be used as url-encoded POST content.
126
59
  # @return [Hash] JSON response
127
60
  def query_api(path, data = nil)
128
- uri = URI("https://#{$api_endpoint}#{path}")
61
+ uri = URI("https://#{@api_endpoint}#{path}")
129
62
 
130
63
  # Setup HTTP request.
131
64
  request = Net::HTTP::Post.new(path)
132
65
  request.basic_auth(@client_id, @client_secret)
133
66
  request["Accept"] = "application/json"
134
67
  request["Content-Type"] = "application/x-www-form-urlencoded"
135
- request["User-Agent"] = "ruby-figo"
68
+ request["User-Agent"] = "figo-ruby/1.3.1"
136
69
  request.body = URI.encode_www_form(data) unless data.nil?
137
70
 
138
71
  # Send HTTP request.
@@ -141,84 +74,55 @@ module Figo
141
74
  # Evaluate HTTP response.
142
75
  return response.body == "" ? {} : JSON.parse(response.body)
143
76
  end
77
+ end
144
78
 
79
+ # Represents a user-bound connection to the figo Connect API and allows access to the user's data.
80
+ class Session
81
+ require_relative "./account_balance/model.rb"
82
+ require_relative "./account_balance/api_call.rb"
145
83
 
146
- # Get the URL a user should open in the web browser to start the login process.
147
- #
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
150
- # into an access token for data access.
151
- #
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
154
- # validated the authenticity of the call to the redirect URL
155
- # @param scope [String] optional scope of data access to ask the user for,
156
- # e.g. `accounts=ro`
157
- # @return [String] the URL to be opened by the user.
158
- def login_url(state, scope = nil)
159
- data = { "response_type" => "code", "client_id" => @client_id, "state" => state }
160
- data["redirect_uri"] = @redirect_uri unless @redirect_uri.nil?
161
- data["scope"] = scope unless scope.nil?
162
- return "https://#{$api_endpoint}/auth/code?" + URI.encode_www_form(data)
163
- end
84
+ require_relative "./account/model.rb"
85
+ require_relative "./account/api_call.rb"
164
86
 
87
+ require_relative "./bank/model.rb"
88
+ require_relative "./bank/api_call.rb"
165
89
 
166
- # Exchange authorization code or refresh token for access token.
167
- #
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
170
- # logon process, or a refresh token
171
- # @param scope [String] optional scope of data access to ask the user for,
172
- # e.g. `accounts=ro`
173
- # @return [Hash] object with the keys `access_token`, `refresh_token` and
174
- # `expires`, as documented in the figo Connect API specification.
175
- def obtain_access_token(authorization_code_or_refresh_token, scope = nil)
176
- # Authorization codes always start with "O" and refresh tokens always start with "R".
177
- if authorization_code_or_refresh_token[0] == "O"
178
- data = { "grant_type" => "authorization_code", "code" => authorization_code_or_refresh_token }
179
- data["redirect_uri"] = @redirect_uri unless @redirect_uri.nil?
180
- elsif authorization_code_or_refresh_token[0] == "R"
181
- data = { "grant_type" => "refresh_token", "refresh_token" => authorization_code_or_refresh_token }
182
- data["scope"] = scope unless scope.nil?
183
- end
184
- return query_api("/auth/token", data)
185
- end
90
+ require_relative "./notification/model.rb"
91
+ require_relative "./notification/api_call.rb"
186
92
 
187
- # Revoke refresh token or access token.
188
- #
189
- # @note this action has immediate effect, i.e. you will not be able use that token anymore after this call.
190
- #
191
- # @param refresh_token_or_access_token [String] access or refresh token to be revoked
192
- # @return [nil]
193
- def revoke_token(refresh_token_or_access_token)
194
- data = { "token" => refresh_token_or_access_token }
195
- query_api("/auth/revoke?" + URI.encode_www_form(data))
196
- return nil
197
- end
93
+ require_relative "./payment/model.rb"
94
+ require_relative "./payment/api_call.rb"
198
95
 
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 -- Not accepted by backend at the moment
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, 'affiliate_client_id' => @client_id} #'send_newsletter' => send_newsletter,
209
- return query_api("/auth/user", data)
210
- end
211
- end
96
+ require_relative "./synchronization_status/model.rb"
97
+ require_relative "./synchronization_status/api_call.rb"
212
98
 
213
- # Represents a user-bound connection to the figo Connect API and allows access to the user's data.
214
- class Session
99
+ require_relative "./transaction/model.rb"
100
+ require_relative "./transaction/api_call.rb"
101
+
102
+ require_relative "./user/model.rb"
103
+ require_relative "./user/api_call.rb"
104
+
105
+ require_relative "./standing_order/model.rb"
106
+ require_relative "./standing_order/api_call.rb"
107
+
108
+ require_relative "./process/model.rb"
109
+ require_relative "./process/api_call.rb"
110
+
111
+ require_relative "./security/model.rb"
112
+ require_relative "./security/api_call.rb"
113
+
114
+ require_relative "./task/model.rb"
115
+ require_relative "./task/api_call.rb"
116
+
117
+ include Figo
215
118
 
216
119
  # Create session object with access token.
217
120
  #
218
121
  # @param access_token [String] the access token
219
- def initialize(access_token)
122
+ def initialize(access_token, fingerprints = $valid_fingerprints, api_endpoint = $api_endpoint)
220
123
  @access_token = access_token
221
- @https = HTTPS.new("figo-#{access_token}")
124
+ @https = HTTPS.new("figo-#{access_token}", nil, fingerprints)
125
+ @api_endpoint = api_endpoint
222
126
  end
223
127
 
224
128
  # Helper method for making a REST request.
@@ -228,7 +132,7 @@ module Figo
228
132
  # @param method [String] the HTTP method
229
133
  # @return [Hash] JSON response
230
134
  def query_api(path, data=nil, method="GET") # :nodoc:
231
- uri = URI("https://#{$api_endpoint}#{path}")
135
+ uri = URI("https://#{@api_endpoint}#{path}")
232
136
 
233
137
  # Setup HTTP request.
234
138
  request = case method
@@ -245,7 +149,8 @@ module Figo
245
149
  request["Authorization"] = "Bearer #{@access_token}"
246
150
  request["Accept"] = "application/json"
247
151
  request["Content-Type"] = "application/json"
248
- request["User-Agent"] = "ruby-figo"
152
+ request["User-Agent"] = "figo-ruby/1.3.1"
153
+
249
154
  request.body = JSON.generate(data) unless data.nil?
250
155
 
251
156
  # Send HTTP request.
@@ -263,236 +168,5 @@ module Figo
263
168
  return type.new(self, response) if array_name.nil?
264
169
  return response[array_name].map {|entry| type.new(self, entry)}
265
170
  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"
280
- end
281
-
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
289
- #
290
- # @return [Array] an array of `Account` objects, one for each account the user has granted the app access
291
- def accounts
292
- query_api_object Account, "/rest/accounts", nil, "GET", "accounts"
293
- end
294
-
295
- # Retrieve specific account.
296
- #
297
- # @param account_id [String] ID of the account to be retrieved.
298
- # @return [Account] account object
299
- def get_account(account_id)
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"
316
- end
317
-
318
- # Retrieve balance of an account.
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_api bank.is_a?(String) ? "/rest/banks/#{bank}/submit": "/rest/banks/#{bank.bank_id}/submit", nil, "POST"
355
- end
356
-
357
- # Get bank information from standard bank code
358
- #
359
- # @param country_code [String]
360
- # @param bank_code [String] bank sort code (Bankleitzahl)
361
- # @return [Hash] JSON response
362
- def find_bank(bank_code, country_code)
363
- query_api "/rest/catalog/banks/#{country_code}/#{bank_code}"
364
- end
365
-
366
- # Retrieve list of transactions (on all or a specific account)
367
- #
368
- # @param account_id [String] ID of the account for which to list the transactions
369
- # @param since [String, Date] this parameter can either be a transaction ID or a date
370
- # @param count [Integer] limit the number of returned transactions
371
- # @param offset [Integer] which offset into the result set should be used to determin the first transaction to return (useful in combination with count)
372
- # @param include_pending [Boolean] this flag indicates whether pending transactions should be included
373
- # in the response; pending transactions are always included as a complete set, regardless of
374
- # the `since` parameter
375
- # @return [Array] an array of `Transaction` objects, one for each transaction of the user
376
- def transactions(account_id = nil, since = nil, count = 1000, offset = 0, include_pending = false)
377
- data = {"count" => count.to_s, "offset" => offset.to_s, "include_pending" => include_pending ? "1" : "0"}
378
- data["since"] = ((since.is_a?(Date) ? since.to_s : since) unless since.nil?)
379
-
380
- query_api_object Transaction, (account_id.nil? ? "/rest/transactions?" : "/rest/accounts/#{account_id}/transactions?") + URI.encode_www_form(data), nil, "GET", "transactions"
381
- end
382
-
383
- # Retrieve a specific transaction
384
- #
385
- # @param account_id [String] ID of the account on which the transaction occured
386
- # @param transaction_id [String] ID of the transaction to be retrieved
387
- # @return [Transaction] transaction object
388
- def get_transaction(account_id, transaction_id)
389
- query_api_object Transaction, "/rest/accounts/#{account_id}/transactions/#{transaction_id}"
390
- end
391
-
392
- # Retrieve the URL a user should open in the web browser to start the synchronization process.
393
- #
394
- # @param redirect_uri [String] the user will be redirected to this URL after the process completes
395
- # @param state [String] this string will be passed on through the complete synchronization process
396
- # and to the redirect target at the end. It should be used to validated the authenticity of
397
- # the call to the redirect URL
398
- # @param if_not_synced_since [Integer] if this parameter is set, only those accounts will be
399
- # synchronized, which have not been synchronized within the specified number of minutes.
400
- # @return [String] the URL to be opened by the user.
401
- def sync_url(redirect_uri, state, if_not_synced_since = 0)
402
- response = query_api "/rest/sync", {"redirect_uri" => redirect_uri, "state" => state, "if_not_synced_since" => if_not_synced_since}, "POST"
403
- return "https://#{$api_endpoint}/task/start?id=#{response["task_token"]}"
404
- end
405
-
406
- # Retrieve list of registered notifications.
407
- #
408
- # @return [Notification] an array of `Notification` objects, one for each registered notification
409
- def notifications
410
- query_api_object Notification, "/rest/notifications", nil, "GET", "notifications"
411
- end
412
-
413
- # Retrieve specific notification.
414
- #
415
- # @param notification_id [String] ID of the notification to be retrieved
416
- # @return [Notification] `Notification` object for the respective notification
417
- def get_notification(notification_id)
418
- query_api_object Notification, "/rest/notifications/#{notification_id}"
419
- end
420
-
421
- # Register a new notification.
422
- #
423
- # @param notification [Notification] notification to be crated. It should not have a notification_id set.
424
- # @return [Notification] newly created `Notification` object
425
- def add_notification(notification)
426
- query_api_object Notification, "/rest/notifications", notification.dump(), "POST"
427
- end
428
-
429
- # Modify notification.
430
- #
431
- # @param notification [Notification] modified notification object
432
- # @return [Notification] modified notification returned by server
433
- def modify_notification(notification)
434
- query_api_object Notification, "/rest/notifications/#{notification.notification_id}", notification.dump(), "PUT"
435
- end
436
-
437
- # Unregister notification.
438
- #
439
- # @param notification [Notification, String] notification object which should be deleted or its ID
440
- def remove_notification(notification)
441
- query_api notification.is_a?(String) ? "/rest/notifications/#{notification}" : "/rest/notifications/#{notification.notification_id}", nil, "DELETE"
442
- end
443
-
444
- # Retrieve list of all payments (on all accounts or one)
445
- #
446
- # @param account_id [String] ID of the account for whicht to list the payments
447
- # @return [Payment] an array of `Payment` objects, one for each payment
448
- def payments(account_id = nil)
449
- query_api_object Payment, account_id.nil? ? "/rest/payments" : "/rest/accounts/#{account_id}/payments", nil, "GET", "payments"
450
- end
451
-
452
- # Retrieve specific payment.
453
- #
454
- # @param account_id [String] ID for the account on which the payment to be retrieved was created
455
- # @param payment_id [String] ID of the notification to be retrieved
456
- # @return [Payment] `Payment` object for the respective payment
457
- def get_payment(account_id, payment_id)
458
- query_api_object Payment, "/rest/accounts/#{account_id}/payments/#{payment_id}"
459
- end
460
-
461
- # Create new payment
462
- #
463
- # @param payment [Payment] payment object to be created. It should not have a payment_id set.
464
- # @return [Payment] newly created `Payment` object
465
- def add_payment(payment)
466
- query_api_object Payment, "/rest/accounts/#{payment.account_id}/payments", payment.dump(), "POST"
467
- end
468
-
469
- # Modify payment
470
- #
471
- # @param payment [Payment] modified payment object
472
- # @return [Payment] modified payment object
473
- def modify_payment(payment)
474
- query_api_object Payment, "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}", payment.dump(), "PUT"
475
- end
476
-
477
- # Submit payment
478
- #
479
- # @param tan_scheme_id [String] TAN scheme ID of user-selected TAN scheme
480
- # @param state [String] Any kind of string that will be forwarded in the callback response message
481
- # @param redirect_uri [String] At the end of the submission process a response will be sent to this callback URL
482
- # @return [String] the URL to be opened by the user for the TAN process
483
- def submit_payment(payment, tan_scheme_id, state, redirect_uri = nil)
484
- params = {"tan_scheme_id" => tan_scheme_id, "state" => state}
485
- params['redirect_uri'] = redirect_uri unless redirect_uri.nil?
486
-
487
- response = query_api "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}/submit", params, "POST"
488
- return "https://#{$api_endpoint}/task/start?id=#{response["task_token"]}"
489
- end
490
-
491
- # Remove payment
492
- #
493
- # @param payment [Payment, String] payment object which should be removed
494
- def remove_payment(payment)
495
- query_api "/rest/accounts/#{payment.account_id}/payments/#{payment.payment_id}", nil, "DELETE"
496
- end
497
171
  end
498
172
  end