amex 0.3.2 → 0.4.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.
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.3.2'
5
+ gem 'amex', '0.4.0'
@@ -1,7 +1,7 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- amex (0.3.2)
4
+ amex (0.4.0)
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.3.2)
18
+ amex (= 0.4.0)
19
19
  httparty (= 0.9.0)
20
20
  nokogiri (= 1.5.6)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ## Amex
1
+ ## Amex *[(view on RubyGems.org)](http://rubygems.org/gems/amex)*
2
2
 
3
3
  Welcome to the last continuation of my Ruby-based assault on various online
4
4
  banking systems, much like my
@@ -14,15 +14,23 @@ Express login, as well as the most recent statement's transactions.
14
14
  ### Changelog
15
15
 
16
16
  __v0.1.0__ - Original version
17
+
17
18
  __v0.2.0__ - Support for multiple American Express cards, parsing using
18
19
  Nokogiri
20
+
19
21
  __v0.3.0__ - Adds support for loading the transactions from the most recent statement
20
22
  (but it's broken because I forgot to change something from testing :( )
23
+
21
24
  __v0.3.1__ - Working version of v0.3.0 that will successfully load transactions
22
25
  from the most recent statement
26
+
23
27
  __v0.3.2__ - Generates a fake HardwareId in the first request, since I'm
24
28
  paranoid about American Express blocking 'dummy_device_id'
25
29
 
30
+ __v0.4.0__ - Improves transactions - adds support for lazy-loading and
31
+ pagination from Amex::CardAccount#transactions
32
+
33
+
26
34
  ### Usage
27
35
 
28
36
  The file `example.rb` provides a very simple example of how the code works, but here's a step by step:
@@ -31,7 +39,9 @@ The file `example.rb` provides a very simple example of how the code works, but
31
39
 
32
40
  ```
33
41
  $ gem install amex
34
- `require 'amex'
42
+ ...
43
+ require 'rubygems'
44
+ require 'amex'
35
45
  ```
36
46
 
37
47
  2. You'll just need two variables, @username and @password, each unsurprisingly corresponding to different authentication details used
@@ -85,7 +95,16 @@ kind of loyalty scheme active? (e.g. Membership Rewards)
85
95
  * __total_balance (float)__ - what American Express refer to as your total balance, whatever that is!
86
96
  * __payment_due (float)__ - the amount of money you need to pay before `payment_due_date`
87
97
  * __payment_due_date (DateTime)__ - when the `payment_due` needs to be paid by
88
- * __transactions (array)__ - an array of Amex::Transaction objects)
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.
89
108
 
90
109
  There are lots of extra useful methods here to make accessing
91
110
  some of the various properties easier. They're very self-explanatory - check `lib/amex/card_account.rb`.
@@ -111,11 +130,6 @@ There's one helper method currently available here, `is_foreign_transaction?`,
111
130
  which returns a boolean representing whether the transaction was foreign (i.e.
112
131
  in a non-native currency).
113
132
 
114
- ### Limitations
115
-
116
- * You can only view transactions from the most recent statement. I intend
117
- to change this in due course to support pagination of some description.
118
-
119
133
  ### License
120
134
 
121
135
  Use this for what you will, as long as it isn't evil. If you make any changes or cool improvements, please let me know at <tim+amex@tim-rogers.co.uk>.
Binary file
data/example.rb CHANGED
@@ -5,6 +5,30 @@ require 'amex'
5
5
  # but it should just contain two class variables, `username` and `password`
6
6
  require "#{File.dirname(__FILE__)}/settings.rb"
7
7
 
8
+ # Instantiate an Amex::Client object
8
9
  client = Amex::Client.new(@username, @password)
10
+
11
+ # Execute the #accounts method on the client, which will return an array
12
+ # of Amex::CardAccount objects
9
13
  accounts = client.accounts
10
- puts accounts.first.inspect
14
+
15
+ # Let's take a look at your first account...
16
+ account = accounts.first
17
+ puts account.inspect
18
+
19
+ # We can find out the transactions since the last statement
20
+ recent_transactions = account.transactions
21
+ puts "There have been #{recent_transactions.length} transactions since your " +
22
+ "last statement."
23
+
24
+ # and then look at individual statements to see their transactions...
25
+ last_statement = account.transactions(1)
26
+ puts "There were #{last_statement.length} transactions on your last statement."
27
+
28
+ # Let's view transactions from now to the end of your last statement, and
29
+ # then find out how many were made abroad...
30
+ foreign_transactions = account.transactions(0..1).keep_if do |tx|
31
+ tx.is_foreign_transaction?
32
+ end
33
+ puts "#{foreign_transactions.length} transactions since the start of your " +
34
+ "last statement period were made abroad."
@@ -5,15 +5,54 @@ module Amex
5
5
  :is_centurion, :is_platinum, :is_premium, :market, :card_art,
6
6
  :loyalty_indicator, :stmt_balance, :payment_credits, :recent_charges,
7
7
  :total_balance, :payment_due, :payment_due_date, :loyalty_programmes,
8
- :transactions
8
+ :client
9
9
 
10
10
  def initialize(options)
11
11
  options.each do |key, value|
12
- method = key.underscore + "="
13
- send(key.underscore + "=", value) if respond_to? method.to_sym
12
+ method = key.to_s.underscore + "="
13
+ send(key.to_s.underscore + "=", value) if respond_to? method.to_sym
14
14
  end
15
15
  @loyalty_programmes = []
16
- @transactions = []
16
+ end
17
+
18
+ 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
+ result = []
28
+
29
+ # Build an array of billing periods we need to fetch - this is almost
30
+ # certainly woefully inefficient code.
31
+ billing_periods = []
32
+ if billing_period.class == Fixnum
33
+ billing_periods << billing_period
34
+ elsif billing_period.class == Range
35
+ billing_period.each { |n| billing_periods << n }
36
+ else
37
+ raise "The passed in billing period option must be a number or a range"
38
+ end
39
+
40
+ billing_periods.each do |n|
41
+ options = { :body => {
42
+ "PayLoadText" => @client.statement_request_xml(@card_index, n)
43
+ }}
44
+ response = @client.class.post(
45
+ '/myca/intl/moblclient/emea/ws.do?Face=en_GB', options
46
+ )
47
+ xml = Nokogiri::XML(response.body)
48
+ xml = xml.css("XMLResponse")
49
+
50
+ xml.css('Transaction').each do |transaction|
51
+ result << Amex::Transaction.new(transaction)
52
+ end
53
+ end
54
+
55
+ result
17
56
  end
18
57
 
19
58
  def statement_balance
@@ -33,7 +33,7 @@ module Amex
33
33
  accounts = [] # We'll store all the accounts in here!
34
34
 
35
35
  xml.css('CardAccounts CardAccount').each do |item|
36
- account_details = {} # All the attributes from the XML go in here
36
+ account_details = {client: self} # All the attributes from the XML go in here
37
37
  # For each of the CardAccount objects, let's first go through
38
38
  # the CardData to pull out lots of nice information
39
39
  item.css('CardData param').each do |attribute|
@@ -80,6 +80,19 @@ module Amex
80
80
 
81
81
  end
82
82
 
83
+ 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
+ xml = File.read(
88
+ File.expand_path(File.dirname(__FILE__) + '/data/statement_request.xml')
89
+ )
90
+
91
+ security_token = @security_token
92
+ ERB.new(xml).result(binding)
93
+ end
94
+
95
+
83
96
  private
84
97
 
85
98
  def request_xml
@@ -97,18 +110,6 @@ module Amex
97
110
  ERB.new(xml).result(binding)
98
111
  end
99
112
 
100
- def statement_request_xml(card_index)
101
- # Generates XML for grabbing the last statement's transactions for a
102
- # card, using the card_index attribute from an account's XML
103
-
104
- xml = File.read(
105
- File.expand_path(File.dirname(__FILE__) + '/data/statement_request.xml')
106
- )
107
-
108
- security_token = @security_token
109
- ERB.new(xml).result(binding)
110
- end
111
-
112
113
  def hardware_id
113
114
  # Generates a fake HardwareId - a 40 character alphanumeric lower-case
114
115
  # string, which is passed in with the original API request
@@ -7,7 +7,7 @@
7
7
  <ServiceName>StatementService</ServiceName>
8
8
  <ClientSecurityToken><%= security_token %></ClientSecurityToken>
9
9
  <StatementRequestData>
10
- <BillingPeriod>0</BillingPeriod>
10
+ <BillingPeriod><%= billing_period %></BillingPeriod>
11
11
  <CardIndex><%= card_index %></CardIndex>
12
12
  </StatementRequestData>
13
13
  </XMLRequest>
@@ -1,3 +1,3 @@
1
1
  module Amex
2
- VERSION = '0.3.2'
2
+ VERSION = '0.4.0'
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.3.2
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -58,6 +58,7 @@ files:
58
58
  - amex-0.2.0.gem
59
59
  - amex-0.3.0.gem
60
60
  - amex-0.3.1.gem
61
+ - amex-0.3.2.gem
61
62
  - amex.gemspec
62
63
  - example.rb
63
64
  - lib/amex.rb