initial import START
authorivan <ivan>
Thu, 1 Apr 2004 14:30:22 +0000 (14:30 +0000)
committerivan <ivan>
Thu, 1 Apr 2004 14:30:22 +0000 (14:30 +0000)
BusinessOnlinePayment.pm [new file with mode: 0644]

diff --git a/BusinessOnlinePayment.pm b/BusinessOnlinePayment.pm
new file mode 100644 (file)
index 0000000..63e8c96
--- /dev/null
@@ -0,0 +1,302 @@
+# Vend::Payment::BusinessOnlinePayment - Interchange wrapper for
+#                                        Business::OnlinePayment modules
+#
+# Copyright (C) 2004 Ivan Kohler.  All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+#
+# Ivan Kohler <ivan-interchange@420.am>
+
+package Vend::Payment::BusinessOnlinePayment;
+
+=head1 NAME
+
+Vend::Payment::BusinessOnlinePayment - Interchange wrapper for Business::OnlinePayment
+
+=head1 SYNOPSIS
+
+    &charge=onlinepayment
+
+        or
+
+    [charge mode=onlinepayment param1=value1 param2=value2]
+
+=head1 PREREQUISITES
+
+  Business::OnlinePayment
+  Business::OnlinePayment:: gateway module
+
+  See L<http://www.420.am/business-onlinepayment/> or 
+  L<http://search.cpan.org/search?query=Business%3A%3AOnlinePayment&mode=module>
+
+=head1 DESCRIPTION
+
+This is a wrapper around Business::OnlinePayment for Interchange.
+
+The Vend::Payment::BusinessOnlinePayment module implements the onlinepayment()
+routine for use with Interchange.  It is compatible on a call level with the
+other Interchange payment modules.  In theory (and even usually in practice)
+you could switch from another gateway to a Business::OnlinePayment supported
+gateway (or between different Business::OnlinePayment gateways) with a few
+configuration file changes.
+
+Business::OnlinePayment is a set of related Perl modules for processing online
+payments (credit cards, electronic checks, and other payment systems).  It
+provides a consistant interface for processing online payments, regardless of
+the gateway backend being used, in the same way that DBI provides an consistant
+interface to different databases.
+
+See L<http://www.420.am/business-onlinepayment/> for more information and
+supported gateways.
+
+It is hoped that a future version of Interchange will do all credit card
+processing through Business::OnlinePayment, but this is my no means
+guaranteed and the timeframe is unknown.  Think ALSA somewhere around
+Linux 2.2 and you've got the general idea.
+
+Currently this module is recommended for people with gateway processors
+unsupported by a native Interchange Vend::Payment:: module and for the
+adventurous.
+
+=head1 USAGE
+
+To enable this module, place this directive in C<interchange.cfg>:
+
+    Require module Vend::Payment::BusinessOnlinePayment
+
+This I<must> be in interchange.cfg or a file included from it.
+
+The mode can be named anything, but the C<gateway> parameter must be set
+to C<onlinepayment>. To make it the default payment gateway for all credit
+card transactions in a specific catalog, you can set in C<catalog.cfg>:
+
+    Variable   MV_PAYMENT_MODE  onlinepayment
+
+It uses several of the standard settings from Interchange payment. Any time
+we speak of a setting, it is obtained either first from the tag/call options,
+then from an Interchange order Route named for the mode, then finally a
+default global payment variable, For example, the C<setting> parameter would
+be specified by:
+
+    [charge mode=onlinepayment setting=value]
+
+or
+
+    Route onlinepayment setting value
+
+or 
+
+    Variable MV_PAYMENT_SETTING      value
+
+The following settings are available:
+
+=over 4
+
+=item processor
+
+Your Business::OnlinePayment processor.
+
+=item id
+
+Your Business::OnlinePayment login.
+
+=item secret
+
+Your Busienss::OnlinePayment password.
+
+=item transaction
+
+The type of transaction to be run. Valid values are:
+
+    Interchange         Business::OnlinePayment
+    ----------------    -----------------------
+        auth            Authorization Only
+        return          Credit
+        reverse
+        sale            Normal Authorization
+        settle          Post Authorization
+        void            Void
+
+=item test
+
+Set this true if you wish to operate in test mode.  Make sure to verify
+that your specific Business::OnlinePayment:: gateway module supports a
+test mode.
+
+=back
+
+In addition, any other processor options are passed to your gateway.  See
+the documentation for your specific Business::OnlinePayment:: gateway module
+for details on what options are required, if any.
+
+=head1 AUTHOR
+
+Ivan Kohler <ivan-interchange@420.am>
+
+=cut
+
+package Vend::Payment;
+use strict;
+use vars qw( $VERSION );
+use Business::OnlinePayment;
+
+$VERSION = '0.01';
+
+my $default_avs = q{You must enter the correct billing address of your credit }.
+                  q{card.  The bank returned the following error: %s};
+
+my $default_declined = "error: %s. Please call in your order or try again.";
+
+sub onlinepayment {
+  my ($user, $amount) = @_;
+
+  my $opt = {};
+  my $secret;
+
+  if ( ref($user) ) {
+    $opt = $user;
+    $user = $opt->{id};
+    $secret = $opt->{secret};
+  }
+
+  my $actual = $opt->{actual} || { map_actual() };
+
+  $user ||= charge_param('id')
+    or return ( MStatus => 'failure-hard',
+                MErrMsg => errmsg('No account id'),
+              );
+
+  $secret ||= charge_param('secret');
+
+  my $precision = $opt->{precision} || 2;
+
+  my $referer = $opt->{referer} || charge_param('referer');
+
+  $actual->{$_} = $opt->{$_}
+    foreach grep defined($opt->{$_}), qw(
+      order_id
+      auth_code
+      mv_credit_card_exp_month
+      mv_credit_card_exp_year
+      mv_credit_card_number
+    );
+
+  $actual->{mv_credit_card_exp_month} =~ s/\D//g;
+  $actual->{mv_credit_card_exp_year} =~ s/\D//g;
+  $actual->{mv_credit_card_exp_year} =~ s/\d\d(\d\d)/$1/;
+  $actual->{mv_credit_card_number} =~ s/\D//g;
+
+  my $exp = sprintf '%02d/%02d', $actual->{mv_credit_card_exp_month},
+                                 $actual->{mv_credit_card_exp_year};
+
+  my %ic2bop = (
+    'auth'    =>  'Authorization Only',
+    'return'  =>  'Credit',
+    #'reverse' =>
+    'sale'    =>  'Normal Authorization',
+    'settle'  =>  'Post Authorization',
+    'void'    =>  'Void',
+  );
+
+  my $action = $ic2bop{$opt->{transaction} || 'sale'};
+
+  $amount = $opt->{total_cost} if $opt->{total_cost};
+       
+  if ( ! $amount ) {
+    $amount = Vend::Interpolate::total_cost();
+    $amount = Vend::Util::round_to_frac_digits($amount, $precision);
+  }
+
+  my $order_id = gen_order_id($opt);
+
+  my $processor = charge_param('processor');
+
+  #processor options!
+  my %ignore = map { $_=>1 } qw(gateway processor id secret transaction );
+  my %options = map  { $_=>1 }
+                grep { !$ignore{$_} } (
+                                        keys(%$opt),
+                                        map { s/^MV_PAYMENT_//; lc($_); }
+                                          grep { /^MV_PAYMENT_/ }
+                                            keys %$main::Variable
+                                      );
+
+  my $transaction =
+    new Business::OnlinePayment ( $processor, %options );
+
+  $transaction->test_transaction($opt->{test} || charge_param('test'));
+
+  $actual->{$_} =~ s/[\n\r]//g foreach keys %$actual;
+
+  $transaction->content(
+    'type'            => 'CC',
+    'login'           => $user,
+    'password'        => $secret,
+    'action'          => $action,
+    #'description'
+    'amount'          => $amount,
+    'card_number'     => $actual->{mv_credit_card_number},
+    'expiration'      => $exp,
+    'cvv2'            => $actual->{cvv2},
+    'order_number'    => $actual->{order_id},
+    'auth_code'       => $actual->{auth_code},
+    #'recurring_billing'
+    'invoice_number'  => $actual->{mv_order_number},
+    #'customer_id'
+    'last_name'       => $actual->{b_lname},
+    'first_name'      => $actual->{b_fname},
+    'name'            => $actual->{b_fname}. ' '. $actual->{b_lname},
+    'company'         => $actual->{b_company},
+    'address'         => $actual->{b_address},
+    'city'            => $actual->{b_city},
+    'state'           => $actual->{b_state},
+    'zip'             => $actual->{b_zip},
+    'country'         => $actual->{b_country},
+    'ship_last_name'  => $actual->{lname},
+    'ship_first_name' => $actual->{fname},
+    'ship_name'       => $actual->{fname}. ' '. $actual->{lname},
+    'ship_company'    => $actual->{company},
+    'ship_address'    => $actual->{address},
+    'ship_city'       => $actual->{city},
+    'ship_state'      => $actual->{state},
+    'ship_zip'        => $actual->{zip},
+    'ship_country'    => $actual->{country},
+    'referer'         => $referer,
+    'email'           => $actual->{email},
+    'phone'           => $actual->{phone_day},
+  );
+
+  $transaction->submit();
+
+  my %result;
+  if ( $transaction->is_success() ) {
+
+    $result{MStatus} = 'success';
+    $result{'order-id'} = $transaction->order_number || $opt->{'order_id'};
+
+  } else {
+
+    $result{MStatus} = 'failure';
+    delete $result{'order-id'};
+
+    if ( 0 ) { #need a standard Business::OnlinePayment way to ask about AVS
+      $result{MErrMsg} = errmsg(
+        $opt->{'message_avs'} || $default_avs,
+        $transaction->error_message
+      )
+    } else {
+      $result{MErrMsg} = errmsg(
+        $opt->{'message_declined'} || "$processor $default_declined",
+         $transaction->error_message
+      );
+    }
+
+  }
+
+  return %result;
+
+}
+
+1;
+