1 package Business::OnlinePayment::AuthorizeNet;
3 # $Id: AuthorizeNet.pm,v 1.12 2002-08-03 21:20:51 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('secure.authorize.net');
24 $self->path('/gateway/transact.dll');
26 $self->build_subs('order_number'); #no idea how it worked for jason w/o this
32 my %content = $self->content();
35 my %actions = ('normal authorization' => 'AUTH_CAPTURE',
36 'authorization only' => 'AUTH_ONLY',
38 'post authorization' => 'PRIOR_AUTH_CAPTURE',
40 $content{'action'} = $actions{lc($content{'action'})} || $content{'action'};
43 my %types = ('visa' => 'CC',
45 'american express' => 'CC',
49 $content{'type'} = $types{lc($content{'type'})} || $content{'type'};
50 $self->transaction_type($content{'type'});
52 $content{'referer'} = defined( $content{'referer'} )
53 ? make_headers( 'Referer' => $content{'referer'} )
56 # stuff it back into %content
57 $self->content(%content);
63 my %content = $self->content();
65 $content{$map{$_}} = $content{$_};
67 $self->content(%content);
71 my($self,@fields) = @_;
73 my %content = $self->content();
75 foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
86 password => 'x_Password',
88 description => 'x_Description',
90 invoice_number => 'x_Invoice_Num',
91 customer_id => 'x_Cust_ID',
92 last_name => 'x_Last_Name',
93 first_name => 'x_First_Name',
94 address => 'x_Address',
98 card_number => 'x_Card_Num',
99 expiration => 'x_Exp_Date',
100 account_number => 'x_Bank_Acct_Num',
101 routing_code => 'x_Bank_ABA_Code',
102 bank_name => 'x_Bank_Name',
103 country => 'x_Country',
107 company => 'x_Company',
108 order_number => 'x_Trans_ID',
109 cvv2 => 'x_Card_Code',
112 if($self->transaction_type() eq "ECHECK") {
113 $self->required_fields(qw/type login password action amount last_name
114 first_name account_number routing_code
116 } elsif($self->transaction_type() eq 'CC' ) {
117 if ( $self->{_content}->{action} eq 'PRIOR_AUTH_CAPTURE' ) {
118 $self->required_fields(qw/type login password action amount
119 card_number expiration/);
121 $self->required_fields(qw/type login password action amount last_name
122 first_name card_number expiration/);
125 Carp::croak("AuthorizeNet can't handle transaction type: ".
126 $self->transaction_type());
129 my %post_data = $self->get_fields(qw/x_Login x_Password x_Invoice_Num
130 x_Description x_Amount x_Cust_ID
131 x_Method x_Type x_Card_Num x_Exp_Date
132 x_Auth_Code x_Bank_Acct_Num
133 x_Bank_ABA_Code x_Bank_Name
134 x_Last_Name x_First_Name x_Address
135 x_City x_State x_Zip x_Country x_Phone
136 x_Fax x_Email x_Email_Customer
137 x_Company x_Country x_Trans_ID
139 $post_data{'x_Test_Request'} = $self->test_transaction()?"TRUE":"FALSE";
140 $post_data{'x_ADC_Delim_Data'} = 'TRUE';
141 $post_data{'x_ADC_URL'} = 'FALSE';
142 $post_data{'x_Version'} = '3.1';
144 my $pd = make_form(%post_data);
145 my $s = $self->server();
146 my $p = $self->port();
147 my $t = $self->path();
148 my $r = $self->{_content}->{referer};
149 my($page,$server_response,%headers) = post_https($s,$p,$t,$r,$pd);
150 #escape NULL (binary 0x00) values
151 $page =~ s/\x00/\^0/g;
153 my $csv = new Text::CSV_XS();
155 my @col = $csv->fields();
157 $self->server_response($page);
158 if($col[0] eq "1" ) { # Authorized/Pending/Test
159 $self->is_success(1);
160 $self->result_code($col[0]);
161 $self->authorization($col[4]);
162 $self->order_number($col[6]);
164 $self->is_success(0);
165 $self->result_code($col[2]);
166 $self->error_message($col[3]);
167 unless ( $self->result_code() ) { #additional logging information
168 #$page =~ s/\x00/\^0/g;
169 $self->error_message($col[3].
170 " DEBUG: No x_response_code from server, ".
171 "(HTTPS response: $server_response) ".
173 join(", ", map { "$_ => ". $headers{$_} } keys %headers ). ") ".
174 "(Raw HTTPS content: $page)"
185 Business::OnlinePayment::AuthorizeNet - AuthorizeNet backend for Business::OnlinePayment
189 use Business::OnlinePayment;
191 my $tx = new Business::OnlinePayment("AuthorizeNet");
194 login => 'testdrive',
196 action => 'Normal Authorization',
197 description => 'Business::OnlinePayment test',
199 invoice_number => '100100',
200 customer_id => 'jsk',
201 first_name => 'Jason',
202 last_name => 'Kohles',
203 address => '123 Anystreet',
207 card_number => '4007000000027',
208 expiration => '09/02',
209 cvv2 => '1234', #optional
210 referer => 'http://valid.referer.url/',
214 if($tx->is_success()) {
215 print "Card processed successfully: ".$tx->authorization."\n";
217 print "Card was rejected: ".$tx->error_message."\n";
220 =head1 SUPPORTED TRANSACTION TYPES
222 =head2 Visa, MasterCard, American Express, Discover
224 Content required: type, login, password, action, amount, first_name, last_name, card_number, expiration.
228 Content required: type, login, password, action, amount, first_name, last_name, account_number, routing_code, bank_name.
232 For detailed information see L<Business::OnlinePayment>.
236 Unlike Business::OnlinePayment or pre-3.0 verisons of
237 Business::OnlinePayment::AuthorizeNet, 3.1 requires separate first_name and
240 To settle an authorization-only transaction (where you set action to
241 'Authorization Only'), submit the nine-digit transaction id code in
242 the field "order_number" with the action set to "Post Authorization".
243 You can get the transaction id from the authorization by calling the
244 order_number method on the object returned from the authorization.
245 You must also submit the amount field with a value less than or equal
246 to the amount specified in the original authorization.
248 Recently (February 2002), Authorize.Net has turned address
249 verification on by default for all merchants. If you do not have
250 valid address information for your customer (such as in an IVR
251 application), you must disable address verification in the Merchant
252 Menu page at https://secure.authorize.net/ so that the transactions
253 aren't denied due to a lack of address information.
257 This module implements Authorize.Net's API verison 3.1 using the ADC
258 Direct Response method. See
259 https://secure.authorize.net/docs/developersguide.pml for details.
263 Jason Kohles, jason@mediabang.com
265 Ivan Kohler <ivan-authorizenet@420.am> updated it for Authorize.Net protocol
266 3.0/3.1 and is the current maintainer.
268 Jason Spence <jspence@lightconsulting.com> contributed support for separate
269 Authorization Only and Post Authorization steps and wrote some docs.
270 OST <services@ostel.com> paid for it.
272 T.J. Mather <tjmather@maxmind.com> sent a patch for the CVV2 field.
276 perl(1). L<Business::OnlinePayment>.