1 package Business::OnlinePayment::BankOfAmerica;
3 # $Id: BankOfAmerica.pm,v 1.3 2002-11-19 23:41:24 ivan Exp $
7 use Business::OnlinePayment;
8 use Net::SSLeay qw/make_form post_https make_headers/;
10 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
14 @ISA = qw(Exporter AutoLoader Business::OnlinePayment);
22 $self->server('cart.bamart.com');
29 my %content = $self->content();
31 # warn "$_ = ". ( ref($map{$_})
33 # : $content{$map{$_}} ). "\n";
34 $content{$_} = ref($map{$_})
38 $self->content(%content);
42 my($self,@fields) = @_;
44 my %content = $self->content();
46 foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
53 $self->{order_number} = shift;
55 return $self->{order_number};
61 my %content = $self->content;
63 my $action = lc($content{'action'});
65 die 'Normal Authorization not supported'
66 if $action eq 'normal authorization';
69 my $ioc_indicator = '';
71 if ( $action eq 'authorization only' ) {
72 $self->path('/payment.mart');
74 ioc_merchant_id ioc_order_total_amount ioc_merchant_shopper_id
75 ioc_merchant_order_id ecom_billto_postal_name_first
76 ecom_billto_postal_name_last ecom_billto_postal_street_line1
77 ecom_billto_postal_street_line2 ecom_billto_postal_city
78 ecom_billto_postal_stateprov ecom_billto_postal_postalcode
79 ecom_billto_postal_countrycode ecom_billto_telecom_phone_number
80 ecom_billto_online_email ecom_payment_card_name
81 ecom_payment_card_number ecom_payment_card_expdate_month
82 ecom_payment_card_expdate_year
84 } elsif ( $action eq 'credit' ) {
85 $self->path('/Settlement.mart');
88 ioc_handshake_id ioc_merchant_id ioc_user_name ioc_password
89 ioc_order_number ioc_indicator ioc_settlement_amount
90 ioc_authorization_code ioc_email_flag
92 # ioc_email_flag ioc_close_flag ioc_invoice_notes ioc_email_notes_flag
93 } elsif ( $action eq 'post authorization' ) {
94 $self->path('/Settlement.mart');
97 ioc_handshake_id ioc_merchant_id ioc_user_name ioc_password
98 ioc_order_number ioc_indicator ioc_settlement_amount
99 ioc_authorization_code ioc_email_flag
101 # ioc_email_flag ioc_close_flag ioc_invoice_notes ioc_email_notes_flag
103 die "unknown action $action";
106 # $self->required_fields(qw/type login password action amount last_name
107 # first_name card_number expiration/);
110 unless ( $action eq 'post authorization' ) {
112 if ( $self->transaction_type() =~
113 /^(cc|visa|mastercard|american express|discover)$/i
116 Carp::croak("BankOfAmerica can't handle transaction type: ".
117 $self->transaction_type());
120 $content{'expiration'} =~ /^(\d+)\D+(\d+)$/
121 or croak "unparsable expiration $content{expiration}";
123 ( $month, $year ) = ( $1, $2 );
124 $year += 2000 if $year < 2000; #not y4k safe, oh shit
128 $self->revmap_fields(
129 ioc_merchant_id => \($self->merchant_id()),
130 ioc_user_name => 'login',
131 ioc_password => 'password',
132 ioc_invoice_notes => 'description',
133 ioc_order_total_amount => 'amount',
134 ioc_settlement_amount => 'amount',
135 ioc_merchant_order_id => 'invoice_number',
136 ioc_order_number => 'order_number',
137 ioc_merchant_shopper_id => 'customer_id',
138 ecom_billto_postal_name_last => 'last_name',
139 ecom_billto_postal_name_first => 'first_name',
140 ecom_billto_postal_street_line1 => 'address',
141 #!!! ecom_billto_postal_street_line2 => 'address',
142 ecom_billto_postal_city => 'city',
143 ecom_billto_postal_stateprov => 'state',
144 ecom_billto_postal_postalcode => 'zip',
145 ecom_payment_card_number => 'card_number',
146 ecom_billto_postal_countrycode => 'country',
147 ecom_billto_telecom_phone_number => 'phone',
148 ecom_billto_online_email => 'email',
150 ecom_payment_card_name =>
151 \( $content{'name'} || "$content{first_name} $content{last_name}" ),
153 ecom_payment_card_expdate_month => \$month,
154 ecom_payment_card_expdate_year => \$year,
156 ioc_authorization_code => 'authorization',
157 ioc_indicator => \$ioc_indicator,
158 ioc_handshake_id => 'order_number',
159 ioc_email_flag => \'No',
163 my %post_data = $self->get_fields( @fields );
165 # warn "$_ => $post_data{$_}\n" for keys %post_data;
167 my $pd = make_form(%post_data);
168 my $s = $self->server();
169 my $p = $self->port();
170 my $t = $self->path();
171 my $headers = make_headers('Referer' => $content{'referer'} )
172 unless $action eq 'post authorization';
173 my($page,$server_response,%headers) = post_https($s,$p,$t,$headers,$pd);
176 if ( $action eq 'post authorization' ) {
178 #$page =~ s/<HTML>.*//s;
182 map { /^(\w+)\=(.*)$/ or /^()()$/ or die "unparsable response: $_";
188 map { /^(\w+)\=(.*)$/ or die "unparsable response: $_";
190 split(/\<BR\>/i, $page);
193 #warn "$_ => $response{$_}\n" for keys %response;
195 $self->server_response($page);
197 if ( $response{'ioc_response_code'} eq '0' ) {
198 $self->is_success(1);
199 $self->result_code($response{'ioc_response_code'});
200 $self->authorization($response{'ioc_authorization_code'});
201 $self->order_number($response{'ioc_order_id'});
203 $self->is_success(0);
204 $self->result_code($response{'ioc_response_code'});
206 $action eq 'post authorization'
207 ? $response{'ioc_response_desc'}
208 : $response{'ioc_reject_description'};
209 $error .= ': '. $response{'ioc_missing_fields'}
210 if $response{'ioc_missing_fields'};
211 $error .= ': '. $response{'ioc_invalid_fields'}
212 if $response{'ioc_invalid_fields'};
213 $self->error_message($error);
223 Business::OnlinePayment::BankOfAmerica - Bank of America backend for Business::OnlinePayment
227 use Business::OnlinePayment;
229 my $tx = new Business::OnlinePayment("BankOfAmerica", 'merchant_id' => 'YOURMERCHANTID');
232 action => 'Authorization Only',
233 description => 'Business::OnlinePayment test',
235 invoice_number => '100100',
236 customer_id => 'jsk',
237 first_name => 'Jason',
238 last_name => 'Kohles',
239 address => '123 Anystreet',
243 email => 'ivan-bofa@420.am',
244 card_number => '4007000000027',
245 expiration => '09/99',
246 referer => 'http://cleanwhisker.420.am/',
250 if($tx->is_success()) {
251 print "Card processed successfully: ".$tx->authorization."\n";
253 print "Card was rejected: ".$tx->error_message."\n";
256 if($tx->is_success()) {
258 $auth = $tx->authorization;
259 $ordernum = $tx->order_number;
261 my $capture = new Business::OnlinePayment("BankOfAmerica", 'merchant_id' => 'YOURMERCHANTID' );
264 action => 'Post Authorization',
266 password => 'YOURPASSWORD',
267 order_number => $ordernum,
269 authorization => $auth,
270 description => 'Business::OnlinePayment::BankOfAmerica visa test',
275 if($capture->is_success()) {
276 print "Card captured successfully: ".$capture->authorization."\n";
278 print "Card was rejected: ".$capture->error_message."\n";
283 =head1 SUPPORTED TRANSACTION TYPES
285 =head2 Visa, MasterCard, American Express, JCB, Discover/Novus, Carte blanche/Diners Club
287 Content required for `Authorization Only': type, action, amount,
288 invoice_number, customer_id, first_name, last_name, address, city, state, zip,
289 email, card_number, expiration, referer
291 Content required for `Post Authorization': action, login, password,
292 order_number, amount, authorization, description
294 `Normal Authorization' is not supported by the Bank of America gateway.
296 `Credit' is untested.
300 For detailed information see L<Business::OnlinePayment>.
304 Unlike Business::OnlinePayment or early verisons of
305 Business::OnlinePayment::AuthorizeNet, Business::OnlinePayment::BankOfAmerica
306 requires separate I<first_name> and I<last_name> fields.
308 An additional I<name> field is optional. By default the I<first_name> and
309 I<last_name> fields will be concatenated.
313 Business::OnlinePayment::BankOfAmerica does not support the
314 B<Normal Authorization> mode which combines authorization and capture into a
315 single tranaction. You must use the B<Authorization Only> mode followed by the
316 B<Post Authorization> mode. The B<Credit> mode is supported.
320 This module implements the interface documented at
321 http://www.bankofamerica.com/merchantservices/index.cfm?template=merch_ic_estores_developer.cfm
323 The settlement API is documented at
324 https://manager.bamart.com/welcome/SettlementAPI.pdf
328 No login and password are required for B<Authorization Only> mode. Access
329 is restricted only by the merchant id (available in any public store webpage
330 which passes off to the backend system) and HTTP referer header.
332 There is no way to run test transactions against the settlement API.
336 Ivan Kohler <ivan-bofa@420.am>
338 Based on Business::OnlinePayment::AuthorizeNet written by Jason Kohles.
342 perl(1). L<Business::OnlinePayment>.