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