--- /dev/null
+## Business::OnlinePayment::Skipjack
+##
+## Original Skipjack.pm developed by New York Connect Net (http://nyct.net)
+## Michael Bacarella <mbac@nyct.net>
+##
+## Modified for GetCareer.com by Slipstream.com
+## Troy Davis <troy@slipstream.com>
+##
+## 'Adapted' (completely rewritten) for Business::OnlinePayment
+## by Fire2Wire Internet Services (http://www.fire2wire.com)
+## Mark Wells <mark@pc-intouch.com>
+## Kristian Hoffmann <khoff@pc-intouch.com>
+## James Switzer <jamess@fire2wire.com>
+
+## Required packages:
+## Net::SSLeay
+## Text::CSV
+## Business::OnlinePayment
+
+
+package Business::OnlinePayment::Skipjack;
+
+use strict;
+use Business::OnlinePayment;
+use Net::SSLeay qw(post_https make_form);
+use Text::CSV;
+use vars qw(@ISA @EXPORT @EXPORT_OK);
+
+#$VERSION="0.1";
+
+require Exporter;
+
+@ISA = qw(Exporter AutoLoader Business::OnlinePayment);
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+@EXPORT = qw();
+@EXPORT_OK = qw();
+
+my %CC_ERRORS = (
+ '-1' => 'Invalid length (-1)',
+ '-35' => 'Invalid credit card number (-35)',
+ '-37' => 'Failed communication (-37)',
+ '-39' => 'Serial number is too short (-39)',
+ '-51' => 'The zip code is invalid',
+ '-52' => 'The shipto zip code is invalid',
+ '-53' => 'Length of expiration date (-53)',
+ '-54' => 'Length of account number date (-54)',
+ '-55' => 'Length of street address (-55)',
+ '-56' => 'Length of shipto street address (-56)',
+ '-57' => 'Length of transaction amount (-57)',
+ '-58' => 'Length of name (-58)',
+ '-59' => 'Length of location (-59)',
+ '-60' => 'Length of state (-60)',
+ '-61' => 'Length of shipto state (-61)',
+ '-62' => 'Length of order string (-62)',
+ '-64' => 'Invalid phone number (-64)',
+ '-65' => 'Empty name (-65)',
+ '-66' => 'Empty email (-66)',
+ '-67' => 'Empty street address (-66)',
+ '-68' => 'Empty city (-68)',
+ '-69' => 'Empty state (-69)',
+ '-70' => 'Empty zip code (-70)',
+ '-71' => 'Empty order number (-71)',
+ '-72' => 'Empty account number (-72)',
+ '-73' => 'Empty expiration month (-73)',
+ '-74' => 'Empty expiration year (-74)',
+ '-75' => 'Empty serial number (-75)',
+ '-76' => 'Empty transaction amount (-76)',
+ '-79' => 'Length of customer name (-79)',
+ '-80' => 'Length of shipto customer name (-80)',
+ '-81' => 'Length of customer location (-81)',
+ '-82' => 'Length of customer state (-82)',
+ '-83' => 'Length of shipto phone (-83)',
+ '-84' => 'Pos Error duplicate ordernumber (-84)',
+ '-91' => 'Pos Error CVV2 (-91)',
+ '-92' => 'Pos Error Approval Code (-92)',
+ '-93' => 'Pos Error Blind Credits Not Allowed (-93)',
+ '-94' => 'Pos Error Blind Credits Failed (-94)',
+ '-95' => 'Pos Error Voice Authorizations Not Allowed (-95)',
+ );
+
+my %AVS_CODES = (
+ 'X' => 'Exact match, 9 digit zip',
+ 'Y' => 'Exact match, 5 digit zip',
+ 'A' => 'Address match only',
+ 'W' => '9 digit match only',
+ 'Z' => '5 digit match only',
+ 'N' => 'No address or zip match',
+ 'U' => 'Address unavailable',
+ 'R' => 'Issuer system unavailable',
+ 'E' => 'Not a mail/phone order',
+ 'S' => 'Service not supported'
+ );
+
+my %FIELDS = (
+ name => 'sjname',
+ email => 'Email',
+ address => 'Streetaddress',
+ city => 'City',
+ state => 'State',
+ zip => 'Zipcode',
+ invoice_number => 'Ordernumber',
+ card_number => 'Accountnumber',
+ exp_month => 'Month',
+ exp_year => 'Year',
+ amount => 'Transactionamount',
+ orderstring => 'Orderstring',
+ phone => 'Shiptophone',
+ login => 'Serialnumber',
+ );
+
+
+sub _gen_ordernum { return int(rand(4000000000)); }
+
+sub set_defaults
+{
+ my $self = shift;
+
+ # For production
+ $self->server('www.skipjackic.com');
+ $self->path('/scripts/evolvcc.dll?AuthorizeAPI');
+
+ # For auth testing
+ #$self->server('developer.skipjackic.com'); # test mode
+ #$self->path('/scripts/evolvcc.dll?AuthorizeAPI');
+
+ # For comms testing
+ #$self->server('www.skipjackic.com');
+ #$self->path('/secure/echo.asp');
+
+ $self->port(443);
+
+ return;
+}
+
+
+sub submit
+{
+ my $self = shift;
+ my %c = $self->content;
+ my (%input, %output);
+ my ($page, $response, %reply_headers);
+
+# if($c{type} and $c{type} ne 'normal authorization') {
+ if($c{type} eq 'credit') {
+ warn 'Business::OnlinePayment::Skipjack does not support "' .
+ $c{type}. '"transactions';
+ return;
+ }
+
+ # FIXME!
+ # This should be set from %processor_info.
+
+ # Or, if we want, from $c{login}.
+
+ $c{expiration} =~ /(\d\d?).*(\d\d?)/; # extremely crude way to split the month and year
+ $c{exp_month} = sprintf('%02d',$1);
+ $c{exp_year} = sprintf('%02d',$2);
+
+ $c{invoice_number} = _gen_ordernum unless $c{invoice_number};
+
+ $c{orderstring} = '0~'.$c{description}.'~'.$c{amount}.'~1~N~||'
+ unless $c{orderstring};
+
+ %input = map { ($FIELDS{$_} || $_), $c{$_} } keys(%c);
+
+ ($page, $response, %reply_headers) =
+ post_https($self->server,
+ $self->port,
+ $self->path,
+ '',
+ make_form(%input));
+
+
+ %output = parse_Authorize_API($page);
+
+ $self->{_result} = \%output;
+ $self->authorization($output{'AUTHCODE'});
+ return;
+}
+
+sub is_success
+{
+ my $self = shift;
+
+ return ($self->{_result}->{'szIsApproved'} == 1);
+}
+
+sub error_message
+{
+ my $self = shift;
+ my $r;
+
+ if($self->is_success) { return ''; }
+ if(($r = $self->{_result}->{'szReturnCode'}) < 0) { return $CC_ERRORS{$r}; }
+ if($r = $self->{_result}->{'szAVSResponseMessage'}) { return $r; }
+ if($r = $self->{_result}->{'szAuthorizationDeclinedMessage'}) { return $r; }
+}
+
+sub parse_Authorize_API
+{
+
+ my $page = shift;
+ my %output;
+ my $csv_keys = new Text::CSV;
+ my $csv_values = new Text::CSV;
+
+ my ($keystring, $valuestring) = split(/\r\n/, $page);
+ $csv_keys->parse($keystring);
+ $csv_values->parse($valuestring);
+ @output{$csv_keys->fields()} = $csv_values->fields();
+
+ return %output;
+
+}
+
+__END__
+
+1;
+