| Finance-Bank-NetBranch documentation | Contained in the Finance-Bank-NetBranch distribution. |
Finance::Bank::NetBranch - Manage your NetBranch accounts with Perl
Version 0.07
use Finance::Bank::NetBranch;
my $nb = Finance::Bank::NetBranch->new(
url => 'https://nbp1.cunetbranch.com/valley/',
account => '12345',
password => 'abcdef',
);
my @accounts = $nb->accounts;
foreach (@accounts) {
printf "%20s : %8s : USD %9.2f of %9.2f\n",
$_->name, $_->account_no, $_->available, $_->balance;
my $days = 20;
for ($_->transactions(from => time - (86400 * $days), to => time)) {
printf "%10s | %20s | %80s : %9.2f, %9.2f\n",
$_->date->ymd, $_->type, $_->description, $_->amount, $_->balance;
}
}
This module provides a rudimentary interface to NetBranch online banking. This
module was originally implemented to interface with Valley Communities Credit
Union's page at https://nbp1.cunetbranch.com/valley/, but the behavior of
the module is theoretically generalized to "NetBranch" type online access.
However, I do not have access to another NetBranch account with another bank,
and so any feedback on the actual behavior of this module would be greatly
appreciated.
You will need either Crypt::SSLeay or IO::Socket::SSL installed for HTTPS
support to work.
Creates a new Finance::Bank::NetBranch object; does not connect to the server.
Retrieves cached accounts information, connecting to the server if necessary.
Logs into the NetBranch site (internal use only)
Logs out of the NetBranch site (internal use only)
Gets account balance information (internal use only)
Gets transaction information, given start and end dates (internal use only)
Pads a number to two digits with zeroes
Return the account name, sort code or account number. The sort code is just the name in this case, but it has been included for consistency with other Finance::Bank::* modules.
Return the account balance or available amount as a signed floating point value.
Provides accessors (from Finance::Card::Citibank)
Retrieves Finance::Bank::NetBranch::Transaction objects for the specified
account object between two dates (unix timestamps or DateTime objects).
Return appropriate data from this transaction.
Provides accessors (from Finance::Card::Citibank)
This warning is verbatim from Simon Cozens' Finance::Bank::LloydsTSB,
and certainly applies to this module as well.
This is code for online banking, and that means your money, and that means BE CAREFUL. You are encouraged, nay, expected, to audit the source of this module yourself to reassure yourself that I am not doing anything untoward with your banking data. This software is useful to me, but is provided under NO GUARANTEE, explicit or implied.
Probably, but moreso lack of such incredibly dangerous features as transfers, scheduled transfers, etc., coming in a future release. Maybe.
Please report any bugs or feature requests to
bug-finance-bank-netbranch at rt.cpan.org, or through the web interface at
http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Finance-Bank-NetBranch.
I will be notified, and then you'll automatically be notified of progress on
your bug as I make changes.
You can find documentation for this module with the perldoc command.
perldoc Finance::Bank::NetBranch
You can also look for information at:
http://rt.cpan.org/NoAuth/Bugs.html?Dist=Finance-Bank-NetBranch
Mark V. Grimes for Finance::Card::Citibank. The pod was taken from Mark's
module.
Darren M. Kulp <darren@kulp.ch>
Copyright (C) 2006 by Darren Kulp
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.7 or, at your option, any later version of Perl 5 you may have available.
| Finance-Bank-NetBranch documentation | Contained in the Finance-Bank-NetBranch distribution. |
package Finance::Bank::NetBranch; use strict; use warnings; use Alias 'attr'; use Carp; use Date::Parse; use DateTime; use HTML::Entities qw(%entity2char _decode_entities); use HTML::TreeBuilder; use WWW::Mechanize; $Alias::AttrPrefix = "main::"; # make use strict 'vars' palatable
our $VERSION = 0.07;
sub new { my $type = shift; bless { @_ }, $type; }
sub accounts { my $self = attr shift; @::accounts || @{ $self->_get_balances } }
sub _login { my $self = attr shift; $::mech ||= WWW::Mechanize->new; $::mech->get($::url) or die "Could not fetch login page URL '$::url'"; my $result = $::mech->submit_form( form_name => 'frmLogin', fields => { USERNAME => $::account, password => $::password, }, button => 'Login' ) or die "Could not submit login form as account '$::account'"; $::mech->uri =~ /welcome/i or die "Failed to log in as account '$::account'"; $::logged_in = 1; $result; }
sub _logout { my $self = attr shift; $::mech->follow_link(text_regex => qr/Logo(ut|ff)/i) or die "Failed to log out"; $::logged_in = 0; }
sub _get_balances { my $self = attr shift; my $result = $self->_login unless $::logged_in; # Change to use HTML::TreeBuilder my ($user, undef, $private) = $result->content =~ m! <h3>welcome\s*([^<]+)</h3>member\s*\#(\d+)\s*\(<b>([^<]+)</b>\)<br> !imox; _decode_entities($user, +{ %entity2char, nbsp => ' ' }); my $t = HTML::TreeBuilder->new; my @accounts = map { my ($name, $bal, $avail) = map { $_->as_text } $_->find('td'); ($name, my $account_no) = ($name =~ m/^([^(]+)\(([^)]+)\).*$/); $avail =~ s/\$//; $bal =~ s/\$//; # get rid of currency sign $avail =~ s/,//g; $bal =~ s/,//g; # Get rid of thousands separators bless { account_no => $account_no, # Detect trailing parenthesis (negative number) available => ($avail =~ /([\d+.]+)\)/) ? -$1 : $avail, balance => ($bal =~ /([\d+.]+)\)/) ? -$1 : $bal, name => $name, parent => $self, sort_code => $name, transactions => [], }, "Finance::Bank::NetBranch::Account"; } do { $t->parse($result->content); $t->eof; $t->look_down( _tag => 'table', sub { my $table = $_[0]; $table->look_down( _tag => 'th', class => 'ColumnTitle', sub { grep { /Balance/i } $_[0]->content_list }, sub { $_[0]->depth - $table->depth < 3 }, ) }, )->look_down( _tag => 'tr', sub { !$_[0]->find('th') }, sub { !grep { $_->as_text =~ /Total/i } $_[0]->content_list }, ) }; $t->delete; $self->_logout; $self->{accounts} = \@accounts }
sub _get_transactions { my $self = attr shift; my ($account, %args) = @_; $self->_login unless $::logged_in; $::mech->follow_link(text_regex => qr/Account History/) or die "Failed to open account history mech"; my $result = $::mech->follow_link( text_regex => qr/\($account->{account_no}\)/ ) or die "Failed to open history for account '$account->{account_no}'"; # Convert dates into DateTime objects if necessary my ($from, $to) = map { ref($_) eq 'DateTime' ? $_ : DateTime->from_epoch(epoch => $_) } @args{qw(from to)};
sub _pad0 { sprintf "%0.2d", shift } $::mech->form_name('HistReq'); $::mech->select('FM', _pad0($from->month)); $::mech->select('FD', $from->day); $::mech->select('FY', $from->year); $::mech->select('TM', _pad0($to->month)); $::mech->select('TD', $to->day); $::mech->select('TY', $to->year); $result = $::mech->submit or die "Could not submit history request form"; my $t = HTML::TreeBuilder->new; # Reverse to put oldest transactions first my @transactions = reverse map { my ($date, $type, $desc, $amount, $bal) = map { $_->as_text } $_->find('td'); $date = DateTime->from_epoch(epoch => str2time($date)); $amount =~ s/\$//; $bal =~ s/\$//; # get rid of currency sign $amount =~ s/,//g; $bal =~ s/,//g; # Get rid of thousands separators $desc =~ s/\x{A0}/ /g; bless { # Detect trailing parenthesis (negative number) amount => ($amount =~ /([\d+.]+)\)/) ? -$1 : $amount, balance => ($bal =~ /([\d+.]+)\)/) ? -$1 : $bal, date => $date, description => $desc, parent => $account, type => $type, }, "Finance::Bank::NetBranch::Transaction"; } do { $t->parse($result->content); $t->eof; $t->look_down( _tag => 'table', sub { my $table = $_[0]; $table->look_down( _tag => 'th', class => 'ColumnTitle', sub { grep { /New Balance/i } $_[0]->content_list }, sub { $_[0]->depth - $table->depth < 3 }, ) }, )->look_down( _tag => 'tr', sub { !$_[0]->find('th') }, ) }; $t->delete; $self->_logout; $self->{transactions} = \@transactions }
package Finance::Bank::NetBranch::Account; use Alias 'attr'; use Carp; no strict;
sub AUTOLOAD { my $self = shift; $AUTOLOAD =~ s/.*:://; $self->{$AUTOLOAD} }
sub transactions ($%) { my $self = attr shift; my (%args) = @_; $args{from} && $args{to} or croak "Must supply from and to dates"; @::transactions = (@::transactions || @{ $::parent->_get_transactions($self, %args) }); }
package Finance::Bank::NetBranch::Transaction; no strict;
sub AUTOLOAD { my $self = shift; $AUTOLOAD =~ s/.*:://; $self->{$AUTOLOAD} } 1; __END__