*** empty log message ***
[Business-OnlinePayment-AuthorizeNet.git] / AuthorizeNet.pm
1 package Business::OnlinePayment::AuthorizeNet;
2
3 use strict;
4 use Carp;
5 use Business::OnlinePayment;
6 use vars qw($VERSION @ISA $me);
7
8 @ISA = qw(Business::OnlinePayment);
9 $VERSION = '3.19';
10 $me = 'Business::OnlinePayment::AuthorizeNet';
11
12 sub set_defaults {
13     my $self = shift;
14
15     $self->build_subs(qw( order_number md5 avs_code cvv2_response
16                           cavv_response
17                      ));
18 }
19
20 sub _map_processor {
21     my($self) = @_;
22
23     my %content = $self->content();
24     my %processors = ('recurring authorization'          => 'ARB',
25                       'modify recurring authorization'   => 'ARB',
26                       'cancel recurring authorization'   => 'ARB',
27                      );
28     $processors{lc($content{'action'})} || 'AIM';
29 }
30
31 sub submit {
32     my($self) = @_;
33
34     my $processor = $me. "::". $self->_map_processor();
35
36     eval "use $processor";
37     croak("unknown processor $processor ($@)") if $@;
38     
39     my $object = bless $self, $processor;
40     $object->set_defaults();
41     $object->submit();
42     bless $self, $me;
43 }
44
45 1;
46 __END__
47
48 =head1 NAME
49
50 Business::OnlinePayment::AuthorizeNet - AuthorizeNet backend for Business::OnlinePayment
51
52 =head1 SYNOPSIS
53
54   use Business::OnlinePayment;
55
56   ####
57   # One step transaction, the simple case.
58   ####
59
60   my $tx = new Business::OnlinePayment("AuthorizeNet");
61   $tx->content(
62       type           => 'VISA',
63       login          => 'testdrive',
64       password       => '', #password or transaction key
65       action         => 'Normal Authorization',
66       description    => 'Business::OnlinePayment test',
67       amount         => '49.95',
68       invoice_number => '100100',
69       customer_id    => 'jsk',
70       first_name     => 'Jason',
71       last_name      => 'Kohles',
72       address        => '123 Anystreet',
73       city           => 'Anywhere',
74       state          => 'UT',
75       zip            => '84058',
76       card_number    => '4007000000027',
77       expiration     => '09/02',
78       cvv2           => '1234', #optional
79       referer        => 'http://valid.referer.url/',
80   );
81   $tx->submit();
82
83   if($tx->is_success()) {
84       print "Card processed successfully: ".$tx->authorization."\n";
85   } else {
86       print "Card was rejected: ".$tx->error_message."\n";
87   }
88
89   ####
90   # Two step transaction, authorization and capture.
91   # If you don't need to review order before capture, you can
92   # process in one step as above.
93   ####
94
95   my $tx = new Business::OnlinePayment("AuthorizeNet");
96   $tx->content(
97       type           => 'VISA',
98       login          => 'testdrive',
99       password       => '',  #password or transaction key
100       action         => 'Authorization Only',
101       description    => 'Business::OnlinePayment test',
102       amount         => '49.95',
103       invoice_number => '100100',
104       customer_id    => 'jsk',
105       first_name     => 'Jason',
106       last_name      => 'Kohles',
107       address        => '123 Anystreet',
108       city           => 'Anywhere',
109       state          => 'UT',
110       zip            => '84058',
111       card_number    => '4007000000027',
112       expiration     => '09/02',
113       cvv2           => '1234', #optional
114       referer        => 'http://valid.referer.url/',
115   );
116   $tx->submit();
117
118   if($tx->is_success()) {
119       # get information about authorization
120       $authorization = $tx->authorization
121       $ordernum = $tx->order_number;
122       $avs_code = $tx->avs_code; # AVS Response Code
123       $cvv2_response = $tx->cvv2_response; # CVV2/CVC2/CID Response Code
124       $cavv_response = $tx->cavv_response; # Cardholder Authentication
125                                            # Verification Value (CAVV) Response
126                                            # Code
127
128       # now capture transaction
129       my $capture = new Business::OnlinePayment("AuthorizeNet");
130
131       $capture->content(
132           type           => 'CC',
133           action         => 'Post Authorization',
134           login          => 'YOURLOGIN
135           password       => 'YOURPASSWORD',
136           order_number   => $ordernum,
137           amount         => '49.95',
138       );
139
140       $capture->submit();
141
142       if($capture->is_success()) { 
143           print "Card captured successfully: ".$capture->authorization."\n";
144       } else {
145           print "Card was rejected: ".$capture->error_message."\n";
146       }
147
148   } else {
149       print "Card was rejected: ".$tx->error_message."\n";
150   }
151
152   ####
153   # One step subscription, the simple case.
154   ####
155
156   my $tx = new Business::OnlinePayment("AuthorizeNet::ARB");
157   $tx->content(
158       type           => 'CC',
159       login          => 'testdrive',
160       password       => 'testpass',
161       action         => 'Recurring Authorization',
162       interval       => '7 days',
163       start          => '2008-3-10',
164       periods        => '16',
165       amount         => '99.95',
166       trialperiods   => '4',
167       trialamount    => '0',
168       description    => 'Business::OnlinePayment test',
169       invoice_number => '1153B33F',
170       customer_id    => 'vip',
171       first_name     => 'Tofu',
172       last_name      => 'Beast',
173       address        => '123 Anystreet',
174       city           => 'Anywhere',
175       state          => 'GA',
176       zip            => '84058',
177       card_number    => '4111111111111111',
178       expiration     => '09/02',
179   );
180   $tx->submit();
181
182   if($tx->is_success()) {
183       print "Card processed successfully: ".$tx->order_number."\n";
184   } else {
185       print "Card was rejected: ".$tx->error_message."\n";
186   }
187   my $subscription = $tx->order_number
188
189
190   ####
191   # Subscription change.   Modestly more complicated.
192   ####
193
194   $tx->content(
195       type           => 'CC',
196       subscription   => '99W2C',
197       login          => 'testdrive',
198       password       => 'testpass',
199       action         => 'Modify Recurring Authorization',
200       interval       => '7 days',
201       start          => '2008-3-10',
202       periods        => '16',
203       amount         => '29.95',
204       trialperiods   => '4',
205       trialamount    => '0',
206       description    => 'Business::OnlinePayment test',
207       invoice_number => '1153B340',
208       customer_id    => 'vip',
209       first_name     => 'Tofu',
210       last_name      => 'Beast',
211       address        => '123 Anystreet',
212       city           => 'Anywhere',
213       state          => 'GA',
214       zip            => '84058',
215       card_number    => '4111111111111111',
216       expiration     => '09/02',
217   );
218   $tx->submit();
219
220   if($tx->is_success()) {
221       print "Update processed successfully."\n";
222   } else {
223       print "Update was rejected: ".$tx->error_message."\n";
224   }
225   $tx->content(
226       subscription   => '99W2D',
227       login          => 'testdrive',
228       password       => 'testpass',
229       action         => 'Cancel Recurring Authorization',
230   );
231   $tx->submit();
232
233   ####
234   # Subscription cancellation.   It happens.
235   ####
236
237   if($tx->is_success()) {
238       print "Cancellation processed successfully."\n";
239   } else {
240       print "Cancellation was rejected: ".$tx->error_message."\n";
241   }
242
243
244 =head1 SUPPORTED TRANSACTION TYPES
245
246 =head2 CC, Visa, MasterCard, American Express, Discover
247
248 Content required: type, login, password|transaction_key, action, amount, first_name, last_name, card_number, expiration.
249
250 =head2 Check
251
252 Content required: type, login, password|transaction_key, action, amount, first_name, last_name, account_number, routing_code, bank_name (non-subscription), account_type (subscription), check_type (subscription).
253
254 =head2 Subscriptions
255
256 Additional content required: interval, start, periods.
257
258 =head1 DESCRIPTION
259
260 For detailed information see L<Business::OnlinePayment>.
261
262 =head1 METHODS AND FUNCTIONS
263
264 See L<Business::OnlinePayment> for the complete list. The following methods either override the methods in L<Business::OnlinePayment> or provide additional functions.  
265
266 =head2 result_code
267
268 Returns the response reason code (from the message.code field for subscriptions).
269
270 =head2 error_message
271
272 Returns the response reason text (from the message.text field for subscriptions.
273
274 =head2 server_response
275
276 Returns the complete response from the server.
277
278 =head1 Handling of content(%content) data:
279
280 =head2 action
281
282 The following actions are valid
283
284   normal authorization
285   authorization only
286   credit
287   post authorization
288   void
289   recurring authorization
290   modify recurring authorization
291   cancel recurring authorization
292
293 =head2 interval
294
295   Interval contains a number of digits, whitespace, and the units of days or months in either singular or plural form.
296   
297
298 =head1 Setting AuthorizeNet ARB parameters from content(%content)
299
300 The following rules are applied to map data to AuthorizeNet ARB parameters
301 from content(%content):
302
303       # ARB param => $content{<key>}
304       merchantAuthentication
305         name                     =>  'login',
306         transactionKey           =>  'password',
307       subscription
308         paymentSchedule
309           interval
310             length               => \( the digits in 'interval' ),
311             unit                 => \( days or months gleaned from 'interval' ),          startDate              => 'start',
312           totalOccurrences       => 'periods',
313           trialOccurrences       => 'trialperiods',
314         amount                   => 'amount',
315         trialAmount              => 'trialamount',
316         payment
317           creditCard
318             cardNumber           => 'card_number',
319             expiration           => \( $year.'-'.$month ), # YYYY-MM from 'expiration'
320           bankAccount
321             accountType          => 'account_type',
322             routingNumber        => 'routing_code',
323             accountNumber        => 'account_number,
324             nameOnAccount        => 'name',
325             bankName             => 'bank_name',
326             echeckType           => 'check_type',
327         order
328           invoiceNumber          => 'invoice_number',
329           description            => 'description',
330         customer
331           type                   => 'customer_org',
332           id                     => 'customer_id',
333           email                  => 'email',
334           phoneNumber            => 'phone',
335           faxNumber              => 'fax',
336           driversLicense
337             number               => 'license_num',
338             state                => 'license_state',
339             dateOfBirth          => 'license_dob',
340           taxid                  => 'customer_ssn',
341         billTo
342           firstName              => 'first_name',
343           lastName               => 'last_name',
344           company                => 'company',
345           address                => 'address',
346           city                   => 'city',
347           state                  => 'state',
348           zip                    => 'zip',
349           country                => 'country',
350         shipTo
351           firstName              => 'ship_first_name',
352           lastName               => 'ship_last_name',
353           company                => 'ship_company',
354           address                => 'ship_address',
355           city                   => 'ship_city',
356           state                  => 'ship_state',
357           zip                    => 'ship_zip',
358           country                => 'ship_country',
359
360 =head1 NOTE
361
362 Unlike Business::OnlinePayment or pre-3.0 verisons of
363 Business::OnlinePayment::AuthorizeNet, 3.1 requires separate first_name and
364 last_name fields.
365
366 Business::OnlinePayment::AuthorizeNet uses Authorize.Net's "Advanced
367 Integration Method (AIM) (formerly known as ADC direct response)" and
368 "Automatic Recurring Billing (ARB)", sending a username and transaction_key
369 or password with every transaction.  Therefore, Authorize.Net's
370 referrer "security" is not necessary.  In your Authorize.Net interface at
371 https://secure.authorize.net/ make sure the list of allowable referers is
372 blank.  Alternatively, set the B<referer> field in the transaction content.
373
374 To settle an authorization-only transaction (where you set action to
375 'Authorization Only'), submit the nine-digit transaction id code in
376 the field "order_number" with the action set to "Post Authorization".
377 You can get the transaction id from the authorization by calling the
378 order_number method on the object returned from the authorization.
379 You must also submit the amount field with a value less than or equal
380 to the amount specified in the original authorization.
381
382 For the subscription actions an authorization code is never returned by
383 the module.  Instead it returns the value of subscriptionId in order_number.
384 This is the value to use for changing or cancelling subscriptions.
385
386 Recently (February 2002), Authorize.Net has turned address
387 verification on by default for all merchants.  If you do not have
388 valid address information for your customer (such as in an IVR
389 application), you must disable address verification in the Merchant
390 Menu page at https://secure.authorize.net/ so that the transactions
391 aren't denied due to a lack of address information.
392
393 =head1 COMPATIBILITY
394
395 This module implements Authorize.Net's API using the Advanced Integration
396 Method (AIM) version 3.1, formerly known as ADC Direct Response and the 
397 Automatic Recurring Billing version 1.0 using the XML interface.  See
398 http://www.authorize.net/support/AIM_guide.pdf and http://www.authorize.net/support/ARB_guide.pdf for details.
399
400 =head1 AUTHOR
401
402 Jason Kohles, jason@mediabang.com
403
404 Ivan Kohler <ivan-authorizenet@420.am> updated it for Authorize.Net protocol
405 3.0/3.1 and is the current maintainer.  Please send patches as unified diffs
406 (diff -u).
407
408 Jason Spence <jspence@lightconsulting.com> contributed support for separate
409 Authorization Only and Post Authorization steps and wrote some docs.
410 OST <services@ostel.com> paid for it.
411
412 Jeff Finucane <authorizenetarb@weasellips.com> added the ARB support.
413 ARB support sponsored by Plus Three, LP. L<http://www.plusthree.com>.
414
415 T.J. Mather <tjmather@maxmind.com> sent a number of CVV2 patches.
416
417 Mike Barry <mbarry@cos.com> sent in a patch for the referer field.
418
419 Yuri V. Mkrtumyan <yuramk@novosoft.ru> sent in a patch to add the void action.
420
421 Paul Zimmer <AuthorizeNetpm@pzimmer.box.bepress.com> sent in a patch for
422 card-less post authorizations.
423
424 Daemmon Hughes <daemmon@daemmonhughes.com> sent in a patch for "transaction
425 key" authentication as well support for the recurring_billing flag and the md5
426 method that returns the MD5 hash which is returned by the gateway.
427
428 Steve Simitzis contributed a patch for better compatibility with
429 eProcessingNetwork's AuthorizeNet compatability mode.
430
431 =head1 SEE ALSO
432
433 perl(1). L<Business::OnlinePayment>.
434
435 =cut
436