amex 0.1.0 → 0.2.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.
@@ -0,0 +1 @@
1
+ settings.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'httparty', '0.9.0'
4
+ gem 'nokogiri', '1.5.6'
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ httparty (0.9.0)
5
+ multi_json (~> 1.0)
6
+ multi_xml
7
+ multi_json (1.5.0)
8
+ multi_xml (0.5.1)
9
+ nokogiri (1.5.6)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ httparty (= 0.9.0)
16
+ nokogiri (= 1.5.6)
@@ -0,0 +1,91 @@
1
+ ## Amex
2
+
3
+ Welcome to the last continuation of my Ruby-based assault on various online
4
+ banking systems, much like my
5
+ [Lloyds TSB screen scraper](https://github.com/timrogers/lloydstsb).
6
+
7
+ However, this one doesn't rely on nasty screen-scraping. Instead, it uses
8
+ the previous unknown internal API used by American Express for their
9
+ "Amex UK" iPhone app. I suspect it works elsewhere, but I haven't tested.
10
+
11
+ ### Changelog
12
+
13
+ __v0.1.0__ - Original version
14
+ __v0.2.0__ - Support for multiple American Express cards, parsing using
15
+ Nokogiri
16
+
17
+ ### Usage
18
+
19
+ The file `example.rb` provides a very simple example of how the code works, but here's a step by step:
20
+
21
+ 1. Ensure the gem is installed, and then include it in your Ruby file, or in your Gemfile where appropriate:
22
+
23
+ ```
24
+ $ gem install amex
25
+ `require 'amex'
26
+ ```
27
+
28
+ 2. You'll just need two variables, @username and @password, each unsurprisingly corresponding to different authentication details used
29
+
30
+ ```
31
+ @username = "chuck_norris"
32
+ @password = "roundhousekick123"
33
+ ```
34
+
35
+ 3. Instantiate a new instance of the `Amex::Client` object, passing in the
36
+ username and password - this is used to perform the authentication required.
37
+
38
+ `client = Amex::Client.new(@username, @password)`
39
+
40
+ 4. Call the `account` method of the object you just made - it'll take a few seconds, and will return an Amex::CardAccount object. There'll only be one, since this
41
+ only supports one card at a time right now.
42
+
43
+ ```
44
+ accounts = client.accounts
45
+ puts account.first.product
46
+ puts account.first.type
47
+ ```
48
+
49
+ ### Data models
50
+
51
+ An `Amex::CardAccount` is created by `Amex::CardAccount.new` passing in a hash
52
+ of the parsed XML. The parsing is done by `Amex::Client`.
53
+
54
+ An __Amex::CardAccount__ instance has the following attributes:
55
+
56
+ * __product (string)__ - the type of card (e.g. "The Preferred Rewards Gold Card®")
57
+ * __card_number_suffix (string)__ - the last five digits of your card number
58
+ * __lending_type (string)__ - either "Charge" or "Credit", depending on the type of credit arrangement you have
59
+ * __card_member_name (string)__ - your name, as recorded as the account holder
60
+ * __past_due (boolean)__ - is the card past its due payment date?
61
+ * __cancelled?__ (boolean)__ - has the account been cancelled?
62
+ * __is_basic/centurion/platinum/premium] (boolean)__ - which type of account does this conform to?
63
+ * __market (string)__ - the market that your card is registered too, e.g. "en_GB"
64
+ * __card__art (string)__ - a URL for an image of your card
65
+ * __loyalty_indicator (boolean)__ - does this card have some
66
+ kind of loyalty scheme active? (e.g. Membership Rewards)
67
+ * __loyalty_programmes (array of Amex::LoyaltyProgramme objects)__ - the loyalty programmes this card belongs to
68
+ * __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
69
+ * __statement_balance (float)__ - the amount of the last statement on your account
70
+ * __payment_credits (float)__ - the combination of current payments and credits on your account
71
+ * __recent_charges (float)__ - charges since your last statement was issued (I believe)
72
+ * __total_balance (float)__ - what American Express refer to as your total balance, whatever that is!
73
+ * __payment_due (float)__ - the amount of money you need to pay before `payment_due_date`
74
+ * __payment_due_date (DateTime)__ - when the `payment_due` needs to be paid by
75
+
76
+ There are lots of extra useful methods here to make accessing
77
+ some of the various properties easier. They're very self-explanatory - check `lib/amex/card_account.rb`.
78
+
79
+ A __LloydsTSB::LoyaltyProgramme has just two attributes:
80
+
81
+ * __name (string)__ - The name of the programme, most often "Membership Rewards"
82
+ * __balance (integer)__ - The balance of the programme
83
+
84
+ ### Limitations
85
+
86
+ * There's no support for viewing transactions yet - watch this space!
87
+
88
+ ### License
89
+
90
+ 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>.
91
+
Binary file
@@ -0,0 +1,15 @@
1
+ require File.expand_path('../lib/amex/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'amex'
5
+ gem.version = Amex::VERSION.dup
6
+ gem.authors = ['Tim Rogers']
7
+ gem.email = ['tim@tim-rogers.co.uk']
8
+ gem.summary = 'A library for accessing data on an American Express account'
9
+ gem.homepage = 'https://github.com/timrogers/amex'
10
+
11
+ gem.add_runtime_dependency "httparty"
12
+ gem.add_runtime_dependency "nokogiri"
13
+
14
+ gem.files = `git ls-files`.split("\n")
15
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'amex'
3
+
4
+ # Bring in the settings.rb file - this isn't included in the repository,
5
+ # but it should just contain two class variables, `username` and `password`
6
+ require "#{File.dirname(__FILE__)}/settings.rb"
7
+
8
+ client = Amex::Client.new(@username, @password)
9
+ accounts = client.accounts
10
+ puts accounts.first.inspect
@@ -1,5 +1,6 @@
1
1
  require 'erb'
2
2
  require 'httparty'
3
+ require 'nokogiri'
3
4
 
4
5
  module Amex
5
6
  class Client
@@ -23,7 +24,7 @@ module Amex
23
24
  ERB.new(xml).result(binding)
24
25
  end
25
26
 
26
- def account
27
+ def accounts
27
28
  # This only supports one account for now, because I'm lazy and I
28
29
  # hate traversing XML...
29
30
  options = { :body => { "PayLoadText" => request_xml }}
@@ -31,30 +32,43 @@ module Amex
31
32
  '/myca/intl/moblclient/emea/ws.do?Face=en_GB', options
32
33
  )
33
34
 
34
- xml = MultiXml.parse(response)['XMLResponse']
35
+ xml = Nokogiri::XML(response.body)
36
+ xml = xml.css("XMLResponse")
35
37
 
36
- if xml['ServiceResponse']['Status'] != "success"
38
+ if xml.css('ServiceResponse Status').text != "success"
37
39
  raise "There was a problem logging in to American Express."
38
40
  else
39
- account_details = {}
40
- xml["CardAccounts"]["CardAccount"]["CardData"]["param"].each do |item|
41
- account_details[item['name']] = item['__content__']
42
- end
41
+ accounts = [] # We'll store all the accounts in here!
43
42
 
44
- xml["CardAccounts"]["CardAccount"]["AccountSummaryData"]["SummaryElement"].each do |item|
45
- account_details[item['name']] = item['value'] ? item['value'].to_f : item['formattedValue']
46
- end
43
+ xml.css('CardAccounts CardAccount').each do |item|
44
+ account_details = {} # All the attributes from the XML go in here
45
+ # For each of the CardAccount objects, let's first go through
46
+ # the CardData to pull out lots of nice information
47
+ item.css('CardData param').each do |attribute|
48
+ account_details[attribute.attr('name')] = attribute.text
49
+ end
47
50
 
48
- account = Amex::CardAccount.new(account_details)
51
+ # Now let's go through the AccountSummaryData to find all the
52
+ # various bits of balance information
53
+ item.css('AccountSummaryData SummaryElement').each do |attribute|
54
+ account_details[attribute.attr('name')] = attribute.attr('value') ? attribute.attr('value').to_f : attribute.attr('formattedValue')
55
+ end
56
+
57
+ # We have all the attributes ready to go, so let's make an
58
+ # Amex::CardAccount object
59
+ account = Amex::CardAccount.new(account_details)
49
60
 
50
- xml["CardAccounts"]["CardAccount"]["LoyaltyProgramData"].each do |item|
51
- item.each do |part|
52
- next if part.class == String
53
- account.loyalty_programmes << Amex::LoyaltyProgramme.new(part['label'], part['formattedValue'].gsub(",", "").to_i)
61
+ # Finally, let's rip out all the loyalty balances...
62
+ item.css('LoyaltyProgramData LoyaltyElement').each do |element|
63
+ account.loyalty_programmes << Amex::LoyaltyProgramme.new(
64
+ element.attr('label'), element.attr('formattedValue').gsub(",", "").to_i
65
+ )
54
66
  end
67
+ accounts << account
68
+
55
69
  end
56
70
 
57
- account
71
+ accounts
58
72
  end
59
73
 
60
74
  end
@@ -1,3 +1,3 @@
1
1
  module Amex
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.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.1.0
4
+ version: 0.2.0
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-26 00:00:00.000000000 Z
12
+ date: 2012-12-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  description:
31
47
  email:
32
48
  - tim@tim-rogers.co.uk
@@ -34,13 +50,21 @@ executables: []
34
50
  extensions: []
35
51
  extra_rdoc_files: []
36
52
  files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - README.md
57
+ - amex-0.1.0.gem
58
+ - amex-0.2.0.gem
59
+ - amex.gemspec
60
+ - example.rb
37
61
  - lib/amex.rb
38
62
  - lib/amex/card_account.rb
39
63
  - lib/amex/client.rb
64
+ - lib/amex/data/request.xml
40
65
  - lib/amex/loyalty_programme.rb
41
66
  - lib/amex/utils.rb
42
67
  - lib/amex/version.rb
43
- - lib/amex/data/request.xml
44
68
  homepage: https://github.com/timrogers/amex
45
69
  licenses: []
46
70
  post_install_message: