starling-ruby 0.1.0 → 0.2.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +8 -0
  3. data/.gitignore +1 -0
  4. data/.reek +27 -0
  5. data/.rubocop.yml +6 -4
  6. data/CHANGELOG.md +17 -0
  7. data/Gemfile.lock +37 -2
  8. data/README.md +102 -17
  9. data/bin/console +2 -6
  10. data/lib/starling.rb +40 -7
  11. data/lib/starling/api_service.rb +45 -37
  12. data/lib/starling/client.rb +165 -6
  13. data/lib/starling/errors/api_error.rb +35 -2
  14. data/lib/starling/errors/base_error.rb +6 -24
  15. data/lib/starling/middlewares/raise_starling_errors.rb +11 -10
  16. data/lib/starling/request.rb +17 -19
  17. data/lib/starling/resources/account_balance_resource.rb +14 -6
  18. data/lib/starling/resources/account_resource.rb +10 -0
  19. data/lib/starling/resources/address_resource.rb +26 -0
  20. data/lib/starling/resources/addresses_resource.rb +18 -0
  21. data/lib/starling/resources/base_resource.rb +34 -9
  22. data/lib/starling/resources/card_resource.rb +46 -0
  23. data/lib/starling/resources/contact_account_resource.rb +31 -0
  24. data/lib/starling/resources/contact_resource.rb +16 -0
  25. data/lib/starling/resources/customer_resource.rb +36 -0
  26. data/lib/starling/resources/direct_debit_mandate_resource.rb +43 -0
  27. data/lib/starling/resources/direct_debit_transaction_resource.rb +54 -0
  28. data/lib/starling/resources/inbound_faster_payments_transaction_resource.rb +56 -0
  29. data/lib/starling/resources/mastercard_transaction_resource.rb +73 -0
  30. data/lib/starling/resources/me_resource.rb +26 -0
  31. data/lib/starling/resources/merchant_location_resource.rb +33 -0
  32. data/lib/starling/resources/merchant_resource.rb +34 -0
  33. data/lib/starling/resources/outbound_faster_payments_transaction_resource.rb +56 -0
  34. data/lib/starling/resources/payment_resource.rb +78 -0
  35. data/lib/starling/resources/transaction_resource.rb +42 -0
  36. data/lib/starling/services/account_balance_service.rb +11 -2
  37. data/lib/starling/services/account_service.rb +16 -3
  38. data/lib/starling/services/addresses_service.rb +26 -0
  39. data/lib/starling/services/base_service.rb +22 -1
  40. data/lib/starling/services/card_service.rb +26 -0
  41. data/lib/starling/services/contact_accounts_service.rb +54 -0
  42. data/lib/starling/services/contacts_service.rb +73 -0
  43. data/lib/starling/services/customer_service.rb +25 -0
  44. data/lib/starling/services/direct_debit_mandates_service.rb +61 -0
  45. data/lib/starling/services/direct_debit_transactions_service.rb +46 -0
  46. data/lib/starling/services/inbound_faster_payments_transactions_service.rb +46 -0
  47. data/lib/starling/services/mastercard_transactions_service.rb +30 -0
  48. data/lib/starling/services/me_service.rb +26 -0
  49. data/lib/starling/services/merchant_locations_service.rb +34 -0
  50. data/lib/starling/services/merchants_service.rb +26 -0
  51. data/lib/starling/services/outbound_faster_payments_transactions_service.rb +46 -0
  52. data/lib/starling/services/payments_service.rb +30 -0
  53. data/lib/starling/services/transactions_service.rb +44 -0
  54. data/lib/starling/utils.rb +30 -0
  55. data/lib/starling/version.rb +1 -1
  56. data/starling-ruby.gemspec +2 -0
  57. metadata +63 -2
@@ -0,0 +1,26 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing an address in the response from the Addresses API
4
+ class AddressResource < BaseResource
5
+ # @return [String] the city where the address is located
6
+ def city
7
+ parsed_data['city']
8
+ end
9
+
10
+ # @return [String] the country where the addresses is located (e.g. "GBR")
11
+ def country
12
+ parsed_data['country']
13
+ end
14
+
15
+ # @return [String] the postcode of the address
16
+ def postcode
17
+ parsed_data['postcode']
18
+ end
19
+
20
+ # @return [String] the street address of the address
21
+ def street_address
22
+ parsed_data['streetAddress']
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a response from the Addresses API
4
+ class AddressesResource < BaseResource
5
+ # @return [AddressResource] the user's current address
6
+ def current
7
+ AddressResource.new(parsed_data: parsed_data['current'])
8
+ end
9
+
10
+ # @return [Array<AddressResource>] a list of the user's previous addresses
11
+ def previous
12
+ parsed_data['previous'].map do |address|
13
+ AddressResource.new(parsed_data: address)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,38 +1,63 @@
1
1
  require 'json'
