initial import BUSINESS_ONLINEPAYMENT_BANKOFAMERICA_1_00 START
authorivan <ivan>
Wed, 26 Sep 2001 03:33:32 +0000 (03:33 +0000)
committerivan <ivan>
Wed, 26 Sep 2001 03:33:32 +0000 (03:33 +0000)
BankOfAmerica.pm [new file with mode: 0644]
Changes [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
Makefile.PL [new file with mode: 0644]
README [new file with mode: 0644]
t/bop.t [new file with mode: 0644]
t/load.t [new file with mode: 0644]
t2/bad_auth.t [new file with mode: 0644]
t2/credit_card.t [new file with mode: 0644]

diff --git a/BankOfAmerica.pm b/BankOfAmerica.pm
new file mode 100644 (file)
index 0000000..adeb175
--- /dev/null
@@ -0,0 +1,339 @@
+package Business::OnlinePayment::BankOfAmerica;
+
+# $Id: BankOfAmerica.pm,v 1.1 2001-09-26 03:33:32 ivan Exp $
+
+use strict;
+use Carp qw(croak);
+use Business::OnlinePayment;
+use Net::SSLeay qw/make_form post_https make_headers/;
+#use Text::CSV;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+
+require Exporter;
+
+@ISA = qw(Exporter AutoLoader Business::OnlinePayment);
+@EXPORT = qw();
+@EXPORT_OK = qw();
+$VERSION = '1.00';
+
+sub set_defaults {
+    my $self = shift;
+
+    $self->server('cart.bamart.com');
+    $self->port('443');
+
+}
+
+sub revmap_fields {
+    my($self, %map) = @_;
+    my %content = $self->content();
+    foreach(keys %map) {
+#    warn "$_ = ". ( ref($map{$_})
+#                         ? ${ $map{$_} }
+#                         : $content{$map{$_}} ). "\n";
+        $content{$_} = ref($map{$_})
+                         ? ${ $map{$_} }
+                         : $content{$map{$_}};
+    }
+    $self->content(%content);
+}
+
+sub get_fields {
+    my($self,@fields) = @_;
+
+    my %content = $self->content();
+    my %new = ();
+    foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
+    return %new;
+}
+
+sub order_number {
+    my $self = shift;
+    if (@_) {
+      $self->{order_number} = shift;
+    }
+    return $self->{order_number};
+}
+
+sub submit {
+    my($self) = @_;
+
+    my %content = $self->content;
+
+    my $action = lc($content{'action'});
+
+    die 'Normal Authorization not supported'
+      if $action eq 'normal authorization';
+
+    my @fields;
+    my $ioc_indicator = '';
+
+    if ( $action eq 'authorization only' ) {
+      $self->path('/payment.mart');
+      @fields = qw(
+          ioc_merchant_id ioc_order_total_amount ioc_merchant_shopper_id
+          ioc_merchant_order_id ecom_billto_postal_name_first
+          ecom_billto_postal_name_last ecom_billto_postal_street_line1
+          ecom_billto_postal_street_line2 ecom_billto_postal_city
+          ecom_billto_postal_stateprov ecom_billto_postal_postalcode
+          ecom_billto_postal_countrycode ecom_billto_telecom_phone_number
+          ecom_billto_online_email ecom_payment_card_name
+          ecom_payment_card_number ecom_payment_card_expdate_month
+          ecom_payment_card_expdate_year
+      );
+    } elsif ( $action eq 'credit' ) {
+      $self->path('/Settlement.mart');
+      $ioc_indicator = 'R';
+      @fields = qw(
+          ioc_handshake_id ioc_merchant_id ioc_user_name ioc_password
+          ioc_order_number ioc_indicator ioc_settlement_amount
+          ioc_authorization_code ioc_email_flag
+      );
+      #    ioc_email_flag ioc_close_flag ioc_invoice_notes ioc_email_notes_flag
+    } elsif ( $action eq 'post authorization' ) {
+      $self->path('/Settlement.mart');
+      $ioc_indicator = 'S';
+      @fields = qw(
+          ioc_handshake_id ioc_merchant_id ioc_user_name ioc_password
+          ioc_order_number ioc_indicator ioc_settlement_amount
+          ioc_authorization_code ioc_email_flag
+      );
+      #    ioc_email_flag ioc_close_flag ioc_invoice_notes ioc_email_notes_flag
+    } else {
+      die "unknown action $action";
+    }
+
+#        $self->required_fields(qw/type login password action amount last_name
+#                                  first_name card_number expiration/);
+
+    my($month, $year);
+    unless ( $action eq 'post authorization' ) {
+
+        if (  $self->transaction_type() =~
+                /^(cc|visa|mastercard|american express|discover)$/i
+           ) {
+        } else {
+            Carp::croak("BankOfAmerica can't handle transaction type: ".
+                        $self->transaction_type());
+        }
+
+      $content{'expiration'} =~ /^(\d+)\D+(\d+)$/
+        or croak "unparsable expiration $content{expiration}";
+
+      ( $month, $year ) = ( $1, $2 );
+      $year += 2000 if $year < 2000; #not y4k safe, oh shit
+
+    }
+
+    $self->revmap_fields(
+        ioc_merchant_id                  => \($self->merchant_id()),
+        ioc_user_name                    => 'login',
+        ioc_password                     => 'password',
+        ioc_invoice_notes                => 'description',
+        ioc_order_total_amount           => 'amount',
+        ioc_settlement_amount            => 'amount',
+        ioc_merchant_order_id            => 'invoice_number',
+        ioc_order_number                 => 'order_number',
+        ioc_merchant_shopper_id          => 'customer_id',
+        ecom_billto_postal_name_last     => 'last_name',
+        ecom_billto_postal_name_first    => 'first_name',
+        ecom_billto_postal_street_line1  => 'address',
+#!!!        ecom_billto_postal_street_line2 => 'address',
+        ecom_billto_postal_city          => 'city',
+        ecom_billto_postal_stateprov     => 'state',
+        ecom_billto_postal_postalcode    => 'zip',
+        ecom_payment_card_number         => 'card_number',
+        ecom_billto_postal_countrycode   => 'country',
+        ecom_billto_telecom_phone_number => 'phone',
+        ecom_billto_online_email         => 'email',
+
+        ecom_payment_card_name =>
+          \( $content{'name'} || "$content{first_name} $content{last_name}" ),
+
+        ecom_payment_card_expdate_month => \$month,
+        ecom_payment_card_expdate_year  => \$year,
+
+        ioc_authorization_code           => 'authorization',
+        ioc_indicator                    => \$ioc_indicator,
+        ioc_handshake_id                 => 'order_number',
+        ioc_email_flag                   => \'No',
+
+    );
+
+    my %post_data = $self->get_fields( @fields );
+
+    warn "$_ => $post_data{$_}\n" for keys %post_data;
+    warn "\n";
+    my $pd = make_form(%post_data);
+    my $s = $self->server();
+    my $p = $self->port();
+    my $t = $self->path();
+    my $headers = make_headers('Referer' => $content{'referer'} )
+      unless $action eq 'post authorization';
+    my($page,$server_response,%headers) = post_https($s,$p,$t,$headers,$pd);
+
+    my %response;
+    if ( $action eq 'post authorization' ) {
+     $page =~ s/<HTML>.*//s;
+     $page =~ s/\n+$//;
+     %response =
+        map { /^(\w+)\=(.*)$/ or /^()()$/ or die $_; lc($1) => $2 }
+          split(/\r/, $page);
+    } else {
+      %response =
+        map { /^(\w+)\=(.*)$/ or die $_; lc($1) => $2 } split(/\<BR\>/i, $page);
+    }
+
+    warn "$_ => $response{$_}\n" for keys %response;
+
+    $self->server_response($page);
+
+    if ( $response{'ioc_response_code'} eq '0' ) {
+        $self->is_success(1);
+        $self->result_code($response{'ioc_response_code'});
+        $self->authorization($response{'ioc_authorization_code'});
+        $self->order_number($response{'ioc_order_id'});
+    } else {
+        $self->is_success(0);
+        $self->result_code($response{'ioc_response_code'});
+        my $error =
+          $action eq 'post authorization'
+            ? $response{'ioc_response_desc'}
+            : $response{'ioc_reject_description'};
+        $error .= ': '. $response{'ioc_missing_fields'}
+          if $response{'ioc_missing_fields'};
+        $error .= ': '. $response{'ioc_invalid_fields'}
+          if $response{'ioc_invalid_fields'};
+        $self->error_message($error);
+    }
+
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Business::OnlinePayment::BankOfAmerica - Bank of America backend for Business::OnlinePayment
+
+=head1 SYNOPSIS
+
+  use Business::OnlinePayment;
+
+  my $tx = new Business::OnlinePayment("BankOfAmerica", 'merchant_id' => 'YOURMERCHANTID');
+  $tx->content(
+      type           => 'VISA',
+      action         => 'Authorization Only',
+      description    => 'Business::OnlinePayment test',
+      amount         => '49.95',
+      invoice_number => '100100',
+      customer_id    => 'jsk',
+      first_name     => 'Jason',
+      last_name      => 'Kohles',
+      address        => '123 Anystreet',
+      city           => 'Anywhere',
+      state          => 'UT',
+      zip            => '84058',
+      email          => 'ivan-bofa@420.am',
+      card_number    => '4007000000027',
+      expiration     => '09/99',
+      referer        => 'http://cleanwhisker.420.am/',
+  );
+  $tx->submit();
+
+  if($tx->is_success()) {
+      print "Card processed successfully: ".$tx->authorization."\n";
+  } else {
+      print "Card was rejected: ".$tx->error_message."\n";
+  }
+
+ if($tx->is_success()) {
+
+      $auth = $tx->authorization;
+      $ordernum = $tx->order_number;
+
+      my $capture = new Business::OnlinePayment("BankOfAmerica", 'merchant_id' => 'YOURMERCHANTID' );
+
+      $capture->content(
+          action         => 'Post Authorization',
+          login          => 'YOURLOGIN
+          password       => 'YOURPASSWORD',
+          order_number   => $ordernum,
+          amount         => '0.01',
+          authorization  => $auth,
+          description    => 'Business::OnlinePayment::BankOfAmerica visa test',
+      );
+
+      $capture->submit();
+
+      if($capture->is_success()) { 
+          print "Card captured successfully: ".$capture->authorization."\n";
+      } else {
+          print "Card was rejected: ".$capture->error_message."\n";
+      }
+
+  }
+
+=head1 SUPPORTED TRANSACTION TYPES
+
+=head2 Visa, MasterCard, American Express, JCB, Discover/Novus, Carte blanche/Diners Club
+
+Content required for `Authorization Only': type, action, amount,
+invoice_number, customer_id, first_name, last_name, address, city, state, zip,
+email, card_number, expiration, referer
+
+Content required for `Post Authorization': action, login, password,
+order_number, amount, authorization, description
+
+`Normal Authorization' is not supported by the Bank of America gateway.
+
+`Credit' is untested.
+
+=head1 DESCRIPTION
+
+For detailed information see L<Business::OnlinePayment>.
+
+=head1 NOTE
+
+Unlike Business::OnlinePayment or early verisons of
+Business::OnlinePayment::AuthorizeNet, Business::OnlinePayment::BankOfAmerica
+requires separate I<first_name> and I<last_name> fields.
+
+An additional I<name> field is optional.  By default the I<first_name> and
+I<last_name> fields will be concatenated.
+
+=head1 NOTE
+
+Business::OnlinePayment::BankOfAmerica does not support the
+B<Normal Authorization> mode which combines authorization and capture into a
+single tranaction.  You must use the B<Authorization Only> mode followed by the
+B<Post Authorization> mode.  The B<Credit> mode is supported.
+
+=head1 COMPATIBILITY
+
+This module implements the interface documented at
+http://www.bankofamerica.com/merchantservices/index.cfm?template=merch_ic_estores_developer.cfm
+
+The settlement API is documented at
+https://manager.bamart.com/welcome/SettlementAPI.pdf
+
+=head1 BUGS
+
+No login and password are required for B<Authorization Only> mode.  Access
+is restricted only by the merchant id (available in any public store webpage
+which passes off to the backend system) and HTTP referer header.
+
+There is no way to run test transactions against the settlement API.
+
+=head1 AUTHOR
+
+Ivan Kohler <ivan-bofa@420.am>
+
+Based on Businss::OnlinePayment::AuthorizeNet written by Jason Kohles.
+
+=head1 SEE ALSO
+
+perl(1). L<Business::OnlinePayment>.
+
+=cut
+
diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..7e8055e
--- /dev/null
+++ b/Changes
@@ -0,0 +1,8 @@
+Revision history for Perl extension Business::OnlinePayment::BankOfAmerica.
+
+1.00  Tue Sep 25 20:28:51 2001
+       - upload to CPAN.
+
+0.01  Sun Sep 13 00:40:03 2001
+       - original version; created by ivan 1.0
+
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..703bd58
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,9 @@
+BankOfAmerica.pm
+Changes
+MANIFEST
+Makefile.PL
+README
+t/bop.t
+t/load.t
+t2/bad_auth.t
+t2/credit_card.t
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644 (file)
index 0000000..cbeb20f
--- /dev/null
@@ -0,0 +1,11 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+    'NAME'         => 'Business::OnlinePayment::BankOfAmerica',
+    'VERSION_FROM' => 'BankOfAmerica.pm', # finds $VERSION
+    'AUTHOR'       => 'Ivan Kohler <ivan-authorizenet@420.am>',
+    #'NORECURS'     => 1, # dont descend into subdirectories
+    'PREREQ_PM'    => {'Net::SSLeay' => 0 }, #, 'Text::CSV' => 0},
+    #'dist'         => {CI => 'ci -l'},
+);
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e3fffa8
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+Copyright (c) 2001 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.
+
+This is Business::OnlinePayment::BankOfAmerica, an Bank of America-specific
+backend module for Business::OnlinePayment.  It implements the interface
+documented in
+
+http://www.bankofamerica.com/merchantservices/index.cfm?template=merch_ic_estores_developer.cfm
+
+The settlement API is documented at
+https://manager.bamart.com/welcome/SettlementAPI.pdf
+
+It based on Businss::OnlinePayment::AuthorizeNet written by Jason Kohles.
+
+There are additional tests in t2/ that may be useful to you once you have a
+merchant_id, login and password.
+
+Ivan Kohler <ivan-bofa@420.am>
+
+Business::OnlinePayment is a generic interface for processing payments through
+online credit card processors, online check acceptance houses, etc.  (If you
+like buzzwords, call it an "multiplatform ecommerce-enabling middleware
+solution").
diff --git a/t/bop.t b/t/bop.t
new file mode 100644 (file)
index 0000000..64332c5
--- /dev/null
+++ b/t/bop.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n"; }
+END {print "not ok 1\n" unless $loaded;}
+use Business::OnlinePayment;
+$loaded = 1;
+print "ok 1\n";
diff --git a/t/load.t b/t/load.t
new file mode 100644 (file)
index 0000000..d49b683
--- /dev/null
+++ b/t/load.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n"; }
+END {print "not ok 1\n" unless $loaded;}
+use Business::OnlinePayment::BankOfAmerica;
+$loaded = 1;
+print "ok 1\n";
diff --git a/t2/bad_auth.t b/t2/bad_auth.t
new file mode 100644 (file)
index 0000000..602c816
--- /dev/null
@@ -0,0 +1,32 @@
+BEGIN { $| = 1; print "1..1\n"; }
+
+use Business::OnlinePayment;
+
+my $tx = new Business::OnlinePayment("BankOfAmerica", 'merchant_id' => 'YOURMERCHANTID' );
+$tx->content(
+    type           => 'VISA',
+    action         => 'Authorization Only',
+    description    => 'Business::OnlinePayment::BankOfAmerica visa test',
+    amount         => '49.95',
+    invoice_number => '100',
+    customer_id    => 'jsk',
+    first_name     => 'Tofu',
+    last_name      => 'Beast',
+    address        => '123 Anystreet',
+    city           => 'Anywhere',
+    state          => 'UT',
+    zip            => '84058',
+    country        => 'US',
+    email          => 'ivan-bofa@420.am',
+#    card_number    => '4007000000027',
+    expiration     => '08/2004',
+    referer        => 'http://cleanwhisker.420.am/',
+);
+$tx->submit();
+
+if($tx->is_success()) {
+    print "not ok 1\n";
+} else {
+#    warn '***** '. $tx->error_message. " *****\n";
+    print "ok 1\n";
+}
diff --git a/t2/credit_card.t b/t2/credit_card.t
new file mode 100644 (file)
index 0000000..1f47875
--- /dev/null
@@ -0,0 +1,61 @@
+BEGIN { $| = 1; print "1..2\n"; }
+
+use Business::OnlinePayment;
+
+my $tx = new Business::OnlinePayment("BankOfAmerica", 'merchant_id' => 'YOURMERCHANTID' );
+$tx->content(
+    type           => 'VISA',
+    action         => 'Authorization Only',
+    description    => 'Business::OnlinePayment::BankOfAmerica visa test',
+    amount         => '0.01',
+    invoice_number => '100',
+    customer_id    => 'jsk',
+    first_name     => 'Tofu',
+    last_name      => 'Beast',
+    address        => '123 Anystreet',
+    city           => 'Anywhere',
+    state          => 'UT',
+    zip            => '84058',
+    country        => 'US',
+    email          => 'ivan-bofa@420.am',
+    card_number    => '4007000000027',
+    expiration     => '12/2002',
+    referer        => 'http://cleanwhisker.420.am/',
+);
+$tx->submit();
+
+if($tx->is_success()) {
+    print "ok 1\n";
+    $auth = $tx->authorization;
+    $ordernum = $tx->order_number;
+    #warn "********* $auth ***********\n";
+    #warn "********* $ordernum ***********\n";
+} else {
+    print "not ok 1\n";
+#    warn '***** '. $tx->error_message. " *****\n";
+    exit;
+}
+
+#exit;
+my $capture = new Business::OnlinePayment("BankOfAmerica", 'merchant_id' => 'YOURMERCHANTID' );
+
+$capture->content(
+    action         => 'Post Authorization',
+    login          => 'YOURLOGIN
+    password       => 'YOURPASSWORD',
+    order_number   => $ordernum,
+    amount         => '0.01',
+    authorization  => $auth,
+    description    => 'Business::OnlinePayment::BankOfAmerica visa test',
+);
+
+$capture->submit();
+
+if($capture->is_success()) { 
+    print "ok 2\n";
+} else {
+#    warn '***** '. $capture->error_message. " *****\n";
+    print "not ok 2\n";
+}
+
+