1 package Business::OnlinePayment::LinkPoint;
4 use vars qw($VERSION @ISA $DEBUG @EXPORT @EXPORT_OK);
6 use Business::OnlinePayment;
8 @ISA = qw(Business::OnlinePayment);
10 $VERSION = eval $VERSION; # modperlstyle: convert the string into a number
13 use lpperl; #3; #lpperl.pm from LinkPoint
14 $LPPERL::VERSION =~ /^(\d+\.\d+)/
15 or die "can't parse lpperl.pm version: $LPPERL::VERSION";
16 die "lpperl.pm minimum version 3 required\n" unless $1 >= 3;
21 #$self->server('staging.linkpt.net');
22 $self->server('secure.linkpt.net');
25 $self->build_subs(qw(order_number avs_code));
32 my %content = $self->content();
35 my %actions = ('normal authorization' => 'SALE',
36 'authorization only' => 'PREAUTH',
38 'post authorization' => 'POSTAUTH',
41 $content{'action'} = $actions{lc($content{'action'})} || $content{'action'};
44 my %account_types = ('personal checking' => 'pc',
45 'personal savings' => 'ps',
46 'business checking' => 'bc',
47 'business savings' => 'bs',
49 $content{'account_type'} = $account_types{lc($content{'account_type'})}
50 || $content{'account_type'};
52 # stuff it back into %content
53 $self->content(%content);
59 #no warnings; #not 5.005
61 eval "sub $_ { my \$self = shift; if(\@_) { \$self->{$_} = shift; } return \$self->{$_}; }";
68 my %content = $self->content();
70 $content{$map{$_}} = $content{$_};
72 $self->content(%content);
77 my %content = $self->content();
79 # warn "$_ = ". ( ref($map{$_})
81 # : $content{$map{$_}} ). "\n";
82 $content{$_} = ref($map{$_})
86 $self->content(%content);
90 my($self,@fields) = @_;
92 my %content = $self->content();
94 foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
103 my %content = $self->content;
106 unless ( $content{action} eq 'POSTAUTH'
107 || ( $content{'action'} =~ /^(CREDIT|VOID)$/
108 && exists $content{'order_number'} )
109 || $self->transaction_type() =~ /^e?check$/i
112 if ( $self->transaction_type() =~
113 /^(cc|visa|mastercard|american express|discover)$/i
116 Carp::croak("LinkPoint can't handle transaction type: ".
117 $self->transaction_type());
120 $content{'expiration'} =~ /^(\d+)\D+\d*(\d{2})$/
121 or croak "unparsable expiration $content{expiration}";
123 ( $month, $year ) = ( $1, $2 );
124 $month = '0'. $month if $month =~ /^\d$/;
127 $content{'address'} =~ /^(\d+)\s/;
130 my $result = $content{'result'};
131 if ( $self->test_transaction) {
133 #$self->server('staging.linkpt.net');
138 #strip phone numbers of non-digits for ACH/echeck
139 #as per undocumented suggestion from LinkPoint
140 if ( $self->transaction_type =~ /^e?check$/i ) {
141 foreach my $field (qw( phone fax )) {
142 $content{$field} =~ s/\D//g;
145 # stuff it back into %content
146 $self->content(%content);
148 $self->revmap_fields(
149 host => \( $self->server ),
150 port => \( $self->port ),
151 #storename => \( $self->storename ),
152 configfile => \( $self->storename ),
153 keyfile => \( $self->keyfile ),
155 chargetotal => 'amount',
157 addrnum => \$addrnum,
158 oid => 'order_number',
160 userid => 'customer_id',
161 ponumber => 'invoice_number',
162 comments => 'description',
163 #reference_number => 'reference_number',
165 cardnumber => 'card_number',
166 cardexpmonth => \$month,
167 cardexpyear => \$year,
169 bankname => 'bank_name',
170 bankstate => 'bank_state',
171 routing => 'routing_code',
172 account => 'account_number',
173 accounttype => 'account_type',
174 name => 'account_name',
176 dlstate => 'state_id_state',
179 my $lperl = new LPPERL;
181 my @required_fields = qw(host port configfile keyfile amount);
182 if ($self->transaction_type() =~ /^(cc|visa|mastercard|american express|discover)$/i) {
183 push @required_fields, qw(cardnumber cardexpmonth cardexpyear);
184 }elsif ($self->transaction_type() =~ /^e?check$/i) {
185 push @required_fields, qw(
186 dl dlstate routing account accounttype bankname bankstate name
189 $self->required_fields(@required_fields);
191 my %post_data = $self->get_fields(qw/
192 host port configfile keyfile
194 chargetotal cardnumber cardexpmonth cardexpyear
195 name company email phone fax addrnum city state zip country
197 dl dlstate routing account accounttype bankname bankstate name void
201 $post_data{'ordertype'} = $content{action};
203 #docs disagree with lpperl.pm here
204 $post_data{'voidcheck'} = 1
205 if $self->transaction_type() =~ /^e?check$/i
206 && $post_data{'ordertype'} =~ /^VOID$/;
208 if ( $content{'cvv2'} ) {
209 $post_data{cvmindicator} = 'provided';
210 $post_data{cvmvalue} = $content{'cvv2'};
214 warn "$_ => $post_data{$_}\n" foreach keys %post_data;
215 $post_data{debug} = 'true';
218 $post_data{'cargs'} = '-k -m 300 -s -S' if $self->test_transaction;
220 # avoid some uninitialized warnings in lpperl.pm
221 foreach (qw(webspace debug debugging)) { $post_data{$_} ||= '' }
226 # %response = $lperl->$action(\%post_data);
228 my %response = $lperl->curl_process(\%post_data);
231 warn "$_ => $response{$_}\n" for keys %response;
234 if ( $response{'r_approved'} eq 'APPROVED' ) {
235 $self->is_success(1);
236 $self->result_code($response{'r_code'});
237 $self->authorization($response{'r_ref'});
238 $self->order_number($response{'r_ordernum'});
239 $self->avs_code($response{'r_avs'});
241 $self->is_success(0);
242 $self->result_code('');
243 if ( $response{'r_error'} =~ /\S/ ) {
244 $self->error_message($response{'r_error'});
246 $self->error_message($response{'r_approved'}); # no r_error for checks
257 Business::OnlinePayment::LinkPoint - LinkPoint (Cardservice) backend for Business::OnlinePayment
261 use Business::OnlinePayment;
263 my $tx = new Business::OnlinePayment( 'LinkPoint',
264 'storename' => 'your_store_number',
265 'keyfile' => '/path/to/keyfile.pem',
270 action => 'Normal Authorization',
271 description => 'Business::OnlinePayment test',
273 invoice_number => '100100',
274 customer_id => 'jsk',
275 name => 'Jason Kohles',
276 address => '123 Anystreet',
280 email => 'ivan-linkpoint@420.am',
281 card_number => '4007000000027',
282 expiration => '09/99',
286 if($tx->is_success()) {
287 print "Card processed successfully: ".$tx->authorization."\n";
289 print "Card was rejected: ".$tx->error_message."\n";
292 =head1 SUPPORTED TRANSACTION TYPES
294 =head2 Visa, MasterCard, American Express, JCB, Discover/Novus, Carte blanche/Diners Club
298 For detailed information see L<Business::OnlinePayment>.
302 This module implements an interface to the LinkPoint Perl Wrapper "lpperl",
303 which you need to download and install separately.
304 http://www.linkpoint.com/product_solutions/internet/lperl/lperl_main.html
305 http://www.linkpoint.com/viewcart/down_index.htm
307 Versions 0.4 and on of this module support the LinkPoint Perl Wrapper version
314 Ivan Kohler <ivan-linkpoint@420.am>
316 Contributions from Mark D. Anderson <mda@discerning.com>
318 Echeck work by Jeff Finucane <jeff@cmh.net>
320 Based on Busienss::OnlinePayment::AuthorizeNet written by Jason Kohles.
324 perl(1), L<Business::OnlinePayment>.