use warnings;
use strict;
#use vars qw( $DEBUG $me );
+use MIME::Base64;
+use Crypt::OpenSSL::RSA;
our $VERSION = 0.01;
$self->build_subs(qw( order_number avs_code cvv2_response
response_page response_code response_headers
- card_token
+ card_token private_key
));
}
sub submit {
my $self = shift;
- $self->server('test.cardfortress.com');
+ $self->server('test.cardfortress.com') if $self->test_transaction;
- my ($page,$server_response,%headers) = $self->https_post($self->content);
+ my %content = $self->content;
+ $content{$_} = $self->$_() for qw( gateway gateway_login gateway_password );
- die $server_response unless $server_response =~ /^200/;
+ my ($page,$server_response,%headers) = $self->https_post(%content);
- my %response = {};
+ die "$server_response\n" unless $server_response =~ /^200/;
+
+ my %response = ();
#this encoding good enough? wfm... if something's easier for other
#languages they can always use a different URL
foreach my $line ( grep /^\w+=/, split(/\n/, $page) ) {
# response_headers()
# response_page()
+ #handle the challenge/response handshake
+ if ( $self->error_message eq '_challenge' ) { #XXX infinite loop protection?
+
+ die "no private key available" unless $self->private_key;
+
+ #decrypt the challenge with the private key
+ my $challenge = decode_base64($response{'card_challenge'});
+
+ #here is the hardest part to implement at each client side
+ my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($self->private_key);
+ my $response = $rsa_priv->decrypt($challenge);
+
+ #try the transaction again with the challenge response
+ # (B:OP could sure use a better way to alter one value)
+ my %content = $self->content;
+ $content{'card_response'} = encode_base64($response, '');
+ $self->content(%content);
+ $self->submit;
+ }
+
}
1;
'gateway' => 'ProcessingGateway',
'gateway_login' => 'gwlogin',
'gateway_password' => 'gwpass',
- 'private_key' => '/path/to/keyfile',
+ 'private_key' => $private_key_string,
);
$rx->content(