File Coverage

lib/Finance/Bank/DE/NetBank.pm
Criterion Covered Total %
statement 28 152 18.4
branch 0 46 0.0
condition 2 42 4.7
subroutine 8 15 53.3
pod 8 8 100.0
total 46 263 17.4


line stmt bran cond sub pod time code
1             package Finance::Bank::DE::NetBank;
2              
3 5     5   90766 use strict;
  5         8  
  5         167  
4 5     5   21 use vars qw($VERSION $DEBUG);
  5         6  
  5         313  
5 5     5   22 use base qw(Class::Accessor);
  5         8  
  5         2779  
6             Finance::Bank::DE::NetBank->mk_accessors(
7             qw(BASE_URL BLZ CUSTOMER_ID PASSWORD AGENT_TYPE AGENT ACCOUNT Debug));
8              
9 5     5   12610 use WWW::Mechanize;
  5         693648  
  5         201  
10 5     5   4304 use Text::CSV_XS;
  5         39839  
  5         256  
11 5     5   2655 use Data::Dumper;
  5         24272  
  5         7275  
12              
13             $| = 1;
14              
15             $VERSION = "1.05_01";
16              
17             sub Version {
18 1     1 1 12 return $VERSION;
19             }
20              
21             sub new {
22 4     4 1 45 my $proto = shift;
23 4         34 my %values = (
24             AGENT_TYPE => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) ",
25             BASE_URL =>
26             'https://www.netbank-money.de/netbank-barrierefrei-banking/view/',
27             BLZ => '20090500', # NetBank BLZ
28             CUSTOMER_ID => '',
29             PASSWORD => '',
30             ACCOUNT => '',
31             @_
32             );
33              
34 4   33     29 my $class = ref($proto) || $proto;
35 4   33     12 my $parent = ref($proto) && $proto;
36              
37 4         6 my $self = {};
38 4         7 bless( $self, $class );
39              
40 4         15 foreach my $key ( keys %values ) {
41 24         226 $self->$key("$values{$key}");
42             }
43              
44 4         30 return $self;
45             }
46              
47             sub connect {
48 0     0 1   my $self = shift;
49 0           print STDERR "Method connect() is deprecated. Use only login() instead!\n";
50 0           return $self->login(@_);
51             }
52              
53             sub login {
54 0     0 1   my $self = shift;
55 0           my %values = (
56             CUSTOMER_ID => $self->CUSTOMER_ID(),
57             PASSWORD => $self->PASSWORD(),
58             @_
59             );
60            
61 0           my $url = $self->BASE_URL() . "index.jsp?blz=" . $self->BLZ();
62 0           my $agent = WWW::Mechanize->new( agent => $self->AGENT_TYPE(), );
63 0           $agent->get($url);
64 0           $self->AGENT($agent);
65              
66 0           $agent->field( "kundennummer", $values{'CUSTOMER_ID'} );
67 0           $agent->field( "pin", $values{'PASSWORD'} );
68 0           $agent->click();
69              
70 0 0         print STDERR Dumper( $agent->content ) if $self->Debug();
71            
72 0 0         if ($agent->content =~ /fieldtableerrorred/ig) {
73 0           return undef;
74             }
75              
76 0           return 1;
77            
78             }
79              
80             sub saldo {
81 0     0 1   my $self = shift;
82 0           my $data = $self->statement(@_);
83            
84 0 0         if ($data) {
85 0 0         print STDERR Dumper($data) if $self->Debug();
86 0           return $data->{'STATEMENT'}{'SALDO'};
87             } else {
88 0           return undef;
89             }
90             }
91              
92             sub statement {
93 0     0 1   my $self = shift;
94 0           my %values = (
95             TIMEFRAME => "30"
96             , # 1 or 30 days || "alle" = ALL || "variabel" = between START_DATE and END_DATE only
97             START_DATE => 0, # dd.mm.yyyy
98             END_DATE => 0, # dd.mm.yyyy
99             ACCOUNT => $self->ACCOUNT(),
100             @_
101             );
102              
103             # get mainpage
104 0           my $login_status = $self->login();
105 0 0         return undef unless $login_status;
106            
107 0           my $agent = $self->AGENT();
108              
109             # If you've problems with your environmet settings activate this and "use encodings"
110             # binmode(STDOUT, ":encoding(iso-8859-15)");
111              
112 0           $agent->field( "kontonummer", $values{'ACCOUNT'} );
113 0           $agent->field( "zeitraum", $values{'TIMEFRAME'} );
114              
115 0 0 0       if ( $values{'TIMEFRAME'} eq "variabel"
      0        
116             && $values{'START_DATE'}
117             && $values{'END_DATE'} )
118             {
119 0           $agent->field( "startdatum", $values{'START_DATE'} );
120 0           $agent->field( "enddatum", $values{'END_DATE'} );
121             }
122              
123 0           $agent->click();
124 0           $agent->get( $self->BASE_URL() . "/umsatzdownload.do" );
125              
126 0           my $content = $agent->content();
127 0 0         print STDERR Dumper($content) if $self->Debug();
128              
129 0           my $csv_content = $self->_parse_csv($content);
130 0           return $csv_content;
131             }
132              
133             sub transfer {
134 0     0 1   my $self = shift;
135 0           my %values = (
136             SENDER_ACCOUNT => $self->ACCOUNT(),
137             RECEIVER_NAME => "",
138             RECEIVER_ACCOUNT => "",
139             RECEIVER_BLZ => "",
140             RECEIVER_SAVE => "false",
141             COMMENT_1 => "",
142             COMMENT_2 => "",
143             AMOUNT => "0.00",
144             TAN => "",
145             @_
146             );
147            
148             # get mainpage
149 0           my $login_status = $self->login();
150 0 0         return undef unless $login_status;
151              
152 0           my $agent = $self->AGENT();
153 0           my $url = $self->BASE_URL();
154              
155 0           $agent->get($url . "ueberweisung_per_heute_neu.do");
156              
157             ( $values{'AMOUNT_EURO'}, $values{'AMOUNT_CENT'} ) =
158 0           split( /\.|,/, $values{'AMOUNT'} );
159            
160 0           $values{'AMOUNT_CENT'} = sprintf("%02d", $values{'AMOUNT_CENT'});
161              
162 0           $agent->field("auftraggeberKontonummer", $values{'SENDER_ACCOUNT'});
163 0           $agent->field("empfaengerName", $values{'RECEIVER_NAME'});
164 0           $agent->field("empfaengerBankleitzahl", $values{'RECEIVER_BLZ'});
165 0           $agent->field("empfaengerKontonummer", $values{'RECEIVER_ACCOUNT'});
166 0           $agent->field("betragEuro", $values{'AMOUNT_EURO'});
167 0           $agent->field("betragCent", $values{'AMOUNT_CENT'});
168 0           $agent->field("verwendungszweck1", $values{'COMMENT_1'});
169 0           $agent->field("verwendungszweck2", $values{'COMMENT_2'});
170 0           $agent->click("btnNeuSpeichern");
171              
172             # get TAN fieldname, index
173 0           my $tan_field;
174             my $tan_index;
175 0           my $tan;
176            
177 0           $agent->content =~ /(?:Tr|TAN)(?:[a-z].*?)\s?(\d+)/gmix;
178            
179 0           $tan_field = $1;
180 0           $tan_index = $2;
181            
182 0 0         print STDERR "tan_field: $tan_field, tan_index: $tan_index\n" if $self->Debug();
183            
184 0 0 0       if ($tan_field && $tan_index && ref($values{'TAN'}) eq "HASH" && $values{'TAN'}->{$tan_index}) {
    0 0        
    0 0        
      0        
      0        
      0        
      0        
185 0 0         print STDERR "METHOD: TAN HASH" if $self->Debug();
186 0           $tan = $values{'TAN'}->{$tan_index};
187             } elsif ($tan_field && $tan_index && ref($values{'TAN'}) eq "ARRAY") {
188 0 0         print STDERR "METHOD: Object/Method" if $self->Debug();
189 0           my $obj = $values{'TAN'}[0];
190 0           my $method = $values{'TAN'}[1];
191 0           eval ( $tan = $obj->$method() );
192 0 0         if ($@) {
193 0           print "ERROR: Could not execute TAN method: $method";
194 0           return undef;
195             }
196             } elsif ($tan_field && $tan_index && ref($values{'TAN'}) eq "CODE") {
197 0 0         print STDERR "METHOD: CALLBACK" if $self->Debug();
198 0           $tan = &{$values{'TAN'}}($tan_index);
  0            
199             }
200              
201 0 0         print STDERR " TAN: [$tan]\n" if $self->Debug();
202            
203 0 0         if ($tan) {
204 0           $agent->field($tan_field, $tan_index);
205 0           $agent->click("btnBestaetigen");
206              
207             # lazy error checking
208 0 0         if ( $agent->content() =~ m|(.*)30017(.*)| ) {
209 0           $agent->content() =~ m|(.*?)|;
210 0           my $error = $1;
211 0           print "ERROR: $error";
212 0           return;
213             } else {
214 0           my $content = $agent->content();
215 0           return $agent->content();
216             }
217             } else {
218 0           print "ERROR: Could not identify requested TAN Index #";
219 0           return;
220             }
221             }
222              
223             sub logout {
224 0     0 1   my $self = shift;
225 0           my $agent = $self->AGENT();
226 0           my $url = $self->BASE_URL();
227 0           $agent->get( $url . "logout.do" );
228             }
229              
230             sub _parse_csv {
231 0     0     my $self = shift;
232 0           my $csv_content = shift;
233 0           $csv_content =~ s/\r//gmi;
234 0           $csv_content =~ s/\f//gmi;
235 0           my @lines = split( "\n", $csv_content );
236 0           my %data;
237              
238 0           my $csv = Text::CSV_XS->new(
239             {
240             sep_char => "\t",
241             binary => 1, ### german umlauts...
242             }
243             );
244              
245 0           my $line_count = 0;
246              
247 0           foreach my $line (@lines) {
248 0           my $status = $csv->parse($line);
249 0           my @columns = $csv->fields();
250 0           $line_count++;
251              
252             ### Account Details ########################
253 0 0 0       if ( $line_count > 3 && $line_count < 6 ) {
254 0           $columns[0] =~ s/://;
255 0           $data{"ACCOUNT"}{ uc( $columns[0] ) } = $columns[1];
256             }
257              
258             ### Statement Details ######################
259 0 0         if ( $line_count == 9 ) {
260 0           $data{"STATEMENT"}{"START_DATE"} = $columns[0];
261 0           $data{"STATEMENT"}{"END_DATE"} = $columns[1];
262 0           $data{"STATEMENT"}{"ACCOUNT_ID"} = $columns[2];
263 0           $data{"STATEMENT"}{"SALDO"} = $columns[3];
264 0           $data{"STATEMENT"}{"WAEHRUNG"} = $columns[4];
265             }
266              
267             ### Transactions ###########################
268 0 0 0       if ( $line_count > 12 && $line_count <= $#lines ) {
269 0           my $row = $line_count - 13;
270 0           $data{"TRANSACTION"}[$row]{"BUCHUNGSTAG"} = $columns[0];
271 0           $data{"TRANSACTION"}[$row]{"WERTSTELLUNGSTAG"} = $columns[1];
272 0           $data{"TRANSACTION"}[$row]{"VERWENDUNGSZWECK"} = $columns[2];
273              
274 0           $columns[3] =~ s/\.//;
275 0           $columns[3] =~ s/,/\./;
276              
277 0           $data{"TRANSACTION"}[$row]{"UMSATZ"} = $columns[3];
278 0           $data{"TRANSACTION"}[$row]{"WAEHRUNG"} = $columns[4];
279 0 0 0       $data{"TRANSACTION"}[$row]{"NOT_YET_FINISHED"} = $columns[5]
280             if ( defined( $columns[5] ) && $columns[5] =~ m/^[^\s]$/ig );
281             }
282             }
283              
284 0           return \%data;
285             }
286              
287             1;
288             __END__