fix order_number and also return avs code
[Business-OnlinePayment-LinkPoint.git] / LinkPoint.pm
1 package Business::OnlinePayment::LinkPoint;
2
3 # $Id: LinkPoint.pm,v 1.21 2004-06-24 15:31:58 ivan Exp $
4
5 use strict;
6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
7 use Carp qw(croak);
8 use AutoLoader;
9 use Business::OnlinePayment;
10
11 require Exporter;
12
13 @ISA = qw(Exporter AutoLoader Business::OnlinePayment);
14 @EXPORT = qw();
15 @EXPORT_OK = qw();
16 $VERSION = '0.04';
17
18 use lpperl; #3;  #lperl.pm from LinkPoint
19 $LPPERL::VERSION =~ /^(\d+\.\d+)/
20   or die "can't parse lperl.pm version: $LPPERL::VERSION";
21 die "lpperl.pm minimum version 3 required\n" unless $1 >= 3;
22
23 sub set_defaults {
24     my $self = shift;
25
26     #$self->server('staging.linkpt.net');
27     $self->server('secure.linkpt.net');
28     $self->port('1129');
29
30     $self->build_subs(qw(order_number avs_code));
31
32 }
33
34 sub map_fields {
35     my($self) = @_;
36
37     my %content = $self->content();
38
39     #ACTION MAP
40     my %actions = ('normal authorization' => 'SALE',
41                    'authorization only'   => 'PREAUTH',
42                    'credit'               => 'CREDIT',
43                    'post authorization'   => 'POSTAUTH',
44                    'void'                 => 'VOID',
45                   );
46     $content{'action'} = $actions{lc($content{'action'})} || $content{'action'};
47
48     # stuff it back into %content
49     $self->content(%content);
50 }
51
52 sub build_subs {
53     my $self = shift;
54     foreach(@_) {
55         #no warnings; #not 5.005
56         local($^W)=0;
57         eval "sub $_ { my \$self = shift; if(\@_) { \$self->{$_} = shift; } return \$self->{$_}; }";
58     }
59 }
60
61 sub remap_fields {
62     my($self,%map) = @_;
63
64     my %content = $self->content();
65     foreach(keys %map) {
66         $content{$map{$_}} = $content{$_};
67     }
68     $self->content(%content);
69 }
70
71 sub revmap_fields {
72     my($self, %map) = @_;
73     my %content = $self->content();
74     foreach(keys %map) {
75 #    warn "$_ = ". ( ref($map{$_})
76 #                         ? ${ $map{$_} }
77 #                         : $content{$map{$_}} ). "\n";
78         $content{$_} = ref($map{$_})
79                          ? ${ $map{$_} }
80                          : $content{$map{$_}};
81     }
82     $self->content(%content);
83 }
84
85 sub get_fields {
86     my($self,@fields) = @_;
87
88     my %content = $self->content();
89     my %new = ();
90     foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
91     return %new;
92 }
93
94 sub submit {
95     my($self) = @_;
96
97     $self->map_fields();
98
99     my %content = $self->content;
100
101     my($month, $year);
102     unless ( $content{action} eq 'POSTAUTH' ) {
103
104         if (  $self->transaction_type() =~
105                 /^(cc|visa|mastercard|american express|discover)$/i
106            ) {
107         } else {
108             Carp::croak("LinkPoint can't handle transaction type: ".
109                         $self->transaction_type());
110         }
111
112       $content{'expiration'} =~ /^(\d+)\D+\d*(\d{2})$/
113         or croak "unparsable expiration $content{expiration}";
114
115       ( $month, $year ) = ( $1, $2 );
116       $month = '0'. $month if $month =~ /^\d$/;
117     }
118
119     $content{'address'} =~ /^(\S+)\s/;
120     my $addrnum = $1;
121
122     my $result = $content{'result'};
123     if ( $self->test_transaction) {
124       $result ||= 'GOOD';
125       #$self->server('staging.linkpt.net');
126     } else {
127       $result ||= 'LIVE';
128     }
129
130     $self->revmap_fields(
131       host         => \( $self->server ),
132       port         => \( $self->port ),
133       #storename    => \( $self->storename ),
134       configfile   => \( $self->storename ),
135       keyfile      => \( $self->keyfile ),
136       addrnum      => \$addrnum,
137       result       => \$result,
138       cardnumber   => 'card_number',
139       cardexpmonth => \$month,
140       cardexpyear  => \$year,
141       chargetotal  => 'amount',
142     );
143
144     my $lperl = new LPPERL;
145
146     $self->required_fields(qw/
147       host port configfile keyfile amount cardnumber cardexpmonth cardexpyear
148     /);
149
150     my %post_data = $self->get_fields(qw/
151       host port configfile keyfile
152       result
153       chargetotal cardnumber cardexpmonth cardexpyear
154       name email phone addrnum city state zip country
155     /);
156
157     $post_data{'ordertype'} = $content{action};
158
159     if ( $content{'cvv2'} ) { 
160       $post_data{cvmindicator} = 'provided';
161       $post_data{cvmvalue} = $content{'cvv2'};
162     }
163
164     warn "$_ => $post_data{$_}\n" foreach keys %post_data;
165
166     my %response;
167     #{
168     #  local($^W)=0;
169     #  %response = $lperl->$action(\%post_data);
170     #}
171     %response = $lperl->curl_process(\%post_data);
172
173     warn "$_ => $response{$_}\n" for keys %response;
174
175     if ( $response{'r_approved'} eq 'APPROVED' ) {
176       $self->is_success(1);
177       $self->result_code($response{'r_code'});
178       $self->authorization($response{'r_ref'});
179       $self->order_number($response{'r_ordernum'});
180       $self->avs_code($response{'r_avs'};
181     } else {
182       $self->is_success(0);
183       $self->result_code('');
184       $self->error_message($response{'r_error'});
185     }
186
187 }
188
189 1;
190 __END__
191
192 =head1 NAME
193
194 Business::OnlinePayment::LinkPoint - LinkPoint (Cardservice) backend for Business::OnlinePayment
195
196 =head1 SYNOPSIS
197
198   use Business::OnlinePayment;
199
200   my $tx = new Business::OnlinePayment( 'LinkPoint',
201     'storename' => 'your_store_number',
202     'keyfile'   => '/path/to/keyfile.pem',
203   );
204
205   $tx->content(
206       type           => 'VISA',
207       action         => 'Normal Authorization',
208       description    => 'Business::OnlinePayment test',
209       amount         => '49.95',
210       invoice_number => '100100',
211       customer_id    => 'jsk',
212       name           => 'Jason Kohles',
213       address        => '123 Anystreet',
214       city           => 'Anywhere',
215       state          => 'UT',
216       zip            => '84058',
217       email          => 'ivan-linkpoint@420.am',
218       card_number    => '4007000000027',
219       expiration     => '09/99',
220   );
221   $tx->submit();
222
223   if($tx->is_success()) {
224       print "Card processed successfully: ".$tx->authorization."\n";
225   } else {
226       print "Card was rejected: ".$tx->error_message."\n";
227   }
228
229 =head1 SUPPORTED TRANSACTION TYPES
230
231 =head2 Visa, MasterCard, American Express, JCB, Discover/Novus, Carte blanche/Diners Club
232
233 =head1 DESCRIPTION
234
235 For detailed information see L<Business::OnlinePayment>.
236
237 =head1 COMPATIBILITY
238
239 This module implements an interface to the LinkPoint Perl Wrapper
240 http://www.linkpoint.com/product_solutions/internet/lperl/lperl_main.html
241
242 Version 0.4 of this module has been updated for the LinkPoint Perl Wrapper
243 version 3.5.
244
245 =head1 BUGS
246
247 =head1 AUTHOR
248
249 Ivan Kohler <ivan-linkpoint@420.am>
250
251 Based on Busienss::OnlinePayment::AuthorizeNet written by Jason Kohles.
252
253 =head1 SEE ALSO
254
255 perl(1), L<Business::OnlinePayment>.
256
257 =cut
258