amex 0.2.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/Gemfile.lock +4 -0
- data/README.md +33 -4
- data/amex-0.2.0.gem +0 -0
- data/amex-0.3.0.gem +0 -0
- data/lib/amex.rb +1 -0
- data/lib/amex/card_account.rb +4 -2
- data/lib/amex/client.rb +28 -0
- data/lib/amex/data/statement_request.xml +13 -0
- data/lib/amex/transaction.rb +25 -0
- data/lib/amex/version.rb +1 -1
- metadata +4 -1
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
amex (0.3.0)
|
5
|
+
httparty
|
6
|
+
nokogiri
|
4
7
|
httparty (0.9.0)
|
5
8
|
multi_json (~> 1.0)
|
6
9
|
multi_xml
|
@@ -12,5 +15,6 @@ PLATFORMS
|
|
12
15
|
ruby
|
13
16
|
|
14
17
|
DEPENDENCIES
|
18
|
+
amex (= 0.3.0)
|
15
19
|
httparty (= 0.9.0)
|
16
20
|
nokogiri (= 1.5.6)
|
data/README.md
CHANGED
@@ -8,11 +8,18 @@ However, this one doesn't rely on nasty screen-scraping. Instead, it uses
|
|
8
8
|
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
|
+
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.
|
13
|
+
|
11
14
|
### Changelog
|
12
15
|
|
13
16
|
__v0.1.0__ - Original version
|
14
17
|
__v0.2.0__ - Support for multiple American Express cards, parsing using
|
15
18
|
Nokogiri
|
19
|
+
__v0.3.0__ - Adds support for loading the transactions from the most recent statement
|
20
|
+
(but it's broken because I forgot to change something from testing :( )
|
21
|
+
__v0.3.1__ - Working version of v0.3.0 that will successfully load transactions
|
22
|
+
from the most recent statement
|
16
23
|
|
17
24
|
### Usage
|
18
25
|
|
@@ -42,8 +49,10 @@ only supports one card at a time right now.
|
|
42
49
|
|
43
50
|
```
|
44
51
|
accounts = client.accounts
|
45
|
-
|
46
|
-
puts
|
52
|
+
my_account = accounts.first
|
53
|
+
puts my_account.product
|
54
|
+
puts my_account.type
|
55
|
+
puts my_account.transactions.inspect
|
47
56
|
```
|
48
57
|
|
49
58
|
### Data models
|
@@ -55,6 +64,8 @@ An __Amex::CardAccount__ instance has the following attributes:
|
|
55
64
|
|
56
65
|
* __product (string)__ - the type of card (e.g. "The Preferred Rewards Gold Card®")
|
57
66
|
* __card_number_suffix (string)__ - the last five digits of your card number
|
67
|
+
* __card_index (integer)__ - the internal number of the card on your account
|
68
|
+
in the Amex system, starting from 0 *(used internally by the gem)*
|
58
69
|
* __lending_type (string)__ - either "Charge" or "Credit", depending on the type of credit arrangement you have
|
59
70
|
* __card_member_name (string)__ - your name, as recorded as the account holder
|
60
71
|
* __past_due (boolean)__ - is the card past its due payment date?
|
@@ -72,18 +83,36 @@ kind of loyalty scheme active? (e.g. Membership Rewards)
|
|
72
83
|
* __total_balance (float)__ - what American Express refer to as your total balance, whatever that is!
|
73
84
|
* __payment_due (float)__ - the amount of money you need to pay before `payment_due_date`
|
74
85
|
* __payment_due_date (DateTime)__ - when the `payment_due` needs to be paid by
|
86
|
+
* __transactions (array)__ - an array of Amex::Transaction objects)
|
75
87
|
|
76
88
|
There are lots of extra useful methods here to make accessing
|
77
89
|
some of the various properties easier. They're very self-explanatory - check `lib/amex/card_account.rb`.
|
78
90
|
|
79
|
-
A
|
91
|
+
A __Amex::LoyaltyProgramme has just two attributes:
|
80
92
|
|
81
93
|
* __name (string)__ - The name of the programme, most often "Membership Rewards"
|
82
94
|
* __balance (integer)__ - The balance of the programme
|
83
95
|
|
96
|
+
An __Amex::Transaction represents a transaction in your most recent American
|
97
|
+
Express statement. It has four attributes:
|
98
|
+
|
99
|
+
* __amount (float)__ - The amount of the transaction
|
100
|
+
* __date (Date)__ - The date that the transaction was recorded
|
101
|
+
* __narrative (string)__ - The description shown on your statement, usually
|
102
|
+
contaning the name of the merchant and their location
|
103
|
+
* __extra_details (hash)__ - This hash contains any extra pieces of information
|
104
|
+
provided by American Express...for instance, foreign transactions have their
|
105
|
+
exchange rate and commission. The name of the attribute will be the key, and
|
106
|
+
its formatted value in the value in the hash.
|
107
|
+
|
108
|
+
There's one helper method currently available here, `is_foreign_transaction?`,
|
109
|
+
which returns a boolean representing whether the transaction was foreign (i.e.
|
110
|
+
in a non-native currency).
|
111
|
+
|
84
112
|
### Limitations
|
85
113
|
|
86
|
-
*
|
114
|
+
* You can only view transactions from the most recent statement. I intend
|
115
|
+
to change this in due course to support pagination of some description.
|
87
116
|
|
88
117
|
### License
|
89
118
|
|
data/amex-0.2.0.gem
ADDED
Binary file
|
data/amex-0.3.0.gem
ADDED
Binary file
|
data/lib/amex.rb
CHANGED
data/lib/amex/card_account.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Amex
|
2
2
|
class CardAccount
|
3
|
-
attr_accessor :card_product, :card_number_suffix,
|
3
|
+
attr_accessor :card_product, :card_number_suffix, :card_index,
|
4
4
|
:lending_type, :card_member_name, :past_due, :cancelled, :is_basic,
|
5
5
|
:is_centurion, :is_platinum, :is_premium, :market, :card_art,
|
6
6
|
:loyalty_indicator, :stmt_balance, :payment_credits, :recent_charges,
|
7
|
-
:total_balance, :payment_due, :payment_due_date, :loyalty_programmes
|
7
|
+
:total_balance, :payment_due, :payment_due_date, :loyalty_programmes,
|
8
|
+
:transactions
|
8
9
|
|
9
10
|
def initialize(options)
|
10
11
|
options.each do |key, value|
|
@@ -12,6 +13,7 @@ module Amex
|
|
12
13
|
send(key.underscore + "=", value) if respond_to? method.to_sym
|
13
14
|
end
|
14
15
|
@loyalty_programmes = []
|
16
|
+
@transactions = []
|
15
17
|
end
|
16
18
|
|
17
19
|
def statement_balance
|
data/lib/amex/client.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'erb'
|
2
2
|
require 'httparty'
|
3
3
|
require 'nokogiri'
|
4
|
+
require 'date'
|
4
5
|
|
5
6
|
module Amex
|
6
7
|
class Client
|
@@ -24,6 +25,15 @@ module Amex
|
|
24
25
|
ERB.new(xml).result(binding)
|
25
26
|
end
|
26
27
|
|
28
|
+
def statement_request_xml(card_index)
|
29
|
+
xml = File.read(
|
30
|
+
File.expand_path(File.dirname(__FILE__) + '/data/statement_request.xml')
|
31
|
+
)
|
32
|
+
|
33
|
+
security_token = @security_token
|
34
|
+
ERB.new(xml).result(binding)
|
35
|
+
end
|
36
|
+
|
27
37
|
def accounts
|
28
38
|
# This only supports one account for now, because I'm lazy and I
|
29
39
|
# hate traversing XML...
|
@@ -38,6 +48,9 @@ module Amex
|
|
38
48
|
if xml.css('ServiceResponse Status').text != "success"
|
39
49
|
raise "There was a problem logging in to American Express."
|
40
50
|
else
|
51
|
+
# Store the security token - we need this for further requests
|
52
|
+
@security_token = xml.css('ClientSecurityToken').text
|
53
|
+
|
41
54
|
accounts = [] # We'll store all the accounts in here!
|
42
55
|
|
43
56
|
xml.css('CardAccounts CardAccount').each do |item|
|
@@ -64,6 +77,21 @@ module Amex
|
|
64
77
|
element.attr('label'), element.attr('formattedValue').gsub(",", "").to_i
|
65
78
|
)
|
66
79
|
end
|
80
|
+
|
81
|
+
# Now we can fetch the transactions...
|
82
|
+
options = { :body => {
|
83
|
+
"PayLoadText" => statement_request_xml(account.card_index)
|
84
|
+
}}
|
85
|
+
response = self.class.post(
|
86
|
+
'/myca/intl/moblclient/emea/ws.do?Face=en_GB', options
|
87
|
+
)
|
88
|
+
xml = Nokogiri::XML(response.body)
|
89
|
+
xml = xml.css("XMLResponse")
|
90
|
+
|
91
|
+
xml.css('Transaction').each do |transaction|
|
92
|
+
account.transactions << Amex::Transaction.new(transaction)
|
93
|
+
end
|
94
|
+
|
67
95
|
accounts << account
|
68
96
|
|
69
97
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<XMLRequest>
|
3
|
+
<ClientType>iPhone</ClientType>
|
4
|
+
<ClientVersion>1.8</ClientVersion>
|
5
|
+
<ServiceVersion>1.0</ServiceVersion>
|
6
|
+
<Locale>en_GB</Locale>
|
7
|
+
<ServiceName>StatementService</ServiceName>
|
8
|
+
<ClientSecurityToken><%= security_token %></ClientSecurityToken>
|
9
|
+
<StatementRequestData>
|
10
|
+
<BillingPeriod>0</BillingPeriod>
|
11
|
+
<CardIndex><%= card_index %></CardIndex>
|
12
|
+
</StatementRequestData>
|
13
|
+
</XMLRequest>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Amex
|
4
|
+
class Transaction
|
5
|
+
attr_reader :date, :narrative, :amount, :extra_details
|
6
|
+
|
7
|
+
def initialize(transaction)
|
8
|
+
# Pass this a <Transaction> element, and it'll parse it
|
9
|
+
@date = Date.strptime(transaction.css('TransChargeDate').text, '%m/%d/%y')
|
10
|
+
@narrative = transaction.css('TransDesc').text
|
11
|
+
@amount = transaction.css('TransAmount').text.to_f
|
12
|
+
|
13
|
+
@extra_details = {}
|
14
|
+
transaction.css('TransExtDetail ExtDetailElement').each do |element|
|
15
|
+
@extra_details[element.attr('name')] = element.attr('formattedValue')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_foreign_transaction?
|
20
|
+
return true if @extra_details.has_key?('currencyRate')
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/amex/version.rb
CHANGED
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
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -56,13 +56,16 @@ files:
|
|
56
56
|
- README.md
|
57
57
|
- amex-0.1.0.gem
|
58
58
|
- amex-0.2.0.gem
|
59
|
+
- amex-0.3.0.gem
|
59
60
|
- amex.gemspec
|
60
61
|
- example.rb
|
61
62
|
- lib/amex.rb
|
62
63
|
- lib/amex/card_account.rb
|
63
64
|
- lib/amex/client.rb
|
64
65
|
- lib/amex/data/request.xml
|
66
|
+
- lib/amex/data/statement_request.xml
|
65
67
|
- lib/amex/loyalty_programme.rb
|
68
|
+
- lib/amex/transaction.rb
|
66
69
|
- lib/amex/utils.rb
|
67
70
|
- lib/amex/version.rb
|
68
71
|
homepage: https://github.com/timrogers/amex
|