amex 0.3.2 → 0.4.0

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