2
2
  require 'time'
3
+ require 'date'
3
4
 
4
5
  module Starling
5
6
  module Resources
7
+ # A basic implementation of a resource representing a response from the Starling Bank
8
+ # API
6
9
  class BaseResource
7
- # A resource can be instantiated with either a Faraday::Response, including a
8
- # #body, or with a Hash pre-parsed from JSON
10
+ # A resource can be instantiated with either a Faraday::Response (including a
11
+ # #body), or with a Hash pre-parsed from JSON.
12
+ #
13
+ # An alternative possible approach to our resources would be to parse out the
14
+ # attributes we care about at initialisation, and then just add `attr_reader`s,
15
+ # rather than looking into the parsed JSON hash. The current solution is probably
16
+ # preferable, since it defers delving into the hash until a parameter is actually
17
+ # wanted, and keeps instance variables to a minimum.
18
+ #
19
+ # @param response [Faraday::Response] The complete HTTP response, returned by
20
+ # {Request#make_request}
21
+ # @param parsed_data [Hash] The pre-parsed data for the resource, useful for
22
+ # building resources from list resources we've already
23
+ # parsed
9
24
  def initialize(response: nil, parsed_data: nil)
10
- if response.nil? && parsed_data.nil?
25
+ unless response || parsed_data
11
26
  raise ArgumentError, 'Either response or parsed_data must be provided to ' \
12
27
  'instantiate a resource'
13
28
  end
14
29
 
15
30
  @response = response
16
- @parsed_data = parsed_data
31
+ @parsed_data = parsed_data || JSON.parse(response.body)
17
32
  end
18
33
 
19
34
  private
20
35
 
36
+ attr_reader :parsed_data
37
+
21
38
  def present_datetime(iso8601_string)
22
39
  Time.parse(iso8601_string)
23
40
  end
24
41
 
42
+ def present_date(string)
43
+ Date.parse(string)
44
+ end
45
+
46
+ # Many fields returned in the API (e.g. transaction amounts) can be either integers
47
+ # or more complex values with decimal places. The JSON parser will turn these into
48
+ # Integer (Fixnum in Ruby versions before 2.4) and Float objects respectively. For
49
+ # consistency, we will convert anything that *could* be a Float into a Float.
50
+ def present_float(number)
51
+ Float(number)
52
+ end
53
+
25
54
  # Some strings returned by the API are specified as Enum types, with a specified
26
55
  # set of possible values. These are best represented in Ruby as symbols (e.g.
27
56
  # the Transaction API's `source` can have the value MASTER_CARD, which will become
28
57
  # :master_card.
29
- def symbolize_enum_string(enum_string)
58
+ def present_enum(enum_string)
30
59
  enum_string.downcase.to_sym
31
60
  end
32
-
33
- def parsed_data
34
- @parsed_data ||= JSON.parse(@response.body)
35
- end
36
61
  end
37
62
  end
38
63
  end
