File Coverage

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


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