starling-ruby 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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