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