File Coverage

blib/lib/Business/OnlinePayment/viaKLIX.pm
Criterion Covered Total %
statement 29 113 25.6
branch 3 34 8.8
condition 1 23 4.3
subroutine 6 11 54.5
pod 5 5 100.0
total 44 186 23.6


line stmt bran cond sub pod time code
1             package Business::OnlinePayment::viaKLIX;
2              
3 2     2   31196 use strict;
  2         4  
  2         88  
4 2     2   11 use vars qw($VERSION $DEBUG);
  2         5  
  2         196  
5 2     2   14 use Carp qw(carp croak);
  2         8  
  2         141  
6              
7 2     2   10 use base qw(Business::OnlinePayment::HTTPS);
  2         4  
  2         1919  
8              
9             $VERSION = '0.02';
10             $VERSION = eval $VERSION;
11             $DEBUG = 0;
12              
13             sub debug {
14 0     0 1 0 my $self = shift;
15              
16 0 0       0 if (@_) {
17 0   0     0 my $level = shift || 0;
18 0 0       0 if ( ref($self) ) {
19 0         0 $self->{"__DEBUG"} = $level;
20             }
21             else {
22 0         0 $DEBUG = $level;
23             }
24 0         0 $Business::OnlinePayment::HTTPS::DEBUG = $level;
25             }
26 0 0 0     0 return ref($self) ? ( $self->{"__DEBUG"} || $DEBUG ) : $DEBUG;
27             }
28              
29             sub set_defaults {
30 2     2 1 2848 my $self = shift;
31 2         4 my %opts = @_;
32              
33             # standard B::OP methods/data
34 2         51 $self->server("www.viaKLIX.com");
35 2         67 $self->port("443");
36 2         60 $self->path("/process.asp");
37              
38 2         25 $self->build_subs(qw(
39             order_number avs_code cvv2_response
40             response_page response_code response_headers
41             ));
42              
43             # module specific data
44 2 50       136 if ( $opts{debug} ) {
45 0         0 $self->debug( $opts{debug} );
46 0         0 delete $opts{debug};
47             }
48              
49 2         4 my %_defaults = ();
50 2         5 foreach my $key (keys %opts) {
51 0 0       0 $key =~ /^default_(\w*)$/ or next;
52 0         0 $_defaults{$1} = $opts{$key};
53 0         0 delete $opts{$key};
54             }
55 2         9 $self->{_defaults} = \%_defaults;
56              
57             }
58              
59             sub _map_fields {
60 0     0   0 my ($self) = @_;
61              
62 0         0 my %content = $self->content();
63              
64             #ACTION MAP
65 0         0 my %actions = (
66             'normal authorization' => 'SALE', # Authorization/Settle transaction
67             'credit' => 'CREDIT', # Credit (refund)
68             );
69              
70 0   0     0 $content{'ssl_transaction_type'} = $actions{ lc( $content{'action'} ) }
71             || $content{'action'};
72              
73             # TYPE MAP
74 0         0 my %types = (
75             'visa' => 'CC',
76             'mastercard' => 'CC',
77             'american express' => 'CC',
78             'discover' => 'CC',
79             'cc' => 'CC',
80             );
81              
82 0   0     0 $content{'type'} = $types{ lc( $content{'type'} ) } || $content{'type'};
83              
84 0         0 $self->transaction_type( $content{'type'} );
85              
86             # stuff it back into %content
87 0         0 $self->content(%content);
88             }
89              
90             sub _revmap_fields {
91 0     0   0 my ( $self, %map ) = @_;
92 0         0 my %content = $self->content();
93 0         0 foreach ( keys %map ) {
94 0         0 $content{$_} =
95             ref( $map{$_} )
96 0 0       0 ? ${ $map{$_} }
97             : $content{ $map{$_} };
98             }
99 0         0 $self->content(%content);
100             }
101              
102             sub expdate_mmyy {
103 4     4 1 918 my $self = shift;
104 4         4 my $expiration = shift;
105 4         5 my $expdate_mmyy;
106 4 50 33     33 if ( defined($expiration) and $expiration =~ /^(\d+)\D+\d*(\d{2})$/ ) {
107 4         10 my ( $month, $year ) = ( $1, $2 );
108 4         13 $expdate_mmyy = sprintf( "%02d", $month ) . $year;
109             }
110 4 50       14 return defined($expdate_mmyy) ? $expdate_mmyy : $expiration;
111             }
112              
113             sub required_fields {
114 0     0 1   my($self,@fields) = @_;
115              
116 0           my @missing;
117 0           my %content = $self->content();
118 0           foreach(@fields) {
119             next
120 0 0 0       if (exists $content{$_} && defined $content{$_} && $content{$_}=~/\S+/);
      0        
121 0           push(@missing, $_);
122             }
123              
124 0 0         Carp::croak("missing required field(s): " . join(", ", @missing) . "\n")
125             if(@missing);
126              
127             }
128              
129             sub submit {
130 0     0 1   my ($self) = @_;
131              
132 0           $self->_map_fields();
133              
134 0           my %content = $self->content;
135              
136 0           my %required;
137 0           $required{CC_SALE} = [ qw( ssl_transaction_type ssl_merchant_id ssl_pin
138             ssl_amount ssl_card_number ssl_exp_date
139             ) ];
140 0           $required{CC_CREDIT} = $required{CC_SALE};
141 0           my %optional;
142 0           $optional{CC_SALE} = [ qw( ssl_user_id ssl_salestax ssl_cvv2 ssl_cvv2cvc2
143             ssl_description ssl_invoice_number
144             ssl_customer_code ssl_company ssl_first_name
145             ssl_last_name ssl_avs_address ssl_address2
146             ssl_city ssl_state ssl_avs_zip ssl_country
147             ssl_phone ssl_email ssl_ship_to_company
148             ssl_ship_to_first_name ssl_ship_to_last_name
149             ssl_ship_to_address ssl_ship_to_city
150             ssl_ship_to_state ssl_ship_to_zip
151             ssl_ship_to_country
152             ) ];
153 0           $optional{CC_CREDIT} = $optional{CC_SALE};
154              
155 0           my $type_action = $self->transaction_type(). '_'. $content{ssl_transaction_type};
156 0 0         unless ( exists($required{$type_action}) ) {
157 0           $self->error_message("viaKLIX can't handle transaction type: ".
158             "$content{action} on " . $self->transaction_type() );
159 0           $self->is_success(0);
160 0           return;
161             }
162              
163 0           my $expdate_mmyy = $self->expdate_mmyy( $content{"expiration"} );
164 0           my $zip = $content{'zip'};
165 0           $zip =~ s/[^[:alnum:]]//g;
166              
167 0 0         my $cvv2indicator = 'present' if ( $content{"cvv2"} ); # visa only
168              
169 0           $self->_revmap_fields(
170              
171             ssl_merchant_id => 'login',
172             ssl_pin => 'password',
173              
174             ssl_amount => 'amount',
175             ssl_card_number => 'card_number',
176             ssl_exp_date => \$expdate_mmyy, # MMYY from 'expiration'
177             ssl_cvv2 => \$cvv2indicator,
178             ssl_cvv2cvc2 => 'cvv2',
179             ssl_description => 'description',
180             ssl_invoice_number => 'invoice_number',
181             ssl_customer_code => 'customer_id',
182              
183             ssl_first_name => 'first_name',
184             ssl_last_name => 'last_name',
185             ssl_avs_address => 'address',
186             ssl_city => 'city',
187             ssl_state => 'state',
188             ssl_avs_zip => \$zip, # 'zip' with non-alnums removed
189             ssl_country => 'country',
190             ssl_phone => 'phone',
191             ssl_email => 'email',
192              
193             );
194              
195 0           my %params = $self->get_fields( @{$required{$type_action}},
  0            
196 0           @{$optional{$type_action}},
197             );
198              
199 0           foreach ( keys ( %{($self->{_defaults})} ) ) {
  0            
200 0 0         $params{$_} = $self->{_defaults}->{$_} unless exists($params{$_});
201             }
202              
203 0 0         $params{ssl_test_mode}='true' if $self->test_transaction;
204            
205 0           $params{ssl_show_form}='false';
206 0           $params{ssl_result_format}='ASCII';
207              
208 0           $self->required_fields(@{$required{$type_action}});
  0            
209            
210 0 0         warn join("\n", map{ "$_ => $params{$_}" } keys(%params)) if $DEBUG > 1;
  0            
211 0           my ( $page, $resp, %resp_headers ) =
212             $self->https_post( %params );
213              
214 0           $self->response_code( $resp );
215 0           $self->response_page( $page );
216 0           $self->response_headers( \%resp_headers );
217              
218 0 0         warn "$page\n" if $DEBUG > 1;
219             # $page should contain key/value pairs
220              
221 0           my $status ='';
222 0           my %results = map { s/\s*$//; split '=', $_, 2 } split '^', $page;
  0            
  0            
223              
224             # AVS and CVS values may be set on success or failure
225 0           $self->avs_code( $results{ssl_avs_response} );
226 0           $self->cvv2_response( $results{ ssl_cvv2_response } );
227 0           $self->result_code( $status = $results{ ssl_result } );
228 0           $self->order_number( $results{ ssl_txn_id } );
229 0           $self->authorization( $results{ ssl_approval_code } );
230 0           $self->error_message( $results{ ssl_result_message } );
231              
232              
233 0 0 0       if ( $resp =~ /^(HTTP\S+ )?200/ && $status eq "0" ) {
234 0           $self->is_success(1);
235             } else {
236 0           $self->is_success(0);
237             }
238             }
239              
240             1;
241              
242             __END__