@@ -0,0 +1,46 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a response from the Card API
4
+ class CardResource < BaseResource
5
+ # @return [String] the Starling internal ID of the card
6
+ def id
7
+ parsed_data['id']
8
+ end
9
+
10
+ # @return [String] the name on the front of the card
11
+ def name_on_card
12
+ parsed_data['nameOnCard']
13
+ end
14
+
15
+ # @return [String] the type of the card (e.g. "ContactlessDebitMastercard")
16
+ def type
17
+ parsed_data['type']
18
+ end
19
+
20
+ # @return [true, false] whether the card is enabled
21
+ def enabled
22
+ parsed_data['enabled']
23
+ end
24
+
25
+ # @return [true, false] whether the card has been cancelled
26
+ def cancelled
27
+ parsed_data['cancelled']
28
+ end
29
+
30
+ # @return [true, false] whether the card's activation has been requested
31
+ def activation_requested
32
+ parsed_data['activationRequested']
33
+ end
34
+
35
+ # @return [true, false] whether the card has been activated
36
+ def activated
37
+ parsed_data['activated']
38
+ end
39
+
40
+ # @return [Date] when the card was dispatched by post to the user
41
+ def dispatch_date
42
+ present_date(parsed_data['dispatchDate'])
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,31 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a Contact Account returned from the Contact Accounts API
4
+ class ContactAccountResource < BaseResource
5
+ # @return [String] the Starling internal ID of the contact account
6
+ def id
7
+ parsed_data['id']
8
+ end
9
+
10
+ # @return [String] the name of the contact account
11
+ def name
12
+ parsed_data['name']
13
+ end
14
+
15
+ # @return [Symbol] the type of the contact account (e.g. `:domestic`)
16
+ def type
17
+ present_enum(parsed_data['type'])
18
+ end
19
+
20
+ # @return [String] the account number of the contact account
21
+ def account_number
22
+ parsed_data['accountNumber']
23
+ end
24
+
25
+ # @return [String] the sort code of the contact account
26
+ def sort_code
27
+ parsed_data['sortCode']
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a Contact returned from the Contacts API
4
+ class ContactResource < BaseResource
5
+ # @return [String] the Starling internal ID of the contact
6
+ def id
7
+ parsed_data['id']
8
+ end
9
+
10
+ # @return [String] the name of the contact
11
+ def name
12
+ parsed_data['name']
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,36 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing the response returned from the Customer API
4
+ class CustomerResource < BaseResource
5
+ # @return [String] the Starling internal ID of the customer
6
+ def customer_uid
7
+ parsed_data['customerUid']
8
+ end
9
+
10
+ # @return [String] the first name of the customer
11
+ def first_name
12
+ parsed_data['firstName']
13
+ end
14
+
15
+ # @return [String] the last name of the customer
16
+ def last_name
17
+ parsed_data['lastName']
18
+ end
19
+
20
+ # @return [Date] the date of birth of the customer
21
+ def date_of_birth
22
+ present_date(parsed_data['dateOfBirth'])
23
+ end
24
+
25
+ # @return [String] the email address of the customer
26
+ def email
27
+ parsed_data['email']
28
+ end
29
+
30
+ # @return [String] the phone number of the customer
31
+ def phone
32
+ parsed_data['phone']
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a Direct Debit mandate returned from the Direct Debit
4
+ # Mandates API
5
+ class DirectDebitMandateResource < BaseResource
6
+ # @return [String] the Starling internal ID of the Direct Debit mandate
7
+ def uid
8
+ parsed_data['uid']
9
+ end
10
+
11
+ # @return [String] the reference of the Direct Debit mandate
12
+ def reference
13
+ parsed_data['reference']
14
+ end
15
+
16
+ # @return [Symbol] the status of the mandate (e.g. `:live`)
17
+ def status
18
+ present_enum(parsed_data['status'])
19
+ end
20
+
21
+ # @return [Symbol] the source of the mandate (e.g. `:electronic` or `paper)
22
+ def source
23
+ present_enum(parsed_data['source'])
24
+ end
25
+
26
+ # @return [Time] the date when the mandate was created
27
+ def created
28
+ present_datetime(parsed_data['created'])
29
+ end
30
+ alias created_at created
31
+
32
+ # @return [String] the name of the Direct Debit mandate's originator
33
+ def originator_name
34
+ parsed_data['originatorName']
35
+ end
36
+
37
+ # @return [String] the Starling internal ID of the Direct Debit mandate's originator
38
+ def originator_uid
39
+ parsed_data['originatorUid']
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,54 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a Transaction returned from the Transaction Direct Debit
4
+ # API
5
+ class DirectDebitTransactionResource < BaseResource
6
+ # @return [String] the Starling internal ID of the transaction
7
+ def id
8
+ parsed_data['id']
9
+ end
10
+
11
+ # @return [String] the currency of the transaction (e.g. "GBP" or "UAH")
12
+ def currency
13
+ parsed_data['currency']
14
+ end
15
+
16
+ # @return [Float] the amount of the transaction
17
+ def amount
18
+ present_float(parsed_data['amount'])
19
+ end
20
+
21
+ # @return [Symbol] the direction of the transaction (e.g. `:outbound`)
22
+ def direction
23
+ present_enum(parsed_data['direction'])
24
+ end
25
+
26
+ # @return [Time] the date and time when the transaction was recorded
27
+ def created
28
+ present_datetime(parsed_data['created'])
29
+ end
30
+ alias created_at created
31
+
32
+ # @return [String] the narrative of the transaction
33
+ def narrative
34
+ parsed_data['narrative']
35
+ end
36
+
37
+ # @return [Symbol] the source of the transaction (e.g. `:master_card`)
38
+ def source
39
+ present_enum(parsed_data['source'])
40
+ end
41
+
42
+ # @return [String] the Starling internal ID of the Direct Debit mandate
43
+ def mandate_id
44
+ parsed_data['mandateId']
45
+ end
46
+
47
+ # @return [Symbol] the type of the transaction
48
+ # (e.g. `:first_payment_of_direct_debit` or `:direct_debit`)
49
+ def type
50
+ present_enum(parsed_data['type'])
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,56 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a Transaction returned from the Transactions Faster
4
+ # Payments In API
5
+ class InboundFasterPaymentsTransactionResource < BaseResource
6
+ # @return [String] the Starling internal ID of the transaction
7
+ def id
8
+ parsed_data['id']
9
+ end
10
+
11
+ # @return [String] the currency of the transaction (e.g. "GBP" or "UAH")
12
+ def currency
13
+ parsed_data['currency']
14
+ end
15
+
16
+ # @return [Float] the amount of the transaction
17
+ def amount
18
+ present_float(parsed_data['amount'])
19
+ end
20
+
21
+ # @return [Symbol] the direction of the transaction (e.g. `:outbound`)
22
+ def direction
23
+ present_enum(parsed_data['direction'])
24
+ end
25
+
26
+ # @return [Time] the date and time when the transaction was recorded
27
+ def created
28
+ present_datetime(parsed_data['created'])
29
+ end
30
+ alias created_at created
31
+
32
+ # @return [String] the narrative of the transaction
33
+ def narrative
34
+ parsed_data['narrative']
35
+ end
36
+
37
+ # @return [Symbol] the source of the transaction (e.g. `:master_card`)
38
+ def source
39
+ present_enum(parsed_data['source'])
40
+ end
41
+
42
+ # @return [String, nil] the Starling internal ID of the contact who sent the
43
+ # payment, or nil if they are not one of the user's contacts
44
+ def sending_contact_id
45
+ parsed_data['sendingContactId']
46
+ end
47
+
48
+ # @return [String, nil] the Starling internal ID of the contact account which sent
49
+ # the payment, or nil if they are not one of the user's
50
+ # contacts
51
+ def sending_contact_account_id
52
+ parsed_data['sendingContactAccountId']
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,73 @@
1
+ module Starling
2
+ module Resources
3
+ # A resource representing a Transaction returned from the Transactions Mastercard API
4
+ class MastercardTransactionResource < BaseResource
5
+ # @return [String] the Starling internal ID of the transaction
6
+ def id
7
+ parsed_data['id']
8
+ end
9
+
10
+ # @return [String] the currency of the transaction (e.g. "GBP" or "UAH")
11
+ def currency
12
+ parsed_data['currency']
13
+ end
14
+
15
+ # @return [Float] the amount of the transaction
16
+ def amount
17
+ present_float(parsed_data['amount'])
18
+ end
19
+
20
+ # @return [Symbol] the direction of the transaction (e.g. `:outbound`)
21
+ def direction
22
+ present_enum(parsed_data['direction'])
23
+ end
24
+
25
+ # @return [Time] the date and time when the transaction was recorded
26
+ def created
27
+ present_datetime(parsed_data['created'])
28
+ end
29
+ alias created_at created
30
+
31
+ # @return [String] the narrative of the transaction
32
+ def narrative
33
+ parsed_data['narrative']
34
+ end
35
+
36
+ # @return [Symbol] the source of the transaction (e.g. `:master_card`)
37
+ def source
38
+ present_enum(parsed_data['source'])
39
+ end
40
+
41
+ # @return [Symbol] the MasterCard transaction method of the transaction (e.g.
42
+ # `:contactless`)
43
+ def mastercard_transaction_method
44
+ present_enum(parsed_data['mastercardTransactionMethod'])
45
+ end
46
+
47
+ # @return [Symbol] the status of the transaction (e.g. `:settled`)
48
+ def status
49
+ present_enum(parsed_data['status'])
50
+ end
51
+
52
+ # @return [String] the source currency of the transaction (e.g. "GBP" or "UAH")
53
+ def source_currency
54
+ parsed_data['sourceCurrency']
55
+ end
56
+
57
+ # @return [Float] the source amount of the transaction
58
+ def source_amount
59
+ present_float(parsed_data['sourceAmount'])
60
+ end
61
+
62
+ # @return [String] the Starling internal ID of the merchant
63
+ def merchant_id
64
+ parsed_data['merchantId']
65
+ end
66
+
67
+ # @return [String] the Starling internal ID of the merchant location
68
+ def merchant_location_id
69
+ parsed_data['merchantLocationId']
70
+ end
71
+ end
72
+ end
73
+ end