1 package Business::OnlinePayment;
10 $VERSION = eval $VERSION; # modperlstyle: convert the string into a number
12 # Remember subclasses we have "wrapped" submit() with _pre_submit()
13 my %Presubmit_Added = ();
16 authorization => undef,
17 error_message => undef,
18 failure_status => undef,
19 fraud_detect => undef,
21 maximum_risk => undef,
27 server_response => undef,
28 test_transaction => undef,
29 transaction_type => undef,
33 my($class,$processor,%data) = @_;
35 Carp::croak("unspecified processor") unless $processor;
37 my $subclass = "${class}::$processor";
38 if(!defined(&$subclass)) {
40 Carp::croak("unknown processor $processor ($@)") if $@;
43 my $self = bless {processor => $processor}, $subclass;
44 $self->build_subs(keys %fields);
46 if($self->can("set_defaults")) {
47 $self->set_defaults();
52 my $value = $data{$_};
54 $self->build_subs($key);
58 # "wrap" submit with _pre_submit only once
59 unless ( $Presubmit_Added{$subclass} ) {
60 my $real_submit = $subclass->can('submit');
62 no warnings 'redefine';
65 *{"${subclass}::submit"} = sub {
67 return unless $self->_pre_submit(@_);
68 return $real_submit->($self, @_);
76 my ($self, $risk_transaction) = @_;
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()) {
86 $self->error_message('Excessive risk from risk management');
89 $self->error_message('Error in risk detection stage: ' . $risk_transaction->error_message);
97 my $fraud_detection = $self->fraud_detect();
99 # early return if user does not want optional risk mgt
100 return 1 unless $fraud_detection;
102 # Search for an appropriate FD module
103 foreach my $subclass ( q(Business::OnlinePayment::) . $fraud_detection,
104 q(Business::FraudDetect::) . $fraud_detection) {
106 if (!defined(&$subclass)) {
107 eval "use $subclass";
109 Carp::croak("serious problem loading fraud_detection module ($@)") unless
110 $@ =~ m/^Can\'t locate/;
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();
117 $risk_tx->_glean_parameters_from_parent($self);
118 return $self->_risk_detect($risk_tx);
122 return 1; # BUG?: success if fraud_detection module not found!
126 my($self,%params) = @_;
129 if($params{'type'}) { $self->transaction_type($params{'type'}); }
130 %{$self->{'_content'}} = %params;
132 return exists $self->{'_content'} ? %{$self->{'_content'}} : ();
135 sub required_fields {
136 my($self,@fields) = @_;
139 my %content = $self->content();
141 push(@missing, $_) unless exists $content{$_};
144 Carp::croak("missing required field(s): " . join(", ", @missing) . "\n")
149 my($self, @fields) = @_;
151 my %content = $self->content();
154 #foreach(@fields) { $new{$_} = $content{$_}; }
156 map { $_ => $content{$_} } grep defined $content{$_}, @fields;
162 my %content = $self->content();
163 foreach( keys %map ) {
164 $content{$map{$_}} = $content{$_};
166 $self->content(%content);
172 Carp::croak("Processor subclass did not override submit function");
178 my %content = $self->content();
180 foreach(sort keys %content) {
181 $dump .= "$_ = $content{$_}\n";
186 # didnt use AUTOLOAD because Net::SSLeay::AUTOLOAD passes right to
187 # AutoLoader::AUTOLOAD, instead of passing up the chain
192 next if($self->can($_));
193 eval "sub $_ { my \$self = shift; if(\@_) { \$self->{$_} = shift; } return \$self->{$_}; }";
203 Business::OnlinePayment - Perl extension for online payment processing
207 use Business::OnlinePayment;
209 my $transaction = new Business::OnlinePayment($processor, %processor_info);
210 $transaction->content(
213 card_number => '1234123412341238',
214 expiration => '0100',
215 name => 'John Q Doe',
217 $transaction->submit();
219 if($transaction->is_success()) {
220 print "Card processed successfully: ", $transaction->authorization(), "\n";
222 print "Card was rejected: ", $transaction->error_message(), "\n";
227 Business::OnlinePayment is a generic module for processing payments
228 through online credit card processors, electronic cash systems, etc.
230 =head1 METHODS AND FUNCTIONS
232 =head2 new($processor, %processor_options);
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.
243 =head2 content(%content);
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:
254 Transaction type, supported types are:
255 Visa, MasterCard, American Express, Discover, Check (not all
256 processors support all these transaction types).
260 Your login name to use for authentication to the online processor.
264 Your password to use for authentication to the online processor.
268 What to do with the transaction (currently available are: Normal
269 Authorization, Authorization Only, Credit, Post Authorization)
273 A description of the transaction (used by some processors to send
274 information to the client, normally not a required field).
278 The amount of the transaction, most processors don't want dollar signs
279 and the like, just a floating point number.
281 =item * invoice_number
283 An invoice number, for your use and not normally required, many
284 processors require this field to be a numeric only field.
288 A customer identifier, again not normally required.
292 The customers name, your processor may not require this.
296 The customers address (your processor may not require this unless you
297 are requiring AVS Verification).
301 The customers city (your processor may not require this unless you are
302 requiring AVS Verification).
306 The customers state (your processor may not require this unless you
307 are requiring AVS Verification).
311 The customers zip code (your processor may not require this unless you
312 are requiring AVS Verification).
320 Customer's phone number.
324 Customer's fax number.
328 Customer's email address.
332 Credit card number (obviously not required for non-credit card
337 Credit card expiration (obviously not required for non-credit card
340 =item * account_number
342 Bank account number for electronic checks or electronic funds transfer.
346 Bank's routing code for electronic checks or electronic funds transfer.
350 Bank's name for electronic checks or electronic funds transfer.
356 Submit the transaction to the processor for completion
360 Returns true if the transaction was submitted successfully, false if
361 it failed (or undef if it has not been submitted yet).
363 =head2 failure_status();
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).
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
376 =head2 result_code();
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
383 =head2 test_transaction();
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).
391 =head2 require_avs();
393 Providing a true argument to this module will turn on address
394 verification (if the processor supports it).
396 =head2 transaction_type();
398 Retrieve the transaction type (the 'type' argument to contents();).
399 Generally only used internally, but provided in case it is useful.
401 =head2 error_message();
403 If the transaction has been submitted but was not accepted, this
404 function will return the provided error message (if any) that the
407 =head2 authorization();
409 If the transaction has been submitted and accepted, this function will
410 provide you with the authorization code that the processor returned.
414 Retrieve or change the processor submission server address (CHANGE AT
419 Retrieve or change the processor submission port (CHANGE AT YOUR OWN RISK).
423 Retrieve or change the processor submission path (CHANGE AT YOUR OWN RISK).
427 Jason Kohles, email@jasonkohles.com
429 (v3 rewrite) Ivan Kohler <ivan-business-onlinepayment@420.am>
431 Phil Lobbes E<lt>phil at perkpartners dot comE<gt>
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.
441 http://420.am/business-onlinepayment/
443 For verification of credit card checksums, see L<Business::CreditCard>.