File Coverage

blib/lib/Finance/Bank/HSBC.pm
Criterion Covered Total %
statement 15 65 23.0
branch 0 14 0.0
condition n/a
subroutine 5 6 83.3
pod 0 1 0.0
total 20 86 23.2


line stmt bran cond sub pod time code
1             package Finance::Bank::HSBC;
2 1     1   6751 use strict;
  1         3  
  1         32  
3 1     1   5 use Carp;
  1         2  
  1         82  
4             our $VERSION = '1.03';
5              
6 1     1   1182 use Data::Dumper;
  1         17406  
  1         69  
7 1     1   1234 use WWW::Mechanize;
  1         210641  
  1         50  
8 1     1   13 use HTML::TokeParser;
  1         2  
  1         638  
9              
10             sub check_balance {
11 0     0 0   my ($class, %opts) = @_;
12 0           my @accounts;
13 0 0         croak "Must provide a security code" unless exists $opts{seccode};
14 0 0         croak "Must provide a banking id" unless exists $opts{bankingid};
15 0 0         croak "Must provide a date of birth" unless exists $opts{dateofbirth};
16              
17 0           my $self = bless { %opts }, $class;
18            
19 0           my $agent = WWW::Mechanize->new();
20 0           $agent->get("http://www.ukpersonal.hsbc.com/public/ukpersonal/internet_banking/en/logon.jhtml");
21              
22             # Filling in the login form.
23 0           $agent->form(0);
24 0           $agent->field("internetBankingID", $opts{bankingid});
25 0           $agent->click("Log on to Internet Banking. This link will open in a new browser window.");
26              
27             # We're given a redirect, and then need to navigate a frameset.
28 0           $agent->follow(2);
29              
30             # The new login page.
31 0           $agent->field("dateOfBirth", $opts{dateofbirth});
32            
33 0           $agent->content =~ /Please enter the (\w+), (\w+) and (\w+) digits/;
34              
35             # Supplied by Leon Cowle. Anyone have a one-liner for this?
36 0           my $seccodedigits = "000000";
37 0 0         if ( $agent->content =~ /Please enter the (.*?) digits of your security number/ ) {
38 0           $seccodedigits = $1;
39             }
40             else {
41 0           croak "Was expecting request for security code digits";
42             }
43              
44 0           my @digitnames = qw /FIRST SECOND THIRD FOURTH FIFTH SIXTH SEVENTH EIGHTH NINTH/;
45 0           my $seccodelength = length($opts{seccode});
46 0           my @seccodearray = split(//, $opts{seccode});
47              
48 0           $seccodedigits =~ s/LAST/$seccodearray[--$seccodelength]/;
49              
50             # Substitute the other words (FIRST, etc) with the respective digits
51 0           while ($seccodelength >= 0) {
52 0           $seccodedigits =~ s/$digitnames[$seccodelength]/$seccodearray[$seccodelength]/;
53 0           $seccodelength--;
54             }
55              
56             # Remove all non-digits from result.
57 0           $seccodedigits =~ s/\D//g;
58              
59 0           $agent->field("tsn", $seccodedigits);
60 0           $agent->click("Continue to log on");
61              
62             # More frameset navigation.
63 0           $agent->follow(0);
64 0           $agent->follow(2);
65              
66             # Now we have the data, we need to parse it. This is fragile.
67             # (Update, 2004-01-19: Actually, the whole module's fragile. Sorry.)
68            
69 0           my $content = $agent->{content};
70              
71 0           my ($split1, $split2) = split /Balance<\/b><\/td>/, $content;
72 0           my ($content, $split2) = split /*/, $split2;
73              
74 0 0         my $stream = HTML::TokeParser->new(\$content) or die "$!";
75 0           $stream->get_tag("tr");
76              
77 0           while (my $token = $stream->get_tag("tr")) {
78 0           $token = $stream->get_tag("td");
79            
80 0 0         if ($token->[1]{height} eq "25") {
81             # We have an account.
82 0           my $accountname = $stream->get_trimmed_text("/td");
83 0           $stream->get_tag("td");
84              
85 0           my $accounttype = $stream->get_trimmed_text("/td");
86 0           $stream->get_tag("td");
87              
88 0           my $accountnumber = $stream->get_trimmed_text("/td");
89 0           $stream->get_tag("td");
90 0           $stream->get_tag("td");
91              
92 0           my $accountbalance = $stream->get_trimmed_text("/td");
93              
94             # Convert / [CD]$/ to a positive or negative float.
95 0           $accountbalance =~ s/ C$//;
96 0 0         $accountbalance = "-$accountbalance" if $accountbalance =~ s/ D$//;
97            
98 0           push @accounts, {
99             balance => $accountbalance,
100             name => $accountname,
101             type => $accounttype,
102             account => $accountnumber
103             };
104             }
105             }
106 0           return @accounts;
107             }
108              
109             1;
110             __END__