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