X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=lib%2FBusiness%2FOnlinePayment%2FCardFortress.pm;h=1d97d4909c0358d9b48a43914d06b85ee4eb790b;hb=589d9cfa12b8b2f60730e74fba681053ced34047;hp=513ed2606a4152c030c3e03fd150f7d7afc68e0c;hpb=0aa824efca85bf4ae52559ea4b974b817c0a93b1;p=Business-OnlinePayment-CardFortress.git diff --git a/lib/Business/OnlinePayment/CardFortress.pm b/lib/Business/OnlinePayment/CardFortress.pm index 513ed26..1d97d49 100644 --- a/lib/Business/OnlinePayment/CardFortress.pm +++ b/lib/Business/OnlinePayment/CardFortress.pm @@ -5,12 +5,15 @@ use base qw( Business::OnlinePayment::HTTPS ); use warnings; use strict; #use vars qw( $DEBUG $me ); +use File::Slurp; +use MIME::Base64; +use Crypt::OpenSSL::RSA; -our $VERSION = 0.01; +our $VERSION = 0.03; sub _info { { - 'info_version' => '0.01', + 'info_compat' => '0.01', 'module_version' => $VERSION, 'supported_types' => [ 'CC' ], 'supported_actions' => { 'CC' => [ @@ -19,9 +22,10 @@ sub _info { 'Post Authorization', 'Void', 'Credit', + 'Tokenize', ], }, - 'token_support' => 'challenge/response', + 'token_support' => 1, #need to figure out how to pass through for gateways that do... an option? #'CC_void_requires_card' => 1, }; @@ -38,20 +42,25 @@ sub set_defaults { $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/; + $content{$_} = $self->$_() for grep $self->can($_), qw( bop_options ); - my %response = {}; + my ($page,$server_response,%headers) = $self->https_post(%content); + + 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) ) { @@ -73,6 +82,30 @@ sub submit { # response_headers() # response_page() + #handle the challenge/response handshake + if ( $self->error_message eq '_challenge' ) { #XXX infinite loop protection? + + my $private_key = $self->private_key + or die "no private key available"; + + $private_key = read_file($private_key) + if $private_key !~ /-----BEGIN/ && -r $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($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; @@ -87,12 +120,13 @@ Business::OnlinePayment::CardFortress - CardFortress backend for Business::Onlin use Business::OnlinePayment; - my $tx = new Business::OnlinePayment( 'CardFortress', - 'gateway' => 'ProcessingGateway', - 'gateway_login' => 'gwlogin', - 'gateway_password' => 'gwpass', - #private_key not necessary - ); + my $tx = new Business::OnlinePayment( + 'CardFortress', + 'gateway' => 'ProcessingGateway', + 'gateway_login' => 'gwlogin', + 'gateway_password' => 'gwpass', + #private_key not necessary + ); $tx->content( type => 'VISA', @@ -123,12 +157,14 @@ Business::OnlinePayment::CardFortress - CardFortress backend for Business::Onlin # ... time slips by ... - my $rx = new Business::OnlinePayment( 'CardFortress', - 'gateway' => 'ProcessingGateway', - 'gateway_login' => 'gwlogin', - 'gateway_password' => 'gwpass', - 'private_key' => '/path/to/keyfile', - ); + my $rx = new Business::OnlinePayment( + 'CardFortress', + 'gateway' => 'ProcessingGateway', + 'gateway_login' => 'gwlogin', + 'gateway_password' => 'gwpass', + 'private_key' => $private_key_string, #or filename + 'bop_options' => join('/', map "$_=".$options{$_}, keys %options), + ); $rx->content( type => 'VISA',