File Coverage

blib/lib/Finance/Bank/Natwest.pm
Criterion Covered Total %
statement 61 61 100.0
branch 4 6 66.6
condition 2 3 66.6
subroutine 12 12 100.0
pod 2 3 66.6
total 81 85 95.2


line stmt bran cond sub pod time code
1             package Finance::Bank::Natwest;
2 3     3   1924 use strict;
  3         5  
  3         122  
3 3     3   15 use vars qw( $VERSION );
  3         5  
  3         133  
4              
5 3     3   92 use Carp;
  3         5  
  3         222  
6 3     3   15579 use HTML::TokeParser;
  3         758237  
  3         183  
7 3     3   1538 use Finance::Bank::Natwest::Connection;
  3         6  
  3         141  
8              
9             $VERSION = '0.05';
10              
11             =head1 NAME
12              
13             Finance::Bank::Natwest - Check your Natwest bank accounts from Perl
14              
15             =head1 DESCRIPTION
16              
17             This module provides a rudimentary interface to the Natwest online
18             banking system at C. You will need
19             either C or C installed for HTTPS
20             support to work with LWP.
21              
22             =head1 SYNOPSIS
23              
24             my $nw = Finance::Bank::Natwest->new( credentials => 'Constant',
25             credentials_options => {
26             dob => '010179',
27             uid => '0001',
28             password => 'Password',
29             pin => '4321' } );
30              
31             my @accounts = $nw->accounts;
32              
33             foreach (@accounts) {
34             printf "%25s : %6s / %8s : GBP %8.2f\n",
35             $_->{name}, $_->{sortcode}, $_->{account}, $_->{available};
36             }
37              
38             =head1 METHODS
39              
40             =over 4
41              
42             =item B
43              
44             my $nw = Finance::Bank::Natwest->new( credentials => 'Constant',
45             credentials_options => {
46             dob => '010179',
47             uid => '0001',
48             password => 'Password',
49             pin => '4321' }
50             );
51              
52             # Or create the credentials object ourselves
53             my $credentials = Finance::Bank::Natwest::CredentialsProvider::Constant->new(
54             dob => '010179', uid => '0001', password => 'Password', pin => '4321' );
55              
56             my $nw = Finance::Bank::Natwest->new( credentials => $credentials );
57              
58              
59             C can be called in two different ways. It can take a single parameter,
60             C, which will accept an already created credentials object, of type
61             C. Alternatively, it can take two
62             parameters, C and C. In this case
63             C is the name of a credentials class to create an instance of, and
64             C is a hash of the options to pass-through to the
65             constructor of the chosen class.
66              
67             If the second form of C is being used, and the chosen class is I one
68             of the ones supplied as standard then it will need to be C first.
69              
70             If any errors occur then C will C.
71              
72             =cut
73              
74 3     3   14 use constant URL_ROOT => 'https://www.nwolb.com';
  3         6  
  3         143  
75 3     3   15 use constant DIR_BASE => '/secure/';
  3         4  
  3         1762  
76              
77 31     31 0 240 sub url_base { $_[0]->URL_ROOT . $_[0]->DIR_BASE };
78              
79             sub new {
80 22     22 1 21648 my ($class, %opts) = @_;
81              
82 22         50 my $self = bless {}, $class;
83              
84             {
85 22         23 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
  22         29  
86 22         71 $self->{connection} = Finance::Bank::Natwest::Connection->new(
87             %opts, url_base => $self->url_base
88             );
89             }
90              
91 2         13 $self->_load_accounts();
92            
93 2         11 return $self;
94             };
95              
96             =item B
97              
98             my @accounts = $nw->accounts;
99              
100             # Or get a list ref instead
101             my $accounts = $nw->accounts;
102              
103             Returns a list containing a summary of any accounts available from the
104             supplied credentials. Each item in the list is a hash reference that holds
105             summary information for a single account, and contains this data:
106              
107             =over 4
108              
109             =item B - the name of the account
110              
111             =item B - the account number
112              
113             =item B
114              
115             =item B
116              
117             =item B - the currently available funds
118              
119             =back
120              
121             =cut
122              
123             sub accounts {
124 4     4 1 4206 my $self = shift;
125            
126 4 50       13 return unless defined wantarray;
127              
128 4 100       13 return wantarray ? @{$self->{data}{accounts}} : $self->{data}{accounts};
  2         9  
129             }
130              
131             sub _load_accounts {
132 2     2   3 my $self = shift;
133              
134 2         11 my ($accountlist, $ministmt) =
135             ($self->{connection}->post("Balances.asp?0") =~
136             /(.*?)<\/form>(.*?)
/s);
137              
138 2         111 $self->{data}{accounts} = $self->_process_accountlist($accountlist);
139              
140             }
141              
142             sub _process_accountlist{
143 2     2   4 my ($self, $accountlist) = @_;
144 2         2 my (@accounts, $stream, $token);
145              
146 2 50       18 $stream = HTML::TokeParser->new(\$accountlist) or croak "$!, stopped";
147              
148 2         441 $stream->get_tag("tr");
149 2   66     413 while ($token = $stream->get_tag("tr") and exists $token->[1]{class}) {
150 4         237 $token = $stream->get_tag("td");
151              
152 4         90 my $name = $stream->get_trimmed_text("/td");
153 4         183 $stream->get_tag("td"); $stream->get_tag("span");
  4         140  
154              
155 4         56 $name =~ s/\xa0+/ /;
156 4         11 $name =~ s/^\s+//;
157 4         5 $name =~ s/\s+$//;
158              
159 4         11 my $sortcode = $stream->get_trimmed_text("/span");
160 4         158 $stream->get_tag("span");
161              
162 4         112 my $account = $stream->get_trimmed_text("/span");
163 4         149 $stream->get_tag("td");
164              
165 4         165 my $balance = $stream->get_trimmed_text("/td");
166 4         139 $stream->get_tag("td");
167              
168 4         105 $balance =~ s/\xa3//;
169 4         8 $balance =~ s/,//g;
170              
171 4         10 my $available = $stream->get_trimmed_text("/td");
172 4         141 $available =~ s/\xa3//;
173 4         15 $available =~ s/,//g;
174              
175 4         26 push @accounts, {
176             name => $name,
177             account => $account,
178             sortcode => $sortcode,
179             balance => $balance,
180             available => $available,
181             };
182             }
183              
184 2         130 return \@accounts;
185             };
186              
187             1;
188             __END__