initial import
[Business-OnlinePayment-Capstone.git] / lib / Business / OnlinePayment / Capstone.pm
1 package Business::OnlinePayment::Capstone;\r
2 \r
3 use strict;\r
4 use Carp;\r
5 #use Tie::IxHash;\r
6 use URI::Escape;\r
7 use Business::OnlinePayment 3;\r
8 use Business::OnlinePayment::HTTPS 0.03;\r
9 use vars qw($VERSION $DEBUG @ISA);\r
10 \r
11 @ISA = qw(Business::OnlinePayment::HTTPS);\r
12 $VERSION = '0.01';\r
13 $DEBUG = 0;\r
14 \r
15 sub set_defaults {\r
16     my $self = shift;\r
17 \r
18     $self->server('www.capstonepay.com');\r
19     $self->port('443');\r
20     $self->path('/cgi-bin/client/transaction.cgi');\r
21 \r
22     $self->build_subs(qw( order_number avs_code cvv2_response ));\r
23 }\r
24 \r
25 sub submit {\r
26     my($self) = @_;\r
27 \r
28     my $action = $self->{_content}{'action'};\r
29     if ( $self->{_content}{'action'} =~ /^\s*normal\s*authorization\s*$/i ) {\r
30       $action = 'authpostauth';\r
31     } elsif ( $self->{_content}{'action'} =~ /^\s*authorization\s*only\s*$/i ) {\r
32       $action = 'auth';\r
33     } elsif ( $self->{_content}{'action'} =~ /^\s*post\s*authorization\s*$/i ) {\r
34       $action = 'postauth';\r
35     } elsif ( $self->{_content}{'action'} =~ /^\s*void\s*$/i ) {\r
36       $action = 'void';\r
37     } elsif ( $self->{_content}{'action'} =~ /^\s*credit\s*$/i ) {\r
38       $action = 'return';\r
39     }\r
40 \r
41    #$self->map_fields();\r
42     $self->revmap_fields(\r
43         merchantid          =>'login',\r
44         account_password    => 'password',\r
45         action              => \$action,\r
46         amount              => 'amount',\r
47         name                => 'name',\r
48         address1            => 'address',\r
49         #address2\r
50         city                => 'city',\r
51         state               => 'state',\r
52         postal              => 'zip',\r
53         country             => 'country',\r
54         currency            => \'USD', #XXX fix me\r
55         email               => 'email',\r
56         ipaddress           => 'customer_ip',\r
57         card_num            => 'card_number',\r
58         #card_exp            => 'expiration', #strip /\r
59         card_cvv            => 'cvv2',\r
60         #start_date          => 'card_start', #strip /\r
61         issue_num           => 'issue_number',\r
62         #bank_name   #XXX fix to support ACH\r
63         #bank_phone  #XXX fix to support ACH\r
64         orderid             => 'order_number',\r
65         custom0             => 'description',\r
66       );\r
67 \r
68 \r
69         #                => 'order_type',\r
70         #                => 'transaction_type',\r
71 \r
72         #authorization   => \r
73 \r
74         #company         =>\r
75         #country         =>\r
76         #phone            => \r
77         #fax             =>\r
78 \r
79         #invoice_number  =>\r
80         #customer_id     =>\r
81         #authorization    => 'txn_number'\r
82 \r
83     # XXXfix check required fields!\r
84 #    if ( $action =~ /^(purchase|preauth|ind_refund)$/ ) {\r
85 #\r
86 #      $self->required_fields(\r
87 #        qw( login password amount card_number expiration )\r
88 #      );\r
89 #\r
90       $self->{_content}{'expiration'} =~ /^(\d+)\D+\d*(\d{2})$/\r
91         or croak "unparsable expiration ". $self->{_content}{expiration};\r
92       my( $month, $year ) = ( $1, $2 );\r
93       $month = '0'. $month if $month =~ /^\d$/;\r
94       $self->{_content}{card_exp} = $month.$year;\r
95 \r
96       if ( $self->{_content}{'card_start'} ) {\r
97         $self->{_content}{'card_start'} =~ /^(\d+)\D+\d*(\d{2})$/\r
98           or croak "unparsable expiration ". $self->{_content}{card_start};\r
99         my( $month, $year ) = ( $1, $2 );\r
100         $month = '0'. $month if $month =~ /^\d$/;\r
101         $self->{_content}{start_date} = $month.$year;\r
102       }\r
103 \r
104 #      $self->generate_order_id;\r
105 #\r
106 #      $self->{_content}{amount} = sprintf('%.2f', $self->{_content}{amount} );\r
107 #\r
108 #    } elsif ( $action eq 'completion' || $action eq 'void' ) {\r
109 #\r
110 #      $self->required_fields( qw( login password order_number authorization ) );\r
111 #\r
112 #    } elsif ( $action eq 'refund' ) {\r
113 #\r
114 #      $self->required_fields(\r
115 #        qw( login password order_number authorization )\r
116 #      );\r
117 #\r
118 #    }\r
119 \r
120     #warn $self->get_fields('zip');\r
121     #warn $self->get_fields('postal');\r
122 \r
123     $self->{'_content'}{country} ||= 'US';\r
124 \r
125     #tie my %post_data, 'Tie::IxHash', $self->get_fields(qw(\r
126     my %post_data = $self->get_fields(qw(\r
127       merchantid\r
128       account_password\r
129       action\r
130       amount\r
131       name\r
132       address1\r
133       city\r
134       state\r
135       postal\r
136       country\r
137       currency\r
138       email\r
139       ipaddress\r
140       card_num\r
141       card_exp\r
142       card_cvv\r
143       state_date\r
144       issue_num\r
145       bank_name\r
146       bank_phone\r
147       orderid\r
148       custom0\r
149     ));\r
150 \r
151     warn join("\n", map { "$_: ". $post_data{$_} } keys %post_data )\r
152       if $DEBUG;\r
153 \r
154     #my( $page, $response, @reply_headers) = $self->https_post( \%post_data );\r
155     my( $page, $response, @reply_headers) = $self->https_post( %post_data );\r
156 \r
157     #my %reply_headers = @reply_headers;\r
158     #warn join('', map { "  $_ => $reply_headers{$_}\n" } keys %reply_headers )\r
159     #  if $DEBUG;\r
160 \r
161     #XXX check $response and die if not 200?\r
162 \r
163     $self->server_response($page);\r
164 \r
165     #warn "****** $page *******";\r
166 \r
167     $page =~ s/^\n+//;\r
168 \r
169     my %result = map { \r
170                        /^(\w+)=(.*)$/ or die "can't parse response: $_";\r
171                        ($1, uri_unescape($2));\r
172                      }\r
173                  split(/\&/, $page);\r
174 \r
175     $self->result_code(   $result{'status_code'} );\r
176     $self->avs_code(      $result{'avs_resp'} );\r
177     $self->cvv2_response( $result{'cvv_resp'} );\r
178 \r
179     if ( $result{'status'} eq 'good' ) {\r
180       $self->is_success(1);\r
181       $self->authorization( $result{'auth_code'}   );\r
182       $self->order_number(   $result{'orderid'}     );\r
183     } elsif ( $result{'status'} =~ /^(bad|error|fraud)$/ ) {\r
184       $self->is_success(0);\r
185       $self->error_message("$1: ". $result{'status_msg'});\r
186     } else {\r
187       die "unparsable response received from gateway".\r
188           ( $DEBUG ? ": $page" : '' );\r
189     }\r
190 \r
191 }\r
192 \r
193 sub revmap_fields {\r
194     my($self, %map) = @_;\r
195     my %content = $self->content();\r
196     foreach(keys %map) {\r
197 #    warn "$_ = ". ( ref($map{$_})\r
198 #                         ? ${ $map{$_} }\r
199 #                         : $content{$map{$_}} ). "\n";\r
200         $content{$_} = ref($map{$_})\r
201                          ? ${ $map{$_} }\r
202                          : $content{$map{$_}};\r
203     }\r
204     $self->content(%content);\r
205 }\r
206 \r
207 1;\r
208 \r
209 __END__\r
210 \r
211 =head1 NAME\r
212 \r
213 Business::OnlinePayment::Capstone - CapstonePay backend module for Business::OnlinePayment\r
214 \r
215 =head1 SYNOPSIS\r
216 \r
217   use Business::OnlinePayment;\r
218 \r
219   ####\r
220   # One step transaction, the simple case.\r
221   ####\r
222 \r
223   my $tx = new Business::OnlinePayment("Capstone");\r
224   $tx->content(\r
225       type           => 'VISA',\r
226       login          => 'Merchant ID',\r
227       password       => 'API password',\r
228       action         => 'Normal Authorization',\r
229       description    => 'Business::OnlinePayment test',\r
230       amount         => '49.95',\r
231       name           => 'Tofu Beast',\r
232       address        => '123 Anystreet',\r
233       city           => 'Anywhere',\r
234       state          => 'UT',\r
235       zip            => '84058',\r
236       phone          => '420-867-5309',\r
237       email          => 'tofu.beast@example.com',\r
238       card_number    => '4005550000000019',\r
239       expiration     => '08/06',\r
240       card_start     => '05/04', #switch/solo \r
241       issue_number   => '5678',  #\r
242       cvv2           => '1234', #optional\r
243   );\r
244   $tx->submit();\r
245 \r
246   if($tx->is_success()) {\r
247       print "Card processed successfully: ".$tx->authorization."\n";\r
248   } else {\r
249       print "Card was rejected: ".$tx->error_message."\n";\r
250   }\r
251 \r
252 =head1 SUPPORTED TRANSACTION TYPES\r
253 \r
254 =head2 CC, Visa, MasterCard, American Express, Discover\r
255 \r
256 Content required: type, login, password, action, amount, card_number, expiration.\r
257 \r
258 =head1 PREREQUISITES\r
259 \r
260   URI::Escape\r
261   #Tie::IxHash\r
262 \r
263   Net::SSLeay _or_ ( Crypt::SSLeay and LWP )\r
264 \r
265 =head1 DESCRIPTION\r
266 \r
267 For detailed information see L<Business::OnlinePayment>.\r
268 \r
269 =head1 NOTE\r
270 \r
271 =head1 AUTHOR\r
272 \r
273 Ivan Kohler <ivan-capstone@420.am>\r
274 \r
275 =head1 SEE ALSO\r
276 \r
277 perl(1). L<Business::OnlinePayment>.\r
278 \r
279 =cut\r
280 \r