New modules for preCharge
[Business-OnlinePayment.git] / OnlinePayment.pm
1 package Business::OnlinePayment;
2
3 use strict;
4 use vars qw($VERSION); # @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
5 use Carp;
6 use Symbol;
7
8 require 5.005;
9 ##use Data::Dumper;
10
11 #require Exporter;
12
13 #@ISA = (); #qw(Exporter AutoLoader);
14 #@EXPORT = qw();
15 #@EXPORT_OK = qw();
16
17 $VERSION = '3.00_04';
18 sub VERSION { #Argument "3.00_01" isn't numeric in subroutine entry
19   local($^W)=0;
20   UNIVERSAL::VERSION(@_);
21 }
22
23 my %fields = (
24     is_success       => undef,
25     failure_status   => undef,
26     result_code      => undef,
27     test_transaction => undef,
28     require_avs      => undef,
29     transaction_type => undef,
30     error_message    => undef,
31     authorization    => undef,
32     server           => undef,
33     port             => undef,
34     path             => undef,
35     risk_management  => undef,
36     risk_management_params => undef,          
37     server_response  => undef,
38     maximum_risk     => undef,
39 );
40
41
42 sub new {
43
44     my($class,$processor,%data) = @_;
45
46     Carp::croak("unspecified processor") unless $processor;
47
48     my $subclass = "${class}::$processor";
49     if(!defined(&$subclass)) {
50         eval "use $subclass";
51         Carp::croak("unknown processor $processor ($@)") if $@;
52     }
53
54     my $self = bless {processor => $processor}, $subclass;
55     $self->build_subs(keys %fields);
56
57     if($self->can("set_defaults")) {
58         $self->set_defaults();
59     }
60
61     foreach(keys %data) {
62         my $key = lc($_);
63         my $value = $data{$_};
64         $key =~ s/^\-//;
65         $self->build_subs($key);
66         $self->$key($value);
67     }
68
69     {
70         no strict 'refs';
71         no warnings 'redefine';
72         my $submit = qualify_to_ref('submit', $subclass);
73         $self->{_child_submit} = \&$submit;
74         *{"${subclass}::submit"} = sub {
75             my $self = shift;
76             $self->_pre_submit(@_);
77
78         }
79     }
80
81     return $self;
82 }
83
84 sub _risk_detect {
85     my ($self, $risk_transaction) = @_;
86
87     my %parent_content = $self->content();
88     $parent_content{action} = 'Fraud Detect';
89     $risk_transaction->content( %parent_content ); 
90     $risk_transaction->submit();
91     if ($risk_transaction->is_success()) {
92         if ( $risk_transaction->risk_level <= $self->maximum_risk()) {
93             $self->{_child_submit}->($self);
94         } else {
95             $self->is_success(0);
96             $self->error_message('Excessive risk from risk management');
97         }
98     } else {
99         $self->error_message('Error in risk detection stage: ' .  $risk_transaction->error_message);
100         $self->is_success(0);
101     }
102 }
103
104 sub _pre_submit{
105     my ($self) = @_;
106     my $risk_detection = $self->risk_management();
107
108     #
109     # early return if user does not want optional risk mgt
110     #
111
112     return $self->{_child_submit}->($self,@_) unless $risk_detection && length $risk_detection;
113
114     #
115
116     # Search for an appropriate FD module
117     #
118     
119     foreach my $subclass ( q(Business::OnlinePayment::) . $risk_detection,
120                            q(Business::FraudDetect::).$risk_detection) {
121
122         if (!defined(&$subclass)) {
123             eval "use $subclass";
124             if ($@) {
125                 Carp::croak("serious problem loading risk_detection module ($@)") unless
126                     $@ =~ m/^Can\'t locate/;
127             } else {
128                 my $risk_tx = bless ( { processor => $risk_detection } , $subclass );
129                 $risk_tx->build_subs(keys %fields);
130                 if ($risk_tx->can('set_defaults')) {
131                     $risk_tx->set_defaults();
132                 }
133                 my %risk_params = %{$self->risk_management_params()};
134                 foreach my $key ( keys %risk_params ) {
135                     my $value = $risk_params{$key};
136                     $key = lc($key);
137                     $key =~ s/^\-//;
138                     $risk_tx->build_subs($key);
139                     $risk_tx->$key($value);
140                 }
141                 return $self->_risk_detect($risk_tx);
142             }
143         }
144     }
145 };
146
147 sub content {
148     my($self,%params) = @_;
149
150     if(%params) {
151         if($params{'type'}) { $self->transaction_type($params{'type'}); }
152         %{$self->{'_content'}} = %params;
153     }
154     return %{$self->{'_content'}};
155 }
156
157 sub required_fields {
158     my($self,@fields) = @_;
159
160     my %content = $self->content();
161     foreach(@fields) {
162         Carp::croak("missing required field $_") unless exists $content{$_};
163     }
164 }
165
166 sub get_fields {
167     my($self, @fields) = @_;
168
169     my %content = $self->content();
170
171     #my %new = ();
172     #foreach(@fields) { $new{$_} = $content{$_}; }
173     #return %new;
174     map { $_ => $content{$_} } grep defined $content{$_}, @fields;
175 }
176
177 sub remap_fields {
178     my($self,%map) = @_;
179
180     my %content = $self->content();
181     foreach( keys %map ) {
182         $content{$map{$_}} = $content{$_};
183     }
184     $self->content(%content);
185 }
186
187 sub submit {
188     my($self) = @_;
189
190     Carp::croak("Processor subclass did not override submit function");
191 }
192
193 sub dump_contents {
194     my($self) = @_;
195
196     my %content = $self->content();
197     my $dump = "";
198     foreach(keys %content) {
199         $dump .= "$_ = $content{$_}\n";
200     }
201     return $dump;
202 }
203
204 # didnt use AUTOLOAD because Net::SSLeay::AUTOLOAD passes right to
205 # AutoLoader::AUTOLOAD, instead of passing up the chain
206 sub build_subs {
207     my $self = shift;
208     no warnings 'redefine';
209     foreach(@_) {
210         eval "sub $_ { my \$self = shift; if(\@_) { \$self->{$_} = shift; } return \$self->{$_}; }";
211     }
212 }
213
214 1;
215
216 __END__
217
218 =head1 NAME
219
220 Business::OnlinePayment - Perl extension for online payment processing
221
222 =head1 SYNOPSIS
223
224   use Business::OnlinePayment;
225
226   my $transaction = new Business::OnlinePayment($processor, %processor_info);
227   $transaction->content(
228                         type       => 'Visa',
229                         amount     => '49.95',
230                         cardnumber => '1234123412341238',
231                         expiration => '0100',
232                         name       => 'John Q Doe',
233                        );
234   $transaction->submit();
235
236   if($transaction->is_success()) {
237     print "Card processed successfully: ".$transaction->authorization()."\n";
238   } else {
239     print "Card was rejected: ".$transaction->error_message()."\n";
240   }
241
242 =head1 DESCRIPTION
243
244 Business::OnlinePayment is a generic module for processing payments through
245 online credit card processors, electronic cash systems, etc.
246
247 =head1 METHODS AND FUNCTIONS
248
249 =head2 new($processor, %processor_options);
250
251 Create a new Business::OnlinePayment object, $processor is required, and defines the online processor to use.  If necessary, processor options can be specified, currently supported options are 'Server', 'Port', and 'Path', which specify how to find the online processor (https://server:port/path), but individual processor modules should supply reasonable defaults for this information, override the defaults only if absolutely necessary (especially path), as the processor module was probably written with a specific target script in mind.
252
253 =head2 content(%content);
254
255 The information necessary for the transaction, this tends to vary a little depending on the processor, so we have chosen to use a system which defines specific fields in the frontend which get mapped to the correct fields in the backend.  The currently defined fields are:
256
257 =over 4
258
259 =item * type
260
261 Transaction type, supported types are:
262 Visa, MasterCard, American Express, Discover, Check (not all processors support all these transaction types).
263
264 =item * login
265
266 Your login name to use for authentication to the online processor.
267
268 =item * password
269
270 Your password to use for authentication to the online processor.
271
272 =item * action
273
274 What to do with the transaction (currently available are: Normal Authorization, Authorization Only, Credit, Post Authorization)
275
276 =item * description
277
278 A description of the transaction (used by some processors to send information to the client, normally not a required field).
279
280 =item * amount
281
282 The amount of the transaction, most processors dont want dollar signs and the like, just a floating point number.
283
284 =item * invoice_number
285
286 An invoice number, for your use and not normally required, many processors require this field to be a numeric only field.
287
288 =item * customer_id
289
290 A customer identifier, again not normally required.
291
292 =item * name
293
294 The customers name, your processor may not require this.
295
296 =item * address
297
298 The customers address (your processor may not require this unless you are requiring AVS Verification).
299
300 =item * city
301
302 The customers city (your processor may not require this unless you are requiring AVS Verification).
303
304 =item * state
305
306 The customers state (your processor may not require this unless you are requiring AVS Verification).
307
308 =item * zip
309
310 The customers zip code (your processor may not require this unless you are requiring AVS Verification).
311
312 =item * country
313
314 Customer's country.
315
316 =item * phone
317
318 Customer's phone number.
319
320 =item * fax
321
322 Customer's fax number.
323
324 =item * email
325
326 Customer's email address.
327
328 =item * card_number
329
330 Credit card number (obviously not required for non-credit card transactions).
331
332 =item * exp_date
333
334 Credit card expiration (obviously not required for non-credit card transactions).
335
336 =item * account_number
337
338 Bank account number for electronic checks or electronic funds transfer.
339
340 =item * routing_code
341
342 Bank's routing code for electronic checks or electronic funds transfer.
343
344 =item * bank_name
345
346 Bank's name for electronic checks or electronic funds transfer.
347
348 =back
349
350 =head2 submit();
351
352 Submit the transaction to the processor for completion
353
354 =head2 is_success();
355
356 Returns true if the transaction was submitted successfully, false if it failed (or undef if it has not been submitted yet).
357
358 =head2 failure_status();
359
360 If the transactdion failed, it can optionally return a specific failure status
361 (normalized, not gateway-specific).  Currently defined statuses are: "expired",
362 "nsf" (non-sufficient funds), "stolen", "pickup", "blacklisted" and
363 "declined" (card/transaction declines only, not other errors).
364
365 Note that (as of Aug 2006) this is only supported by some of the newest
366 processor modules, and that, even if supported, a failure status is an entirely
367 optional field that is only set for specific kinds of failures.
368
369 =head2 result_code();
370
371 Returns the precise result code that the processor returned, these are normally one letter codes that don't mean much unless you understand the protocol they speak, you probably don't need this, but it's there just in case.
372
373 =head2 test_transaction();
374
375 Most processors provide a test mode, where submitted transactions will not actually be charged or added to your batch, calling this function with a true argument will turn that mode on if the processor supports it, or generate a fatal error if the processor does not support a test mode (which is probably better than accidentally making real charges).
376
377 =head2 require_avs();
378
379 Providing a true argument to this module will turn on address verification (if the processor supports it).
380
381 =head2 transaction_type();
382
383 Retrieve the transaction type (the 'type' argument to contents();).  Generally only used internally, but provided in case it is useful.
384
385 =head2 error_message();
386
387 If the transaction has been submitted but was not accepted, this function will return the provided error message (if any) that the processor returned.
388
389 =head2 authorization();
390
391 If the transaction has been submitted and accepted, this function will provide you with the authorization code that the processor returned.
392
393 =head2 server();
394
395 Retrieve or change the processor submission server address (CHANGE AT YOUR OWN RISK).
396
397 =head2 port();
398
399 Retrieve or change the processor submission port (CHANGE AT YOUR OWN RISK).
400
401 =head2 path();
402
403 Retrieve or change the processor submission path (CHANGE AT YOUR OWN RISK).
404
405 =head1 AUTHORS
406
407 Jason Kohles, email@jasonkohles.com
408
409 (v3 rewrite) Ivan Kohler <ivan-business-onlinepayment@420.am>
410
411 =head1 DISCLAIMER
412
413 THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
414 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
415 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
416
417
418 =head1 SEE ALSO
419
420 http://420.am/business-onlinepayment/
421
422 For verification of credit card checksums, see L<Business::CreditCard>.
423
424 =cut