complete rewrite, version 0.10
[Business-OnlineThirdPartyPayment.git] / OnlineThirdPartyPayment.pm
index b642ffd..8ada8d5 100644 (file)
@@ -7,28 +7,21 @@ use base qw(Business::OnlinePayment);
 
 require 5.005;
 
-$VERSION = '3.00_09';
+$VERSION = 0.10;
 $VERSION = eval $VERSION; # modperlstyle: convert the string into a number
 
 my %fields = (
-    authorization        => undef,
-    error_message        => undef,
-    failure_status       => undef,
-    fraud_detect         => undef,  # unsupported
-    is_success           => undef,
-    maximum_risk         => undef,  # unsupported
-    path                 => undef,
-    port                 => undef,
-    require_avs          => undef,
-    result_code          => undef,
-    server               => undef,
-    server_response      => undef,
-    test_transaction     => undef,
-    transaction_type     => undef,
-    fraud_score          => undef,  # unsupported
-    fraud_transaction_id => undef,  # unsupported
-    popup_url            => undef,
-    collectitems         => undef,
+    is_success          => undef,
+    token               => undef,
+    redirect            => undef,
+    post_params         => undef,
+    statustext          => undef,
+    order_number        => undef,
+    authorization       => undef,
+    error_message       => undef,
+    test_transaction    => undef,
+    return_url          => undef,
+    cancel_url          => undef,
 );
 
 sub new {
@@ -58,127 +51,177 @@ sub new {
     return $self;
 }
 
-sub reference {
-    my($self) = @_;
-
-    croak("Processor subclass did not override reference function");
-}
-
 1;
 
 __END__
 
 =head1 NAME
 
-Business::OnlineThirdPartyPayment - Perl extension for third party web page based online payment processing
+Business::OnlineThirdPartyPayment - Common interface to browser-based 
+online payment processors
 
 =head1 SYNOPSIS
 
   use Business::OnlineThirdPartyPayment;
+  use CGI;
 
-  my $transaction =
-    new Business::OnlineThirdPartyPayment($processor, %processor_info);
-  $transaction->content(
-                        type        => 'CC',
-                        action      => 'Authorization Only',
-                        amount      => '49.95',
-                        reference   => '3735928559',
-                       );
-  $transaction->submit();
-  
-  if($transaction->is_success()) {
-    print "Success!  Redirect browser to ". $transaction->popup_url();
+  my %processor_info = (
+    'return_url'  => 'https://www.example.com/payment/return',
+    'cancel_url'  => 'https://www.example.com/payment/cancel',
+    # ... other processor-specific values
+  );
+
+  my $txn = Business::OnlineThirdPartyPayment->new('MyBank', %processor_info);
+  # start a payment
+  $txn->create( customer_id     => 4030,
+                invoice_number  => 10318,
+                amount          => 49.95,
+                currency        => 'CAD',
+                description     => 'Internet Services',
+              );
+
+  if ( $txn->is_success} ) {
+    store_payment_id($txn->token); # keep it somewhere
+    print CGI->redirect( $txn->redirect );
   } else {
-    print "Card was rejected: ", $transaction->error_message(), "\n";
+    die $txn->error_message;
   }
 
-  #when the provider calls us back via HTTP
-  use CGI;
-  my $cgi = new CGI;  #initialized to current page
+  ...
+  # then, at /payment/return...
+  my $txn = Business::OnlineThirdPartyPayment->new('MyBank', %processor_info);
+  $txn->token( get_payment_id($cgi) ); # probably from a session cookie
+  my %params = $cgi->Vars;
+
+  $txn->execute(%params);
   
-  my $reference = $transaction->reference($cgi->Vars);
-  $transaction->content(
-                        type        => 'CC',
-                        action      => 'Post Authorization',
-                        reference   => $reference,
-                       );
-  $transaction->submit();
-  if($transaction->is_success()) {
-    print "Card processed scucessfully: ", $transaction->authorization(), "\n";
+  if ( $txn->is_success ) {
+    store_payment_success($txn->order_number, $txn->authorization);
+    print "Your payment was successful!\n";
   } else {
-    print "Card was rejected: ", $transaction->error_message(), "\n";
+    store_payment_failure($txn->order_number, $txn->error_message);
+    print "Your payment failed.\n";
   }
 
-  
-
 =head1 DESCRIPTION
 
 Business::OnlineThirdPartyPayment is a generic module for processing payments
 through online credit card processors, electronic cash systems, etc. through
-which the payors web browser is redirected.  It is a subclass of
-L<Business::OnlinePayment>
+which the payer's web browser is redirected.
+
+=head1 METHODS
 
-=head1 METHODS AND FUNCTIONS
+=head2 new($module, %processor_options)
 
-=head2 new($processor, %processor_options);
+Class method.  Create a Business::OnlineThirdPartyPayment object.
+$module is required, and defines the gateway module to use.  The 
+other options are processor-specific, but should always include:
 
-Create a new Business::OnlineThirdPartyPayment 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.
+=over 4
+
+=item return_url - The callback URL to redirect the user to after completing 
+a payment.
+
+=item cancel_url - The URL to redirect the user to if they choose not to 
+complete the payment.
+
+=back
 
-=head2 content(%content);
+=head2 create(%content)
 
-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.  Currently defined fields are:
+Tell the gateway module to start a transaction.  This may involve 
+communicating with the gateway, or it may happen entirely locally.
+%content is a hash containing some of the following:
 
-=head3 PROCESSOR FIELDS
+=head3 TRANSACTION FIELDS
 
 =over 4
 
-=item * reference
+=item amount - The amount of the transaction, as a decimal number. Required.
+
+=item description - A description of the purchase. Required.
+
+=item invoice_number - Your invoice number, if this payment is associated
+with a specific invoice.
+
+=item currency - Currency, specified as an ISO 4217 three-letter code, such 
+as USD, CAD, EUR, AUD, DKK, GBP, JPY, NZD, etc.
+
+=item customer_id - The customer number, if any.
+
+=item email - Customer's email address.
 
-A unique reference for this transaction.
+=item customer_ip - IP address from which the transaction originated.
 
 =back
 
 For additional fields, see L<Business::OnlinePayment> and the specific
 processor module used.
 
-=head2 submit();
+C<create()> sets properties of the transaction object to indicate the 
+result.  These will always include:
 
-Submit the transaction to the processor for completion
+=over 4
+
+=item is_success - 1 if the transaction was created successfully, 0 
+otherwise.
+
+=item error_message - a text description of any error that occurred.
+Since the payer hasn't provided a payment account or any other 
+information at this stage, this is probably not meaningful to them.
+
+=item token - a reference string that will be used to identify
+this transaction later.  If is_success is true, you I<must> store this 
+value in your merchant system and pass it to execute() later.  Merchant 
+systems should allow at least 256 characters for this string.
+
+=item statustext - a freeform text field for any state information 
+that the gateway needs to receive to complete the transaction.
 
-=head2 is_success();
+=item redirect - a URL to redirect the payer to.
 
-Returns true if the transaction was submitted successfully, false if
-it failed (or undef if it has not been submitted yet).
+=item post_params - the content of an HTTP POST request to send to the 
+URL.  Since HTTP redirects can't include POST content, in this case the 
+front-end system must provide another way (a self-submitting form) to 
+induce the purchaser's browser to make the request.
 
-=head2 test_transaction();
+=back
+
+=head2 execute(%params)
+
+Complete the transaction.  This should be called from the web server
+(from 'return_url').  %params must contain any query parameters passed 
+in the redirect, and token should be set on the object.
 
-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).
+execute() will set the transaction fields to indicate the result:
+
+=over 4
+
+=item is_success: 1 if the payment was successful, 0 if it was not.
+
+=item error_message: An error message describing the reason for failure.
+Unlike the message returned from C<create()>, this probably is meaningful
+to the user, though the gateway may already have shown it to them.
+
+=item order_number: The transaction ID number assigned by the processor.
+
+=item authorization: The credit card or other authorization number 
+returned by the gateway.  This may be needed to refund the payment or 
+for other customer service issues.
+
+=back
+
+If C<is_success> is true, the merchant system should record this as 
+a successful payment and apply it to the customer's account.
 
 =head1 AUTHOR
 
-Jeff Finucane <business-onlinethirdpartypayment@weasellips>
+Mark Wells <mark@freeside.biz>, based in part on code by Jeff Finucane.
 
 =head1 COPYRIGHT
 
-Partially based on code from Business::OnlinePayment.
-
 Copyright (c) 1999-2004 Jason Kohles.
-Copyright (c) 2004 Ivan Kohler
-Copyright (c) 2007-2009 Freeside Internet Services, Inc.
+Copyright (c) 2007-2013 Freeside Internet Services, Inc.
 
 All rights reserved. This program is free software; you can redistribute
 it and/or modify it under the same terms as Perl itself.
@@ -193,6 +236,4 @@ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
 L<Business::OnlinePayment>, http://420.am/business-onlinepayment/
 
-For verification of credit card checksums, see L<Business::CreditCard>.
-
 =cut