noise reduction
[Business-OnlinePayment-USAePay.git] / USAePay.pm
1 package Business::OnlinePayment::USAePay;
2
3 use strict;
4 use Carp;
5 use Business::OnlinePayment 3;
6 use Business::OnlinePayment::HTTPS;
7 use Digest::MD5 qw(md5_hex);
8 use URI::Escape;
9 use vars qw($VERSION @ISA $DEBUG);
10
11 @ISA = qw(Business::OnlinePayment::HTTPS);
12 $VERSION = '0.01';
13
14 $DEBUG = 0;
15
16 my $default_path = '/gate.php';
17 my $default_cert_path = '/secure/gate.php';
18
19 sub set_defaults {
20     my $self = shift;
21     $self->server('www.usaepay.com');
22     $self->port('443');
23     $self->path($default_path);
24
25     $self->build_subs(qw(order_number));
26 }
27
28 sub map_fields {
29   my($self) = shift;
30
31   my %content = $self->content();
32
33   my %types = ('visa'             => 'CC',
34                'mastercard'       => 'CC',
35                'american express' => 'CC',
36                'discover'         => 'CC',
37                'check'            => 'ECHECK',
38               );
39   $content{'type'} = $types{lc($content{'type'})} || $content{'type'};
40   $self->transaction_type($content{'type'});
41
42   my %actions;
43   my %cc_actions = ('normal authorization' => 'sale',
44                     'authorization only'   => 'authonly',
45                     'post authorization'   => 'postauth',
46                    );
47   my %ec_actions = ('normal authorization' => 'check',
48                     'credit'               => 'checkcredit',
49                    );
50   if ($content{'type'} eq 'CC') {
51     (%actions) = (%cc_actions);
52   }elsif ($content{'type'} eq 'ECHECK') {
53     (%actions) = (%ec_actions);
54   }
55   $content{'action'} = $actions{lc($content{'action'})} || $content{'action'};
56                  
57   $content{'expiration'} =~ s/\D//g;
58
59   $content{'md5hash'} = md5_hex(join(':', map "$content{$_}", qw(action password amount invoice_number md5key))) if defined $content{'password'};
60
61   $self->content(%content);
62 }
63
64 sub submit {
65     my($self) = @_;
66
67     $self->map_fields();
68
69     $self->remap_fields(
70       login            => 'UMkey',
71       md5key           => 'UMmd5key',
72       md5hash          => 'UMmd5hash',
73       card_number      => 'UMcard',
74       expiration       => 'UMexpir',
75       amount           => 'UMamount',
76       invoice_number   => 'UMinvoice',
77       description      => 'UMdescription',
78       customer_id      => 'UMcustid',
79       cvv2             => 'UMcvv2',
80       email            => 'UMcustemail',
81       name             => 'UMname',
82       address          => 'UMstreet',
83       zip              => 'UMzip',
84       customer_ip      => 'UMip',
85       order_number     => 'UMrefNum',
86       authorization    => 'UMauthCode',
87       routing_code     => 'UMrouting',
88       account_number   => 'UMaccount',
89       customer_ssn     => 'UMssn',
90     );
91     my %content = $self->content;
92     if ( $DEBUG ) {
93       warn "content:$_ => $content{$_}\n" foreach keys %content;
94     }
95
96     my @required_fields = qw(type action login);
97
98     if ($self->transaction_type() eq 'CC' ) {
99       push @required_fields, qw/card_number expiration amount invoice_number name address zip/;
100       if ($self->{_content}->{action} eq 'postauth') {
101         push @required_fields, qw/authorization/;
102       }
103       if (    $self->{_content}->{action} eq 'void'
104            || $self->{_content}->{action} eq 'capture') {
105         push @required_fields, qw/order_number/;
106       }
107     }elsif ($self->transaction_type() eq 'ECHECK' ) {
108       push @required_fields, qw/routing_code account_number amount invoice_number name customer_ssn/;
109     } else {
110       croak("USAePay can't handle transaction type: ".
111             $self->transaction_type());
112     }
113
114     $self->required_fields(@required_fields);
115
116     my %post_data = $self->get_fields( map "$_", qw(
117       UMcommand UMkey UMmd5hash UMmd5key UMauthCode UMrefNum UMcard UMexpir
118       UMrouting UMaccount UMamount Umtax UMnontaxable UMtip UMshipping
119       UMdiscount UMsubtotal UMcustid UMinvoice UMorderid UMponum UMdescription
120       UMcvv2 UMcustemail UMcustreceipt UMname UMStreet UMzip UMssn UMdlnum
121       UMdlstate UMclerk UMterminal UMtable UMip UMsoftware UMredir
122       UMredirApproved UMredirDeclined UMechofields UMtestmode
123     ) );
124     $post_data{'UMtestmode'} = $self->test_transaction() ? 1 : 0;
125     $post_data{'UMsoftware'} = __PACKAGE__. " $VERSION";
126     if ( $DEBUG ) {
127       warn "post_data:$_ => $post_data{$_}\n" foreach keys %post_data;
128     }
129
130     my($page,$server_response) = $self->https_post(%post_data);
131     if ( $DEBUG ) {
132       warn "response page: $page\n";
133     }
134
135     my $response;
136     if ($server_response =~ /200/){
137       $response = {map { split '=', $_, 2 } split '&', $page};
138     }else{
139       $response->{UMstatus} = 'Error';
140       $response->{UMerror} = $server_response;
141     }
142
143     $response->{$_} =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg
144       foreach keys %$response;
145
146     if ( $DEBUG ) {
147       warn "response:$_ => $response->{$_}\n" foreach keys %$response;
148     }
149
150     if ( $response->{UMstatus} =~ /^Approved/ ) {
151       $self->is_success(1);
152       $self->authorization($response->{UMauthCode});
153     } else {
154       $self->is_success(0);
155     }
156     $self->result_code($response->{UMresult});
157     $self->error_message($response->{UMerror});
158     $self->server_response($response);
159 }
160
161 1;
162 __END__
163
164 =head1 NAME
165
166 Business::OnlinePayment::USAePay - USA ePay backend for Business::OnlinePayment
167
168 =head1 SYNOPSIS
169
170   use Business::OnlinePayment;
171
172   my $tx = new Business::OnlinePayment("USAePay");
173   $tx->content(
174       login          => 'igztOatyqbpd1wsxijl4xnxjodldwdxR', #USA ePay source key
175       action         => 'Normal Authorization',
176       description    => 'Business::OnlinePayment test',
177       amount         => '49.95',
178       invoice_number => '100100',
179       name           => 'Tofu Beast',
180       card_number    => '46464646464646',
181       expiration     => '11/08',
182       address        => '1234 Bean Curd Lane, San Francisco',
183       zip            => '94102',
184   );
185   $tx->submit();
186
187   if($tx->is_success()) {
188       print "Card processed successfully: ".$tx->authorization."\n";
189   } else {
190       print "Card was rejected: ".$tx->error_message."\n";
191   }
192
193 =head1 DESCRIPTION
194
195 For detailed information see L<Business::OnlinePayment>.
196
197 =head1 NOTE
198
199 =head1 COMPATIBILITY
200
201 This module implements USAePay's CGI Gateway API v2.9.5.  See
202 http://www.usaepay.com/topics/api.html for details.
203
204 =head1 AUTHOR
205
206 Jeff Finucane <jeff@cmh.net>
207
208 =head1 SEE ALSO
209
210 perl(1). L<Business::OnlinePayment>.
211
212 =cut
213