add email->Email mapping
[Business-OnlinePayment-TransactionCentral.git] / lib / Business / OnlinePayment / TransactionCentral.pm
1 package Business::OnlinePayment::TransactionCentral;
2
3 use 5.005;
4 use strict;
5 use Carp;
6 use Business::OnlinePayment 3;
7 use Business::OnlinePayment::HTTPS 0.02;
8 use vars qw($VERSION @ISA $DEBUG);
9
10 @ISA = qw(Business::OnlinePayment::HTTPS);
11 $VERSION = '0.05';
12 $DEBUG = 0;
13
14 sub set_defaults {
15     my $self = shift;
16
17     $self->server('webservices.primerchants.com');
18     $self->port('443');
19     $self->path('/billing/TransactionCentral/');
20
21     $self->build_subs(qw( order_number avs_code cvv2_response
22                           response_page response_code response_headers
23                      ));
24 }
25
26 sub submit {
27   my($self) = @_;
28
29   $self->revmap_fields(
30     'MerchantID'    => 'login',
31     'RegKey'        => 'password',
32     'Amount'        => 'amount',
33 #    'CreditAmount'  => 'amount',
34     'AccountNo'     => 'card_number',
35     'NameonAccount' => 'name',
36     'AVSADDR'       => 'address',
37     'AVSZIP'        => 'zip',
38     'Email'         => 'email',
39     'CCRURL'        => \'',
40     'CVV2'          => 'cvv2',
41     'TransID'       => 'order_number',
42     'TRANSROUTE'    => 'routing_code',
43   );
44
45   #XXX also set required fields here...
46
47   my @required_fields = qw(login password);
48   my %content = $self->content();
49   my $action = $content{'action'};
50   my $url = $self->path;
51   if (
52     $content{'type'} =~ /^(cc|visa|mastercard|american express|discover)$/i
53   ) {
54
55     if ( $action =~ /^\s*normal\s*authorization\s*$/i ) {
56       $url .= 'processCC.asp';
57
58       #REFID
59       $content{'REFID'} = int(rand(2**31));
60
61       #CCMonth & CCYear
62       $content{'expiration'} =~ /^(\d+)\D+\d*(\d{2})$/
63         or croak "unparsable expiration ". $content{'expiration'};
64       my( $month, $year ) = ( $1, $2 );
65       $month = '0'. $month if $month =~ /^\d$/;
66       $content{'CCMonth'} = $month;
67       $content{'CCYear'} = $year;
68
69       push @required_fields, qw( amount card_number expiration
70                                  name address zip
71                                );
72
73     } elsif ( $action =~ /^\s*authorization\s*only\s*$/i ) {
74       croak "Authorizaiton Only is not supported by Transaction Central";
75     } elsif ( $action =~ /^\s*post\s*authorization\s*$/i ) {
76       croak "Post Authorizaiton is not supported by Transaction Central";
77     } elsif ( $action =~ /^\s*(void|credit)\s*$/i ) {
78       $url .= 'voidcreditcconline.asp';
79
80       $content{'CreditAmount'} = delete $content{'Amount'};
81
82     } else {
83       croak "Unknown action $action";
84     }
85
86   } elsif ( $content{'type'} =~ /^e?check$/i ) {
87
88     if ( $action =~ /^\s*normal\s*authorization\s*$/i ) {
89       $url .= 'processcheckonline.asp';
90       $content{'AccountNo'} = $content{'account_number'};
91       $content{'TRANSTYPE'} =
92         ( exists($content{account_type}) && $content{account_type} =~ /^s/i )
93         ? 'SA'
94         : 'CK';
95
96       push @required_fields, qw( amount account_number routing_code
97                                  name
98                                );
99
100     } elsif ( $action =~ /^\s*authorization\s*only\s*$/i ) {
101       croak "Authorizaiton Only is not supported by Transaction Central";
102     } elsif ( $action =~ /^\s*post\s*authorization\s*$/i ) {
103       croak "Post Authorizaiton is not supported by Transaction Central";
104     } elsif ( $action =~ /^\s*(void|credit)\s*$/i ) {
105       $url .= 'addckcreditupdtonline.asp';
106     } else {
107       croak "Unknown action $action";
108     }
109
110   } else {
111     croak 'Unknown type: '. $content{'type'};
112   }
113   $self->path($url);
114   $self->content(%content);
115
116   $self->required_fields(@required_fields);
117
118   my @fields = qw(
119     MerchantID RegKey Amount REFID AccountNo CCMonth CCYear NameonAccount
120     AVSADDR AVSZIP CCRURL CVV2 USER1 USER2 USER3 USER4 TrackData
121     TransID CreditAmount
122     DESCRIPTION DESCDATE TRANSTYPE TRANSROUTE
123   );
124
125   my( $page, $response, %reply_headers ) =
126     $self->https_post( $self->get_fields( @fields ) );
127
128   $self->response_code( $response );
129   $self->response_page( $page );
130   $self->response_headers( \%reply_headers );
131
132   #trim off <html><body> </body></html> around the response we want
133   $page =~ s/^[\s\n]*<html>[\s\n]*<body>[\s\n]*//;
134   $page =~ s/[\s\n]*<\/body>[\s\n]*<\/html>[\s\n]*$//;
135
136   my %return = map { /^(\w+)=(.*)$/ ? ( $1 => $2 ) : () } split(/&/, $page);
137
138   if ( $DEBUG ) { warn "$_ => $return{$_}\n" foreach keys %return; }
139
140   #$self->result_code(   $return{'AVSCode'} );
141   $self->avs_code(      $return{'AVSCode'} );
142   $self->cvv2_response( $return{'CVV2ResponseMsg'} );
143
144   if ( $return{'Auth'} =~ /^\s*(\w+)\s*$/ && lc($1) ne 'declined' ) {
145
146     $self->is_success(1);
147     $self->authorization( $return{'Auth'}   );
148     $self->order_number(  $return{'TransID'} );
149
150   } else {
151
152     $self->is_success(0);
153     $self->error_message( $return{'Notes'} );
154
155   }
156
157 }
158
159 sub revmap_fields {
160     my($self, %map) = @_;
161     my %content = $self->content();
162     foreach(keys %map) {
163 #    warn "$_ = ". ( ref($map{$_})
164 #                         ? ${ $map{$_} }
165 #                         : $content{$map{$_}} ). "\n";
166         $content{$_} = ref($map{$_})
167                          ? ${ $map{$_} }
168                          : $content{$map{$_}};
169     }
170     $self->content(%content);
171 }
172
173 1;
174
175 __END__
176
177 =head1 NAME
178
179 Business::OnlinePayment::TransactionCentral - Transaction Central backend module for Business::OnlinePayment
180
181 =head1 SYNOPSIS
182
183   use Business::OnlinePayment;
184
185   ####
186   # One step transaction, the simple case.
187   ####
188
189   my $tx = new Business::OnlinePayment("TransactionCentral");
190   $tx->content(
191       type           => 'CC',
192       login          => '10011', #MerchantID
193       password       => 'KK48NPYEJHMAH6DK', #Regkey
194       action         => 'Normal Authorization',
195       description    => 'Business::OnlinePayment test',
196       amount         => '49.95',
197       name           => 'Tofu Beast',
198       address        => '123 Anystreet',
199       city           => 'Anywhere',
200       state          => 'UT',
201       zip            => '84058',
202       phone          => '420-867-5309',
203       email          => 'tofu.beast@example.com',
204       card_number    => '4012000000001',
205       expiration     => '08/06',
206       cvv2           => '1234', #optional
207   );
208   $tx->submit();
209
210   if($tx->is_success()) {
211       print "Card processed successfully: ".$tx->authorization."\n";
212   } else {
213       print "Card was rejected: ".$tx->error_message."\n";
214   }
215 =head1 DESCRIPTION
216
217 This is a Business::OnlinePayment backend module for the Transaction Central
218 (MerchantAnywhere, PRIMerchants) gateway.  It is only useful if you have a
219 merchant account with MerchantAnywhere / PRIMerchants:
220
221 http://www.merchantanywhere.com/
222 http://www.merchantanywhere.com/ecshop/TC_elink.htm
223
224 http://www.primerchants.com/
225 http://www.primerchants.com/info/transactioncentral.asp
226
227 =head1 SUPPORTED TRANSACTION TYPES
228
229 =head2 CC, Visa, MasterCard, American Express, Discover
230
231 Content required: type, login, password, action, amount, card_number, expiration, name, address, zip.
232
233 =head2 ECHECK
234
235 Content required: type, login, password, action, amount, account_number, routing_code, name
236
237 =head1 PREREQUISITES
238
239   URI::Escape
240
241   Net::SSLeay _or_ ( Crypt::SSLeay and LWP )
242
243 =head1 DESCRIPTION
244
245 For detailed information see L<Business::OnlinePayment>.
246
247 =head1 NOTE
248
249 The newest publicly available documentation is available at:
250
251 http://www.merchantanywhere.com/ecshop/TC%20Interface%20NEW.pdf
252
253 It is somewhat out-of-date and contains a few discrepancies.  Google
254 "TCInterfaceGuide" for current documentation.
255
256 =head1 AUTHOR
257
258 Ivan Kohler <ivan-transactioncentral@420.am>
259
260 =head1 COPYRIGHT AND LICENSE
261
262 Copyright (C) 2006 by Ivan Kohler
263 Copyright (C) 2007 Freeside Internet Services, Inc.
264
265 This library is free software; you can redistribute it and/or modify
266 it under the same terms as Perl itself.
267
268 =head1 SEE ALSO
269
270 perl(1). L<Business::OnlinePayment>.
271
272 =cut