1 package Business::OnlinePayment::Capstone;
\r
7 use Business::OnlinePayment 3;
\r
8 use Business::OnlinePayment::HTTPS 0.03;
\r
9 use vars qw($VERSION $DEBUG @ISA);
\r
11 @ISA = qw(Business::OnlinePayment::HTTPS);
\r
18 $self->server('www.capstonepay.com');
\r
20 $self->path('/cgi-bin/client/transaction.cgi');
\r
22 $self->build_subs(qw( order_number avs_code cvv2_response ));
\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
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
37 } elsif ( $self->{_content}{'action'} =~ /^\s*credit\s*$/i ) {
\r
41 #$self->map_fields();
\r
42 $self->revmap_fields(
\r
43 merchantid =>'login',
\r
44 account_password => 'password',
\r
48 address1 => 'address',
\r
53 country => 'country',
\r
54 currency => \'USD', #XXX fix me
\r
56 ipaddress => 'customer_ip',
\r
57 card_num => 'card_number',
\r
58 #card_exp => 'expiration', #strip /
\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
70 # => 'transaction_type',
\r
81 #authorization => 'txn_number'
\r
83 # XXXfix check required fields!
\r
84 # if ( $action =~ /^(purchase|preauth|ind_refund)$/ ) {
\r
86 # $self->required_fields(
\r
87 # qw( login password amount card_number expiration )
\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
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
104 # $self->generate_order_id;
\r
106 # $self->{_content}{amount} = sprintf('%.2f', $self->{_content}{amount} );
\r
108 # } elsif ( $action eq 'completion' || $action eq 'void' ) {
\r
110 # $self->required_fields( qw( login password order_number authorization ) );
\r
112 # } elsif ( $action eq 'refund' ) {
\r
114 # $self->required_fields(
\r
115 # qw( login password order_number authorization )
\r
120 #warn $self->get_fields('zip');
\r
121 #warn $self->get_fields('postal');
\r
123 $self->{'_content'}{country} ||= 'US';
\r
125 #tie my %post_data, 'Tie::IxHash', $self->get_fields(qw(
\r
126 my %post_data = $self->get_fields(qw(
\r
151 warn join("\n", map { "$_: ". $post_data{$_} } keys %post_data )
\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
157 #my %reply_headers = @reply_headers;
\r
158 #warn join('', map { " $_ => $reply_headers{$_}\n" } keys %reply_headers )
\r
161 #XXX check $response and die if not 200?
\r
163 $self->server_response($page);
\r
165 #warn "****** $page *******";
\r
169 my %result = map {
\r
170 /^(\w+)=(.*)$/ or die "can't parse response: $_";
\r
171 ($1, uri_unescape($2));
\r
173 split(/\&/, $page);
\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
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
187 die "unparsable response received from gateway".
\r
188 ( $DEBUG ? ": $page" : '' );
\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
199 # : $content{$map{$_}} ). "\n";
\r
200 $content{$_} = ref($map{$_})
\r
202 : $content{$map{$_}};
\r
204 $self->content(%content);
\r
213 Business::OnlinePayment::Capstone - CapstonePay backend module for Business::OnlinePayment
\r
217 use Business::OnlinePayment;
\r
220 # One step transaction, the simple case.
\r
223 my $tx = new Business::OnlinePayment("Capstone");
\r
226 login => 'Merchant ID',
\r
227 password => 'API password',
\r
228 action => 'Normal Authorization',
\r
229 description => 'Business::OnlinePayment test',
\r
231 name => 'Tofu Beast',
\r
232 address => '123 Anystreet',
\r
233 city => 'Anywhere',
\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
246 if($tx->is_success()) {
\r
247 print "Card processed successfully: ".$tx->authorization."\n";
\r
249 print "Card was rejected: ".$tx->error_message."\n";
\r
252 =head1 SUPPORTED TRANSACTION TYPES
\r
254 =head2 CC, Visa, MasterCard, American Express, Discover
\r
256 Content required: type, login, password, action, amount, card_number, expiration.
\r
258 =head1 PREREQUISITES
\r
263 Net::SSLeay _or_ ( Crypt::SSLeay and LWP )
\r
267 For detailed information see L<Business::OnlinePayment>.
\r
273 Ivan Kohler <ivan-capstone@420.am>
\r
277 perl(1). L<Business::OnlinePayment>.
\r