1package Business::OnlinePayment::iAuthorizer;
2
3# $Id: iAuthorizer.pm,v 1.6 2003/09/11 05:30:38 db48x Exp $
4
5use Data::Dumper;
6use strict;
7use Business::OnlinePayment;
8use Net::SSLeay qw/make_form post_https make_headers/;
9use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
10
11require Exporter;
12
13@ISA = qw(Exporter AutoLoader Business::OnlinePayment);
14@EXPORT = qw();
15@EXPORT_OK = qw();
16$VERSION = '0.2';
17
18sub set_defaults {
19    my $self = shift;
20
21    $self->server('tran1.iAuthorizer.net');
22    $self->port('443');
23    $self->path('/trans/postto.asp');
24
25    $self->build_subs('action');
26    $self->build_subs('debug');
27}
28
29sub map_fields {
30    my($self) = @_;
31
32    my %content = $self->content();
33
34    # ACTION MAP
35    my %actions = ('normal authorization' => '5',
36                   'authorization only'   => '6',
37                   'credit'               => '0',
38                   'post authorization'   => '2',
39                   'void'                 => '1',
40                  );
41    $content{'action'} = $actions{lc($content{'action'})};
42
43    my %methods = ('manual'         => '0',
44                   'swipe'          => '1',
45                   'swipe, track 1' => '1',
46                   'swipe, track 2' => '2',
47                  );
48    $content{'entry_method'} = $methods{lc($content{'entry_method'})};
49
50    ($content{'expMonth'}, $content{'expYear'}) = split('/', $content{'expiration'});
51
52    # stuff it back into %content
53    $self->content(%content);
54}
55
56sub remap_fields {
57    my($self,%map) = @_;
58
59    my %content = $self->content();
60    foreach(keys %map) {
61        $content{$map{$_}} = $content{$_};
62    }
63    $self->content(%content);
64}
65
66sub get_fields {
67    my($self,@fields) = @_;
68
69    my %content = $self->content();
70    my %new = ();
71    foreach(grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
72
73    return %new;
74}
75
76sub transaction_type {
77    my $self = shift;
78    return $self->content()->{'action'};
79}
80
81sub submit {
82    my($self) = @_;
83
84    $self->map_fields();
85    $self->remap_fields(
86        entry_method   => 'EntryMethod',
87        login          => 'MerchantCode',
88        password       => 'MerchantPWD',
89        serial         => 'MerchantSerial',
90        action         => 'Trantype',
91        amount         => 'amount',
92        invoice_number => 'invoicenum',
93	order_number   => 'referencenum',
94	authorization  => 'appcode',
95        customer_id    => 'customer',
96        address        => 'Address',
97        zip            => 'ZipCode',
98        card_number    => 'ccnumber',
99        cvv2           => 'CVV2',
100    );
101
102#    if ($self->action() == 0 || $self->action() == 1) # void or force
103#    {
104#      $self->required_fields(qw/login password serial action card_number expiration amount authorization/);
105#    }
106#    else
107#    {
108      $self->required_fields(qw/login password serial action card_number expiration amount/);
109#    }
110
111    my %post_data = $self->get_fields(qw/MerchantCode MerchantPWD MerchantSerial ccnumber
112                                         expYear expMonth Trantype EntryMethod amount
113                                         invoicenum ordernum Zipcode Address CVV2 CF appcode/);
114
115    $post_data{'EntryMethod'} = 0;   # hand entered, as opposed to swiped through a card reader
116    $post_data{'CF'} = 'ON';         # return comma-delimited data
117
118    my $pd = make_form(%post_data);
119    my $s = $self->server();
120    my $p = $self->port();
121    my $t = $self->path();
122    my $r = $self->{_content}->{referer};
123    my($page,$server_response,%headers) = post_https($s,$p,$t,$r,$pd);
124
125    my @col = split(',', $page);
126
127    $self->server_response($page);
128    if($col[0] eq "0" ) {
129        $self->is_success(1);
130        $self->result_code($col[1]);
131        $self->authorization($col[1]);
132    } else {
133        $self->is_success(0);
134        $self->result_code($col[1]);
135        $self->error_message($col[2]);
136    }
137
138    $self->debug("<no response code, debug info follows>\n".
139      "HTTPS response:\n  $server_response\n\n".
140      "HTTPS headers:\n  ".
141        join("\n  ", map { "$_ => ". $headers{$_} } keys %headers ). "\n\n".
142      "POST Data:\n  ".
143        join("\n  ", map { "$_ => ". $post_data{$_} } keys %post_data ). "\n\n".
144      "Raw HTTPS content:\n  $page");
145}
146
1471;
148__END__
149
150=head1 NAME
151
152Business::OnlinePayment::iAuthorizer - iAuthorizer.net backend for Business::OnlinePayment
153
154=head1 SYNOPSIS
155
156  use Business::OnlinePayment;
157
158  my $tx = new Business::OnlinePayment("iAuthorizer");
159  $tx->content('login'       => '...', # login, password, and serial for your account
160               'password'    => '...',
161               'serial'      => '...',
162               'action'      => 'Normal Authorization',
163               'card_number' => '4012888888881',  # test card
164               'expiration'  => '05/05',
165               'amount'      => '1.00',
166               'address'     => '123 Anystreet',
167               'zip'         => '12345',
168               'cvv2'        => '1234',
169              );
170
171  $tx->submit();
172
173  if($tx->is_success()) {
174      print "Card processed successfully: ".$tx->authorization."\n";
175  } else {
176      print "Card was rejected: ".$tx->error_message."\n";
177  }
178
179=head1 SUPPORTED TRANSACTION TYPES
180
181
182
183=head2 Credit Card transactions
184
185All credit card transactions require the login, password, serial, action,
186amount, card_number and expiration fields.
187
188The type field is never required, as the module does not support
189check transactions.
190
191The action field may be filled out as follows:
192
193=head3 Normal Authorization, Authorization Only, and Credit
194
195   The API documentation calls these Purchase, Authorization Only and Return.
196
197=head3 Post Authorization and Void
198
199   Refered to as Force and Void transaction types in the API documentation,
200   you must also pass in the authorization code (in the authorization field)
201   that you recieved with the original transaction.
202
203=head2 Check transactions
204
205Check transactions are not supported by this module. It would not be
206difficult to add, but I will not be needing it, so I may not get to
207it. Feel free to submit a patch :).
208
209=head1 DESCRIPTION
210
211For detailed information see L<Business::OnlinePayment>.
212
213=head1 COMPATIBILITY
214
215This module implements iAuthorizer.net's API, but does not support
216check transactions or the 'post back' response method.
217
218This module has been certified by iAuthorizer.
219
220=head1 AUTHOR
221
222Copyright (c) 2003 Daniel Brooks <db48x@yahoo.com>
223
224Many thanks to Jason Kohles and Ivan Kohler, who wrote and maintain
225Business::OnlinePayment::AuthorizeNet, which I borrowed heavily from
226while building this module.
227
228The iAuthorizer.net service is required before this module will function,
229however the module itself is free software and may be redistributed and/or
230modified under the same terms as Perl itself.
231
232=head1 SEE ALSO
233
234L<Business::OnlinePayment>.
235
236=cut
237
238