amex 0.4.0 → 0.4.1

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.
data/.gitignore CHANGED
@@ -1 +1,4 @@
1
1
  settings.rb
2
+ doc/
3
+ .yardoc
4
+ .gem
@@ -0,0 +1,20 @@
1
+ ## Changelog
2
+
3
+ __v0.1.0__ - Original version
4
+
5
+ __v0.2.0__ - Support for multiple American Express cards, parsing using
6
+ Nokogiri
7
+
8
+ __v0.3.0__ - Adds support for loading the transactions from the most recent statement
9
+ (but it's broken because I forgot to change something from testing :( )
10
+
11
+ __v0.3.1__ - Working version of v0.3.0 that will successfully load transactions
12
+ from the most recent statement
13
+
14
+ __v0.3.2__ - Generates a fake HardwareId in the first request, since I'm
15
+ paranoid about American Express blocking 'dummy_device_id'
16
+
17
+ __v0.4.0__ - Improves transactions - adds support for lazy-loading and
18
+ pagination from Amex::CardAccount#transactions
19
+
20
+ __v0.4.1__ - Adds YARD documentation
data/Gemfile CHANGED
@@ -2,4 +2,4 @@ source "http://rubygems.org"
2
2
 
3
3
  gem 'httparty', '0.9.0'
4
4
  gem 'nokogiri', '1.5.6'
5
- gem 'amex', '0.4.0'
5
+ gem 'amex', '0.4.1'
@@ -1,7 +1,7 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- amex (0.4.0)
4
+ amex (0.4.1)
5
5
  httparty
6
6
  nokogiri
7
7
  httparty (0.9.0)
@@ -15,6 +15,6 @@ PLATFORMS
15
15
  ruby
16
16
 
17
17
  DEPENDENCIES
18
- amex (= 0.4.0)
18
+ amex (= 0.4.1)
19
19
  httparty (= 0.9.0)
20
20
  nokogiri (= 1.5.6)
data/README.md CHANGED
@@ -9,26 +9,9 @@ the previous unknown internal API used by American Express for their
9
9
  "Amex UK" iPhone app. I suspect it works elsewhere, but I haven't tested.
10
10
 
11
11
  This allows you to fetch the details of all the cards on your American
12
- Express login, as well as the most recent statement's transactions.
12
+ Express login, as well as transactions on each card.
13
13
 
14
- ### Changelog
15
-
16
- __v0.1.0__ - Original version
17
-
18
- __v0.2.0__ - Support for multiple American Express cards, parsing using
19
- Nokogiri
20
-
21
- __v0.3.0__ - Adds support for loading the transactions from the most recent statement
22
- (but it's broken because I forgot to change something from testing :( )
23
-
24
- __v0.3.1__ - Working version of v0.3.0 that will successfully load transactions
25
- from the most recent statement
26
-
27
- __v0.3.2__ - Generates a fake HardwareId in the first request, since I'm
28
- paranoid about American Express blocking 'dummy_device_id'
29
-
30
- __v0.4.0__ - Improves transactions - adds support for lazy-loading and
31
- pagination from Amex::CardAccount#transactions
14
+ *See CHANGELOG.md for a changelog.*
32
15
 
33
16
 
34
17
  ### Usage
@@ -67,68 +50,15 @@ puts my_account.type
67
50
  puts my_account.transactions.inspect
68
51
  ```
69
52
 
70
- ### Data models
71
-
72
- An `Amex::CardAccount` is created by `Amex::CardAccount.new` passing in a hash
73
- of the parsed XML. The parsing is done by `Amex::Client`.
74
-
75
- An __Amex::CardAccount__ instance has the following attributes:
76
-
77
- * __product (string)__ - the type of card (e.g. "The Preferred Rewards Gold Card®")
78
- * __card_number_suffix (string)__ - the last five digits of your card number
79
- * __card_index (integer)__ - the internal number of the card on your account
80
- in the Amex system, starting from 0 *(used internally by the gem)*
81
- * __lending_type (string)__ - either "Charge" or "Credit", depending on the type of credit arrangement you have
82
- * __card_member_name (string)__ - your name, as recorded as the account holder
83
- * __past_due (boolean)__ - is the card past its due payment date?
84
- * __cancelled?__ (boolean)__ - has the account been cancelled?
85
- * __is_basic/centurion/platinum/premium] (boolean)__ - which type of account does this conform to?
86
- * __market (string)__ - the market that your card is registered too, e.g. "en_GB"
87
- * __card__art (string)__ - a URL for an image of your card
88
- * __loyalty_indicator (boolean)__ - does this card have some
89
- kind of loyalty scheme active? (e.g. Membership Rewards)
90
- * __loyalty_programmes (array of Amex::LoyaltyProgramme objects)__ - the loyalty programmes this card belongs to
91
- * __loyalty_balances (hash)__ - the loyalty balances on this card - the key is the name of the programme (string), and the balance is the value, as an integer
92
- * __statement_balance (float)__ - the amount of the last statement on your account
93
- * __payment_credits (float)__ - the combination of current payments and credits on your account
94
- * __recent_charges (float)__ - charges since your last statement was issued (I believe)
95
- * __total_balance (float)__ - what American Express refer to as your total balance, whatever that is!
96
- * __payment_due (float)__ - the amount of money you need to pay before `payment_due_date`
97
- * __payment_due_date (DateTime)__ - when the `payment_due` needs to be paid by
98
-
99
- The transactions for a given account can be found by calling the `transaction`
100
- method on a CardAccount. This takes a parameter, `billing_period`, which can
101
- be an integer referring to a particular statement, or a range of integers.
102
-
103
- To get transactions since the most recent statement, simply call
104
- `account.transactions(0)` or `account.transactions`, since this is the default.
105
-
106
- To get the last statement, call `account.transactions(1)`. To get from now up
107
- to 5 statements ago, call `account.transactions(0..5)`. You get the idea.
108
-
109
- There are lots of extra useful methods here to make accessing
110
- some of the various properties easier. They're very self-explanatory - check `lib/amex/card_account.rb`.
111
-
112
- A __Amex::LoyaltyProgramme has just two attributes:
113
-
114
- * __name (string)__ - The name of the programme, most often "Membership Rewards"
115
- * __balance (integer)__ - The balance of the programme
116
-
117
- An __Amex::Transaction represents a transaction in your most recent American
118
- Express statement. It has four attributes:
119
-
120
- * __amount (float)__ - The amount of the transaction
121
- * __date (Date)__ - The date that the transaction was recorded
122
- * __narrative (string)__ - The description shown on your statement, usually
123
- contaning the name of the merchant and their location
124
- * __extra_details (hash)__ - This hash contains any extra pieces of information
125
- provided by American Express...for instance, foreign transactions have their
126
- exchange rate and commission. The name of the attribute will be the key, and
127
- its formatted value in the value in the hash.
128
-
129
- There's one helper method currently available here, `is_foreign_transaction?`,
130
- which returns a boolean representing whether the transaction was foreign (i.e.
131
- in a non-native currency).
53
+ ### Documentation
54
+
55
+ You can view the full YARD documentation [here](http://rubydoc.info/github/timrogers/amex/master/frames).
56
+
57
+ ### Examples
58
+
59
+ * __[amex_alerts](https://github.com/timrogers/amex-alerts)__, a script
60
+ designed to be run as a cron which tracks and alerts you on your rewards
61
+ balances
132
62
 
133
63
  ### License
134
64
 
@@ -7,6 +7,13 @@ module Amex
7
7
  :total_balance, :payment_due, :payment_due_date, :loyalty_programmes,
8
8
  :client
9
9
 
10
+ # Generates a CardAccount object from XML properties grabbed by the client
11
+ #
12
+ # @param [Hash] options A Hash containing XML properties pulled directly
13
+ # from the API XML
14
+ # @return [Amex::CardAccount] an object representing an American Express
15
+ # card
16
+ #
10
17
  def initialize(options)
11
18
  options.each do |key, value|
12
19
  method = key.to_s.underscore + "="
@@ -15,15 +22,20 @@ module Amex
15
22
  @loyalty_programmes = []
16
23
  end
17
24
 
25
+ # Fetches transactions on an American Express card
26
+ #
27
+ # @param [Fixnum, Range] billing_period The billing period(s) to fetch
28
+ # transactions for, as either a single billing period (e.g. 0 or 1) or
29
+ # a range of periods to fetch (e.g. 0..3)
30
+ # @return [Array<Amex::Transaction>] an array of `Amex::Transaction` objects
31
+ # @note This can fetch either a single billing period or a range
32
+ # of billing periods, e.g:
33
+ # => account.transaction(0)
34
+ # fetches transactions since the last statement (default)
35
+ # => account.transaction(0..5)
36
+ # fetches transactions between now and five statements ago
37
+ #
18
38
  def transactions(billing_period=0)
19
- # Fetch the transactions for this account based upon the passed in
20
- # options - this can fetch either a single billing period or a range
21
- # of billing periods, e.g:
22
- #
23
- # => account.transaction(0) fetches transactions since the last statement
24
- # (default)
25
- # => account.transaction(0..5) fetches transactions between now and
26
- # five statements ago
27
39
  result = []
28
40
 
29
41
  # Build an array of billing periods we need to fetch - this is almost
@@ -55,23 +67,46 @@ module Amex
55
67
  result
56
68
  end
57
69
 
70
+ # Returns the balance of the most recent statement
71
+ #
72
+ # @return [Float] the balance of the most recent statement
73
+ #
58
74
  def statement_balance
59
75
  @stmt_balance
60
76
  end
61
77
 
78
+ # Returns the name of the card product that your card conforms to (e.g.
79
+ # "American Express Preferred Rewards Gold")
80
+ #
81
+ # @return [String] the name of the card product that your card conforms to
82
+ #
62
83
  def product
63
84
  @card_product
64
85
  end
65
86
 
87
+ # Returns whether the card account is cancelled
88
+ #
89
+ # @return [Boolean] the cancellation status of this card, either true or
90
+ # false
66
91
  def cancelled?
67
92
  @cancelled
68
93
  end
69
94
 
95
+ # Returns the date that the next payment on the card is due
96
+ #
97
+ # @return [DateTime] the date when the next payment against this account
98
+ # is due
70
99
  def payment_due_date
71
100
  # Overrides attr_accessor so it actually returns a DateTime, not String
72
101
  DateTime.parse(@payment_due_date)
73
102
  end
74
103
 
104
+ # Returns the type of account this card conforms to (generally not useful,
105
+ # probably largely used internally by American Express
106
+ #
107
+ # @return [:basic, :platinum, :centurion, :premium, :unknown] a symbol
108
+ # representing the 'type' of your card
109
+ #
75
110
  def type
76
111
  return :basic if @is_basic
77
112
  return :platinum if @is_platinum
@@ -80,30 +115,59 @@ module Amex
80
115
  :unknown
81
116
  end
82
117
 
118
+ # Returns whether this account is a credit card
119
+ #
120
+ # @return [Boolean] true if the account is a credit card, false otherwise
121
+ #
83
122
  def is_credit_card?
84
123
  return true if @lending_type == "Credit"
85
124
  false
86
125
  end
87
126
 
127
+ # Returns whether this account is a charge card
128
+ #
129
+ # @return [Boolean] true if the account is a charge card, false otherwise
130
+ #
88
131
  def is_charge_card?
89
132
  return true if @lending_type == "Charge"
90
133
  false
91
134
  end
92
135
 
136
+ # Returns whether payment on this account is overdue
137
+ #
138
+ # @return [Boolean] true if the account is overdue, false otherwise
139
+ #
93
140
  def overdue?
94
141
  return true if @past_due
95
142
  false
96
143
  end
97
144
 
145
+ # Returns whether this account has a due payment (i.e. whether you need
146
+ # to pay American Express anything) (see #overdue?)
147
+ #
148
+ # @return [Boolean] true if the account has a due payment, false otherwise
149
+ #
98
150
  def due?
99
151
  return true if @payment_due.to_f > 0
100
152
  false
101
153
  end
102
154
 
155
+ # Returns whether this account has any kind of loyalty scheme attached
156
+ #
157
+ # @return [Boolean] true if the account has a loyalty scheme, false
158
+ # otherwise
159
+ #
103
160
  def loyalty_enabled?
104
161
  @loyalty_indicator
105
162
  end
106
163
 
164
+
165
+ # Returns a hash of loyalty scheme balances for this account
166
+ #
167
+ # @return [Hash{String => String}] the loyalty balances for this account,
168
+ # with the key being the name of the loyalty scheme, and the value its
169
+ # balance
170
+ #
107
171
  def loyalty_balances
108
172
  result = {}
109
173
  @loyalty_programmes.each do |programme|
@@ -8,14 +8,23 @@ module Amex
8
8
  include HTTParty
9
9
  base_uri 'https://global.americanexpress.com/'
10
10
 
11
+ # Generates an Amex::Client object from a username and password
12
+ #
13
+ # @param [String] username Your American Express online services username
14
+ # @param [String] password Your American Express online services password
15
+ # @return [Amex::Client] an object representing an American Express online
16
+ # account
17
+ #
11
18
  def initialize(username, password)
12
19
  @username = username
13
20
  @password = password
14
21
  end
15
22
 
23
+ # Fetches the cards on an American Express online services account
24
+ #
25
+ # @return [Array<Amex::CardAccount>] an array of `Amex::CardAccount` objects
26
+ #
16
27
  def accounts
17
- # This only supports one account for now, because I'm lazy and I
18
- # hate traversing XML...
19
28
  options = { :body => { "PayLoadText" => request_xml }}
20
29
  response = self.class.post(
21
30
  '/myca/intl/moblclient/emea/ws.do?Face=en_GB', options
@@ -80,10 +89,17 @@ module Amex
80
89
 
81
90
  end
82
91
 
92
+ # Generates the XML to send in a request to fetch transactions for a card
93
+ #
94
+ # @param [Integer] card_index The index of the card you're looking up
95
+ # in your account (see Amex::CardAccount#card_index)
96
+ # @param [Integer] billing_period The billing period to look at, with "0"
97
+ # being transactions since your last statement, "1" being your last
98
+ # statement, "2" the statement before that and so on....
99
+ #
100
+ # @return [String] XML to be sent in the request
101
+ #
83
102
  def statement_request_xml(card_index, billing_period=0)
84
- # Generates XML for grabbing the last statement's transactions for a
85
- # card, using the card_index attribute from an account's XML
86
-
87
103
  xml = File.read(
88
104
  File.expand_path(File.dirname(__FILE__) + '/data/statement_request.xml')
89
105
  )
@@ -95,10 +111,11 @@ module Amex
95
111
 
96
112
  private
97
113
 
114
+ # Generates the XML to send in a request to fetch cards for an account
115
+ #
116
+ # @return [String] XML to be sent in the request
117
+ #
98
118
  def request_xml
99
- # Generates XML for the first request for account information, taking
100
- # an XML template and interpolating some parts with ERB
101
-
102
119
  xml = File.read(
103
120
  File.expand_path(File.dirname(__FILE__) + '/data/request.xml')
104
121
  )
@@ -110,10 +127,13 @@ module Amex
110
127
  ERB.new(xml).result(binding)
111
128
  end
112
129
 
130
+ # Generates a fake HardwareId to be sent in requests, in an attempt to
131
+ # hide what requests to the API are coming from this gem
132
+ #
133
+ # @return [String] a 40 character alphanumeric lower-case string, which
134
+ # is passed in with the original API request
135
+ #
113
136
  def hardware_id
114
- # Generates a fake HardwareId - a 40 character alphanumeric lower-case
115
- # string, which is passed in with the original API request
116
-
117
137
  chars = 'abcdefghjkmnpqrstuvwxyz1234567890'
118
138
  id = ''
119
139
  40.times { id << chars[rand(chars.size)] }
@@ -2,6 +2,14 @@ module Amex
2
2
  class LoyaltyProgramme
3
3
  attr_accessor :name, :balance
4
4
 
5
+ # Generates an Amex::LoyaltyProgramme object from a programme name and
6
+ # balance, grabbed from the XML
7
+ #
8
+ # @param [String] name The name of the reward programme
9
+ # @param [Fixnum] balance The balance of the reward programme
10
+ # @return [Amex::LoyaltyProgramme] an object representing a loyalty
11
+ # programme
12
+ #
5
13
  def initialize(name, balance)
6
14
  @name = name
7
15
  @balance = balance
@@ -4,6 +4,14 @@ module Amex
4
4
  class Transaction
5
5
  attr_reader :date, :narrative, :amount, :extra_details
6
6
 
7
+ # Generates an Amex::LoyaltyProgramme object from a Nokogiri object
8
+ # representing <Transaction> element
9
+ #
10
+ # @param [Nokogiri::XML::Element] transaction A <Transaction> node taken
11
+ # the API XML request, parsed by Nokogiri
12
+ # @return [Amex::Transaction] an object representing an individual
13
+ # transaction
14
+ #
7
15
  def initialize(transaction)
8
16
  # Pass this a <Transaction> element, and it'll parse it
9
17
  @date = Date.strptime(transaction.css('TransChargeDate').text, '%m/%d/%y')
@@ -16,6 +24,11 @@ module Amex
16
24
  end
17
25
  end
18
26
 
27
+ # Returns whether the transaction was made abroad/in a foreign currency
28
+ #
29
+ # @return [Boolean] true if the transaction was made abroad/in a foreign
30
+ # currency, false otherwise
31
+ #
19
32
  def is_foreign_transaction?
20
33
  return true if @extra_details.has_key?('currencyRate')
21
34
  false
@@ -1,4 +1,11 @@
1
1
  class String
2
+
3
+ # Converts a String object into a simple as used on an Amex::CardAccount
4
+ # object - the XML uses camelCase attributes, we want underscored ones
5
+ # which we can convert to symbol (e.g. cardProduct to card_product)
6
+ #
7
+ # @return [String] the reformatted string
8
+ #
2
9
  def underscore
3
10
  self.gsub(/::/, '/').
4
11
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
@@ -6,11 +13,4 @@ class String
6
13
  tr("-", "_").
7
14
  downcase
8
15
  end
9
-
10
- def to_bool
11
- return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
12
- return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
13
- raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
14
- end
15
-
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module Amex
2
- VERSION = '0.4.0'
2
+ VERSION = '0.4.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-27 00:00:00.000000000 Z
12
+ date: 2012-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
@@ -51,14 +51,10 @@ extensions: []
51
51
  extra_rdoc_files: []
52
52
  files:
53
53
  - .gitignore
54
+ - CHANGELOG.md
54
55
  - Gemfile
55
56
  - Gemfile.lock
56
57
  - README.md
57
- - amex-0.1.0.gem
58
- - amex-0.2.0.gem
59
- - amex-0.3.0.gem
60
- - amex-0.3.1.gem
61
- - amex-0.3.2.gem
62
58
  - amex.gemspec
63
59
  - example.rb
64
60
  - lib/amex.rb
Binary file
Binary file
Binary file
Binary file
Binary file