amex 0.4.0 → 0.4.1

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