2c2c85cd3e158685b77137f187e76a581d13982d
[Business-OnlinePayment-AuthorizeNet.git] / AuthorizeNet.pm
1 package Business::OnlinePayment::AuthorizeNet;
2
3 # $Id: AuthorizeNet.pm,v 1.4 2002-02-12 23:29:43 ivan Exp $
4
5 use strict;
6 use Business::OnlinePayment;
7 use Net::SSLeay qw/make_form post_https/;
8 use Text::CSV_XS;
9 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
10
11 require Exporter;
12
13 @ISA = qw(Exporter AutoLoader Business::OnlinePayment);
14 @EXPORT = qw();
15 @EXPORT_OK = qw();
16 $VERSION = '3.02';
17
18 sub set_defaults {
19     my $self = shift;
20
21     $self->server('secure.authorize.net');
22     $self->port('443');
23     $self->path('/gateway/transact.dll');
24 }
25
26 sub map_fields {
27     my($self) = @_;
28
29     my %content = $self->content();
30
31     # ACTION MAP
32     my %actions = ('normal authorization' => 'AUTH_CAPTURE',
33                    'authorization only'   => 'AUTH_ONLY',
34                    'credit'               => 'CREDIT',
35                    'post authorization'   => 'PRIOR_AUTH_CAPTURE',
36                   );
37     $content{'action'} = $actions{lc($content{'action'})} || $content{'action'};
38
39     # TYPE MAP
40     my %types = ('visa'               => 'CC',
41                  'mastercard'         => 'CC',
42                  'american express'   => 'CC',
43                  'discover'           => 'CC',
44                  'check'              => 'ECHECK',
45                 );
46     $content{'type'} = $types{lc($content{'type'})} || $content{'type'};
47     $self->transaction_type($content{'type'});
48
49     # stuff it back into %content
50     $self->content(%content);
51 }
52
53 sub remap_fields {
54     my($self,%map) = @_;
55
56     my %content = $self->content();
57     foreach(keys %map) {
58         $content{$map{$_}} = $content{$_};
59     }
60     $self->content(%content);
61 }
62
63 sub get_fields {
64     my($self,@fields) = @_;
65
66     my %content = $self->content();
67     my %new = ();
68     foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
69     return %new;
70 }
71
72 sub submit {
73     my($self) = @_;
74
75     $self->map_fields();
76     $self->remap_fields(
77         type           => 'x_Method',
78         login          => 'x_Login',
79         password       => 'x_Password',
80         action         => 'x_Type',
81         description    => 'x_Description',
82         amount         => 'x_Amount',
83         invoice_number => 'x_Invoice_Num',
84         customer_id    => 'x_Cust_ID',
85         last_name      => 'x_Last_Name',
86         first_name     => 'x_First_Name',
87         address        => 'x_Address',
88         city           => 'x_City',
89         state          => 'x_State',
90         zip            => 'x_Zip',
91         card_number    => 'x_Card_Num',
92         expiration     => 'x_Exp_Date',
93         account_number => 'x_Bank_Acct_Num',
94         routing_code   => 'x_Bank_ABA_Code',
95         bank_name      => 'x_Bank_Name',
96         country        => 'x_Country',
97         phone          => 'x_Phone',
98         fax            => 'x_Fax',
99         email          => 'x_Email',
100         company        => 'x_Company',
101     );
102
103     if($self->transaction_type() eq "ECHECK") {
104         $self->required_fields(qw/type login password action amount last_name
105                                   first_name account_number routing_code
106                                   bank_name/);
107     } elsif($self->transaction_type() eq 'CC' ) {
108         $self->required_fields(qw/type login password action amount last_name
109                                   first_name card_number expiration/);
110     } else {
111         Carp::croak("AuthorizeNet can't handle transaction type: ".
112                     $self->transaction_type());
113     }
114
115     my %post_data = $self->get_fields(qw/x_Login x_Password x_Invoice_Num
116                                          x_Description x_Amount x_Cust_ID
117                                          x_Method x_Type x_Card_Num x_Exp_Date
118                                          x_Auth_Code x_Bank_Acct_Num
119                                          x_Bank_ABA_Code x_Bank_Name
120                                          x_Last_Name x_First_Name x_Address
121                                          x_City x_State x_Zip x_Country x_Phone
122                                          x_Fax x_Email x_Email_Customer
123                                          x_Company x_Country/); 
124     $post_data{'x_Test_Request'} = $self->test_transaction()?"TRUE":"FALSE";
125     $post_data{'x_ADC_Delim_Data'} = 'TRUE';
126     $post_data{'x_ADC_URL'} = 'FALSE';
127     $post_data{'x_Version'} = '3.0';
128
129     my $pd = make_form(%post_data);
130     my $s = $self->server();
131     my $p = $self->port();
132     my $t = $self->path();
133     my($page,$server_response,%headers) = post_https($s,$p,$t,'',$pd);
134
135     my $csv = new Text::CSV_XS();
136     $csv->parse($page);
137     my @col = $csv->fields();
138
139     $self->server_response($page);
140     if($col[0] eq "1" ) { # Authorized/Pending/Test
141         $self->is_success(1);
142         $self->result_code($col[0]);
143         $self->authorization($col[4]);
144     } else {
145         $self->is_success(0);
146         $self->result_code($col[2]);
147         $self->error_message($col[3]);
148     }
149 }
150
151 1;
152 __END__
153
154 =head1 NAME
155
156 Business::OnlinePayment::AuthorizeNet - AuthorizeNet backend for Business::OnlinePayment
157
158 =head1 SYNOPSIS
159
160   use Business::OnlinePayment;
161
162   my $tx = new Business::OnlinePayment("AuthorizeNet");
163   $tx->content(
164       type           => 'VISA',
165       login          => 'testdrive',
166       password       => '',
167       action         => 'Normal Authorization',
168       description    => 'Business::OnlinePayment test',
169       amount         => '49.95',
170       invoice_number => '100100',
171       customer_id    => 'jsk',
172       first_name     => 'Jason',
173       last_name      => 'Kohles',
174       address        => '123 Anystreet',
175       city           => 'Anywhere',
176       state          => 'UT',
177       zip            => '84058',
178       card_number    => '4007000000027',
179       expiration     => '09/99',
180   );
181   $tx->submit();
182
183   if($tx->is_success()) {
184       print "Card processed successfully: ".$tx->authorization."\n";
185   } else {
186       print "Card was rejected: ".$tx->error_message."\n";
187   }
188
189 =head1 SUPPORTED TRANSACTION TYPES
190
191 =head2 Visa, MasterCard, American Express, Discover
192
193 Content required: type, login, password, action, amount, first_name, last_name, card_number, expiration.
194
195 =head2 Check
196
197 Content required: type, login, password, action, amount, first_name, last_name, account_number, routing_code, bank_name.
198
199 =head1 DESCRIPTION
200
201 For detailed information see L<Business::OnlinePayment>.
202
203 =head1 NOTE
204
205 Unlike Business::OnlinePayment or previous verisons of
206 Business::OnlinePayment::AuthorizeNet, 3.0 requires separate first_name and
207 last_name fields.
208
209 =head1 COMPATIBILITY
210
211 This module implements Authorize.Net's API verison 3.0.
212
213 =head1 AUTHOR
214
215 Jason Kohles, jason@mediabang.com
216
217 Ivan Kohler <ivan-authorizenet@420.am> updated it for Authorize.Net protocol
218 3.0 and is the current maintainer.
219
220 =head1 SEE ALSO
221
222 perl(1). L<Business::OnlinePayment>.
223
224 =cut
225