untested update for linkpoint 2.6 changes, ick
[Business-OnlinePayment-LinkPoint.git] / LinkPoint.pm
1 package Business::OnlinePayment::LinkPoint;
2
3 # $Id: LinkPoint.pm,v 1.8 2003-05-13 10:25:08 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.02';
17
18 use lperl; #2.6;  #lperl.pm from LinkPoint
19 $LPERL::VERSION =~ /^(\d+\.\d+)/
20   or die "can't parse lperl.pm version: $LPERL::VERSION";
21 die "lperl.pm minimum version 2.6 required\n" unless $1 >= 2.6;
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 }
31
32 sub map_fields {
33     my($self) = @_;
34
35     my %content = $self->content();
36
37     #ACTION MAP
38     my %actions = ('normal authorization' => 'ApproveSale',
39                    'authorization only'   => 'CapturePayment',
40                    'credit'               => 'ReturnOrder',
41                    'post authorization'   => 'BillOrders',
42                   );
43     $content{'action'} = $actions{lc($content{'action'})} || $content{'action'};
44
45     # stuff it back into %content
46     $self->content(%content);
47 }
48
49 sub build_subs {
50     my $self = shift;
51     foreach(@_) {
52         #no warnings; #not 5.005
53         local($^W)=0;
54         eval "sub $_ { my \$self = shift; if(\@_) { \$self->{$_} = shift; } return \$self->{$_}; }";
55     }
56 }
57
58 sub remap_fields {
59     my($self,%map) = @_;
60
61     my %content = $self->content();
62     foreach(keys %map) {
63         $content{$map{$_}} = $content{$_};
64     }
65     $self->content(%content);
66 }
67
68 sub revmap_fields {
69     my($self, %map) = @_;
70     my %content = $self->content();
71     foreach(keys %map) {
72 #    warn "$_ = ". ( ref($map{$_})
73 #                         ? ${ $map{$_} }
74 #                         : $content{$map{$_}} ). "\n";
75         $content{$_} = ref($map{$_})
76                          ? ${ $map{$_} }
77                          : $content{$map{$_}};
78     }
79     $self->content(%content);
80 }
81
82 sub get_fields {
83     my($self,@fields) = @_;
84
85     my %content = $self->content();
86     my %new = ();
87     foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
88     return %new;
89 }
90
91 sub submit {
92     my($self) = @_;
93
94     $self->map_fields();
95
96     my %content = $self->content;
97
98     my($month, $year);
99     unless ( $content{action} eq 'BillOrders' ) {
100
101         if (  $self->transaction_type() =~
102                 /^(cc|visa|mastercard|american express|discover)$/i
103            ) {
104         } else {
105             Carp::croak("LinkPoint can't handle transaction type: ".
106                         $self->transaction_type());
107         }
108
109       $content{'expiration'} =~ /^(\d+)\D+\d*(\d{2})$/
110         or croak "unparsable expiration $content{expiration}";
111
112       ( $month, $year ) = ( $1, $2 );
113       $month = '0'. $month if $month =~ /^\d$/;
114       $year += 2000 if $year < 2000; #not y4k safe, oh shit
115     }
116
117     $content{'address'} =~ /^(\S+)\s/;
118     my $addrnum = $1;
119
120     my $result = $content{'result'};
121     if ( $self->test_transaction) {
122       $result ||= 'GOOD';
123       $self->server('staging.linkpt.net');
124     } else {
125       $result ||= 'LIVE';
126     }
127
128     $self->revmap_fields(
129       hostname     => \( $self->server ),
130       port         => \( $self->port ),
131       storename    => \( $self->storename ),
132       keyfile      => \( $self->keyfile ),
133       addrnum      => \$addrnum,
134       result       => \$result,
135       cardNumber   => 'card_number',
136       cardExpMonth => \$month,
137       cardExpYear  => \$year,
138     );
139
140     my $lperl = new LPERL;
141     my $action = $content{action};
142
143     $self->required_fields(qw/
144       hostname port storename keyfile amount cardNumber cardExpMonth cardExpYear
145     /);
146
147     my %post_data = $self->get_fields(qw/
148       hostname port storename keyfile
149       result
150       amount cardNumber cardExpMonth cardExpYear
151       name email phone address city state zip country
152     /);
153
154     warn "$_ => $post_data{$_}\n" foreach keys %post_data;
155
156     my %response;
157     {
158       local($^W)=0;
159       %response = $lperl->$action(\%post_data);
160     }
161
162     if ( $response{'statusCode'} == 0 ) {
163       $self->is_success(0);
164       $self->result_code('');
165       if ( exists($response{'statusMessage'})
166            && defined($response{'statusMessage'}) ) { # "normal" error
167         $self->error_message($response{'statusMessage'});
168       } else { # "should not happen" error (should this die/croak?)
169         $self->error_message("No statusMessage returned!  Response follows:".
170           join(' / ', map { "$_=>".$response{$_} } keys %response )           );
171       }
172     } else {
173       $self->is_success(1);
174       $self->result_code($response{'AVSCode'});
175       $self->authorization($response{'trackingID'});
176 #      $self->order_number($response{'neworderID'});
177     }
178
179 }
180
181 1;
182 __END__
183
184 =head1 NAME
185
186 Business::OnlinePayment::LinkPoint - LinkPoint backend for Business::OnlinePayment
187
188 =head1 SYNOPSIS
189
190   use Business::OnlinePayment;
191
192   my $tx = new Business::OnlinePayment( 'LinkPoint',
193     'storename' => 'your_store_number',
194     'keyfile'   => '/path/to/keyfile.pem',
195   );
196
197   $tx->content(
198       type           => 'VISA',
199       action         => 'Normal Authorization',
200       description    => 'Business::OnlinePayment test',
201       amount         => '49.95',
202       invoice_number => '100100',
203       customer_id    => 'jsk',
204       name           => 'Jason Kohles',
205       address        => '123 Anystreet',
206       city           => 'Anywhere',
207       state          => 'UT',
208       zip            => '84058',
209       email          => 'ivan-linkpoint@420.am',
210       card_number    => '4007000000027',
211       expiration     => '09/99',
212   );
213   $tx->submit();
214
215   if($tx->is_success()) {
216       print "Card processed successfully: ".$tx->authorization."\n";
217   } else {
218       print "Card was rejected: ".$tx->error_message."\n";
219   }
220
221 =head1 SUPPORTED TRANSACTION TYPES
222
223 =head2 Visa, MasterCard, American Express, JCB, Discover/Novus, Carte blanche/Diners Club
224
225 =head1 DESCRIPTION
226
227 For detailed information see L<Business::OnlinePayment>.
228
229 =head1 COMPATIBILITY
230
231 This module implements an interface to the LinkPoint Perl Wrapper
232 http://www.linkpoint.com/product_solutions/internet/lperl/lperl_main.html
233
234 Version 0.2 of this module has been updated for the LinkPoint Perl Wrapper
235 version 2.6.
236
237 =head1 BUGS
238
239 =head1 AUTHOR
240
241 Ivan Kohler <ivan-linkpoint@420.am>
242
243 Based on Busienss::OnlinePayment::AuthorizeNet written by Jason Kohles.
244
245 =head1 SEE ALSO
246
247 perl(1), L<Business::OnlinePayment>.
248
249 =cut
250