--- /dev/null
+package Business::OnlinePayment::Capstone;\r
+\r
+use strict;\r
+use Carp;\r
+#use Tie::IxHash;\r
+use URI::Escape;\r
+use Business::OnlinePayment 3;\r
+use Business::OnlinePayment::HTTPS 0.03;\r
+use vars qw($VERSION $DEBUG @ISA);\r
+\r
+@ISA = qw(Business::OnlinePayment::HTTPS);\r
+$VERSION = '0.01';\r
+$DEBUG = 0;\r
+\r
+sub set_defaults {\r
+ my $self = shift;\r
+\r
+ $self->server('www.capstonepay.com');\r
+ $self->port('443');\r
+ $self->path('/cgi-bin/client/transaction.cgi');\r
+\r
+ $self->build_subs(qw( order_number avs_code cvv2_response ));\r
+}\r
+\r
+sub submit {\r
+ my($self) = @_;\r
+\r
+ my $action = $self->{_content}{'action'};\r
+ if ( $self->{_content}{'action'} =~ /^\s*normal\s*authorization\s*$/i ) {\r
+ $action = 'authpostauth';\r
+ } elsif ( $self->{_content}{'action'} =~ /^\s*authorization\s*only\s*$/i ) {\r
+ $action = 'auth';\r
+ } elsif ( $self->{_content}{'action'} =~ /^\s*post\s*authorization\s*$/i ) {\r
+ $action = 'postauth';\r
+ } elsif ( $self->{_content}{'action'} =~ /^\s*void\s*$/i ) {\r
+ $action = 'void';\r
+ } elsif ( $self->{_content}{'action'} =~ /^\s*credit\s*$/i ) {\r
+ $action = 'return';\r
+ }\r
+\r
+ #$self->map_fields();\r
+ $self->revmap_fields(\r
+ merchantid =>'login',\r
+ account_password => 'password',\r
+ action => \$action,\r
+ amount => 'amount',\r
+ name => 'name',\r
+ address1 => 'address',\r
+ #address2\r
+ city => 'city',\r
+ state => 'state',\r
+ postal => 'zip',\r
+ country => 'country',\r
+ currency => \'USD', #XXX fix me\r
+ email => 'email',\r
+ ipaddress => 'customer_ip',\r
+ card_num => 'card_number',\r
+ #card_exp => 'expiration', #strip /\r
+ card_cvv => 'cvv2',\r
+ #start_date => 'card_start', #strip /\r
+ issue_num => 'issue_number',\r
+ #bank_name #XXX fix to support ACH\r
+ #bank_phone #XXX fix to support ACH\r
+ orderid => 'order_number',\r
+ custom0 => 'description',\r
+ );\r
+\r
+\r
+ # => 'order_type',\r
+ # => 'transaction_type',\r
+\r
+ #authorization => \r
+\r
+ #company =>\r
+ #country =>\r
+ #phone => \r
+ #fax =>\r
+\r
+ #invoice_number =>\r
+ #customer_id =>\r
+ #authorization => 'txn_number'\r
+\r
+ # XXXfix check required fields!\r
+# if ( $action =~ /^(purchase|preauth|ind_refund)$/ ) {\r
+#\r
+# $self->required_fields(\r
+# qw( login password amount card_number expiration )\r
+# );\r
+#\r
+ $self->{_content}{'expiration'} =~ /^(\d+)\D+\d*(\d{2})$/\r
+ or croak "unparsable expiration ". $self->{_content}{expiration};\r
+ my( $month, $year ) = ( $1, $2 );\r
+ $month = '0'. $month if $month =~ /^\d$/;\r
+ $self->{_content}{card_exp} = $month.$year;\r
+\r
+ if ( $self->{_content}{'card_start'} ) {\r
+ $self->{_content}{'card_start'} =~ /^(\d+)\D+\d*(\d{2})$/\r
+ or croak "unparsable expiration ". $self->{_content}{card_start};\r
+ my( $month, $year ) = ( $1, $2 );\r
+ $month = '0'. $month if $month =~ /^\d$/;\r
+ $self->{_content}{start_date} = $month.$year;\r
+ }\r
+\r
+# $self->generate_order_id;\r
+#\r
+# $self->{_content}{amount} = sprintf('%.2f', $self->{_content}{amount} );\r
+#\r
+# } elsif ( $action eq 'completion' || $action eq 'void' ) {\r
+#\r
+# $self->required_fields( qw( login password order_number authorization ) );\r
+#\r
+# } elsif ( $action eq 'refund' ) {\r
+#\r
+# $self->required_fields(\r
+# qw( login password order_number authorization )\r
+# );\r
+#\r
+# }\r
+\r
+ #warn $self->get_fields('zip');\r
+ #warn $self->get_fields('postal');\r
+\r
+ $self->{'_content'}{country} ||= 'US';\r
+\r
+ #tie my %post_data, 'Tie::IxHash', $self->get_fields(qw(\r
+ my %post_data = $self->get_fields(qw(\r
+ merchantid\r
+ account_password\r
+ action\r
+ amount\r
+ name\r
+ address1\r
+ city\r
+ state\r
+ postal\r
+ country\r
+ currency\r
+ email\r
+ ipaddress\r
+ card_num\r
+ card_exp\r
+ card_cvv\r
+ state_date\r
+ issue_num\r
+ bank_name\r
+ bank_phone\r
+ orderid\r
+ custom0\r
+ ));\r
+\r
+ warn join("\n", map { "$_: ". $post_data{$_} } keys %post_data )\r
+ if $DEBUG;\r
+\r
+ #my( $page, $response, @reply_headers) = $self->https_post( \%post_data );\r
+ my( $page, $response, @reply_headers) = $self->https_post( %post_data );\r
+\r
+ #my %reply_headers = @reply_headers;\r
+ #warn join('', map { " $_ => $reply_headers{$_}\n" } keys %reply_headers )\r
+ # if $DEBUG;\r
+\r
+ #XXX check $response and die if not 200?\r
+\r
+ $self->server_response($page);\r
+\r
+ #warn "****** $page *******";\r
+\r
+ $page =~ s/^\n+//;\r
+\r
+ my %result = map { \r
+ /^(\w+)=(.*)$/ or die "can't parse response: $_";\r
+ ($1, uri_unescape($2));\r
+ }\r
+ split(/\&/, $page);\r
+\r
+ $self->result_code( $result{'status_code'} );\r
+ $self->avs_code( $result{'avs_resp'} );\r
+ $self->cvv2_response( $result{'cvv_resp'} );\r
+\r
+ if ( $result{'status'} eq 'good' ) {\r
+ $self->is_success(1);\r
+ $self->authorization( $result{'auth_code'} );\r
+ $self->order_number( $result{'orderid'} );\r
+ } elsif ( $result{'status'} =~ /^(bad|error|fraud)$/ ) {\r
+ $self->is_success(0);\r
+ $self->error_message("$1: ". $result{'status_msg'});\r
+ } else {\r
+ die "unparsable response received from gateway".\r
+ ( $DEBUG ? ": $page" : '' );\r
+ }\r
+\r
+}\r
+\r
+sub revmap_fields {\r
+ my($self, %map) = @_;\r
+ my %content = $self->content();\r
+ foreach(keys %map) {\r
+# warn "$_ = ". ( ref($map{$_})\r
+# ? ${ $map{$_} }\r
+# : $content{$map{$_}} ). "\n";\r
+ $content{$_} = ref($map{$_})\r
+ ? ${ $map{$_} }\r
+ : $content{$map{$_}};\r
+ }\r
+ $self->content(%content);\r
+}\r
+\r
+1;\r
+\r
+__END__\r
+\r
+=head1 NAME\r
+\r
+Business::OnlinePayment::Capstone - CapstonePay backend module for Business::OnlinePayment\r
+\r
+=head1 SYNOPSIS\r
+\r
+ use Business::OnlinePayment;\r
+\r
+ ####\r
+ # One step transaction, the simple case.\r
+ ####\r
+\r
+ my $tx = new Business::OnlinePayment("Capstone");\r
+ $tx->content(\r
+ type => 'VISA',\r
+ login => 'Merchant ID',\r
+ password => 'API password',\r
+ action => 'Normal Authorization',\r
+ description => 'Business::OnlinePayment test',\r
+ amount => '49.95',\r
+ name => 'Tofu Beast',\r
+ address => '123 Anystreet',\r
+ city => 'Anywhere',\r
+ state => 'UT',\r
+ zip => '84058',\r
+ phone => '420-867-5309',\r
+ email => 'tofu.beast@example.com',\r
+ card_number => '4005550000000019',\r
+ expiration => '08/06',\r
+ card_start => '05/04', #switch/solo \r
+ issue_number => '5678', #\r
+ cvv2 => '1234', #optional\r
+ );\r
+ $tx->submit();\r
+\r
+ if($tx->is_success()) {\r
+ print "Card processed successfully: ".$tx->authorization."\n";\r
+ } else {\r
+ print "Card was rejected: ".$tx->error_message."\n";\r
+ }\r
+\r
+=head1 SUPPORTED TRANSACTION TYPES\r
+\r
+=head2 CC, Visa, MasterCard, American Express, Discover\r
+\r
+Content required: type, login, password, action, amount, card_number, expiration.\r
+\r
+=head1 PREREQUISITES\r
+\r
+ URI::Escape\r
+ #Tie::IxHash\r
+\r
+ Net::SSLeay _or_ ( Crypt::SSLeay and LWP )\r
+\r
+=head1 DESCRIPTION\r
+\r
+For detailed information see L<Business::OnlinePayment>.\r
+\r
+=head1 NOTE\r
+\r
+=head1 AUTHOR\r
+\r
+Ivan Kohler <ivan-capstone@420.am>\r
+\r
+=head1 SEE ALSO\r
+\r
+perl(1). L<Business::OnlinePayment>.\r
+\r
+=cut\r
+\r