From 81a5c124dca2504b9cb7b8dd2e2d9a72eb15c3e1 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Sun, 4 Dec 2016 23:13:04 -0800 Subject: [PATCH] rework card tokenization test --- FS/t/suite/13-tokenization.t | 150 ++++++++++++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 37 deletions(-) diff --git a/FS/t/suite/13-tokenization.t b/FS/t/suite/13-tokenization.t index 9a3ef3f22..b4d204f89 100755 --- a/FS/t/suite/13-tokenization.t +++ b/FS/t/suite/13-tokenization.t @@ -1,36 +1,29 @@ #!/usr/bin/perl +use strict; use FS::Test; -use Test::More tests => 9; +use Test::More; use FS::Conf; +use FS::cust_main; +use Business::CreditCard qw(generate_last_digit); +use DateTime; +if ( stat('/usr/local/etc/freeside/cardfortresstest.txt') ) { + plan tests => 18; +} else { + plan skip_all => 'CardFortress test encryption key is not installed.'; +} ### can only run on test database (company name "Freeside Test") ### will run upgrade, which uses lots of prints & warns beyond regular test output my $fs = FS::Test->new( user => 'admin' ); -my $conf = new_ok('FS::Conf'); +my $conf = FS::Conf->new; my $err; my $bopconf; like( $conf->config('company_name'), qr/^Freeside Test/, 'using test database' ) or BAIL_OUT(''); -# some pre-upgrade cleanup, upgrade will fail if these are still configured -foreach my $cust_main ( $fs->qsearch('cust_main') ) { - my @count = $fs->qsearch('agent_payment_gateway', { agentnum => $cust_main->agentnum } ); - if (@count > 1) { - note("DELETING CARDTYPE GATEWAYS"); - foreach my $apg (@count) { - $err = $apg->delete if $apg->cardtype; - last if $err; - } - @count = $fs->qsearch('agent_payment_gateway', { agentnum => $cust_main->agentnum } ); - if (@count > 1) { - $err = "Still found ".@count." gateways for custnum ".$cust_main->custnum; - last; - } - } -} -ok( !$err, "remove obsolete payment gateways" ) or BAIL_OUT($err); +# test db no longer contains cardtype overrides $bopconf = 'IPPay @@ -78,9 +71,40 @@ foreach my $cust_pay ( $fs->qsearch('cust_pay',{ payby => 'CARD' }) ) { } ok( !$err, "create some refunds and voids" ) or BAIL_OUT($err); +# also, just to test behavior in this case, create a record for an aborted +# verification payment. this will have no customer number. + +my $pending_failed = FS::cust_pay_pending->new({ + 'custnum_pending' => 1, + 'paid' => '1.00', + '_date' => time - 86400, + random_card(), + 'status' => 'failed', + 'statustext' => 'Tokenization upgrade test', +}); +$err = $pending_failed->insert; +ok( !$err, "create a failed payment attempt" ) or BAIL_OUT($err); + +# find two stored credit cards. +my @cust = map { FS::cust_main->by_key($_) } (10, 12); +my @payby = map { ($_->cust_payby)[0] } @cust; +my @payment; + +ok( $payby[0]->payby eq 'CARD' && !$payby[0]->tokenized, + "first customer has a non-tokenized card" + ) or BAIL_OUT(); + +$err = $cust[0]->realtime_cust_payby(amount => '2.00'); +ok( !$err, "create a payment through IPPay" ) + or BAIL_OUT($err); +$payment[0] = $fs->qsearchs('cust_pay', { custnum => $cust[0]->custnum, + paid => '2.00' }) + or BAIL_OUT("can't find payment record"); + $err = system('freeside-upgrade','admin'); ok( !$err, 'initial upgrade' ) or BAIL_OUT('Error string: '.$!); +# switch to CardFortress $bopconf = 'CardFortress cardfortresstest @@ -97,26 +121,78 @@ private_key $conf->set('business-onlinepayment' => $bopconf); is( join("\n",$conf->config('business-onlinepayment')), $bopconf, "setting tokenizable default gateway" ) or BAIL_OUT(''); -foreach my $pg ($fs->qsearch('payment_gateway')) { - unless ($pg->gateway_module eq 'CardFortress') { - note('UPGRADING NON-CF PAYMENT GATEWAY'); - my %pgopts = ( - gateway => $pg->gateway_module, - gateway_login => $pg->gateway_username, - gateway_password => $pg->gateway_password, - private_key => '/usr/local/etc/freeside/cardfortresstest.txt', - ); - $pg->gateway_module('CardFortress'); - $pg->gateway_username('cardfortresstest'); - $pg->gateway_password('(TEST54)'); - $err = $pg->replace(\%pgopts); - last if $err; - } +# create a payment using a non-tokenized card. this should immediately +# trigger tokenization. +ok( $payby[1]->payby eq 'CARD' && ! $payby[1]->tokenized, + "second customer has a non-tokenized card" + ) or BAIL_OUT(); + +$err = $cust[1]->realtime_cust_payby(amount => '3.00'); +ok( !$err, "tokenize a card when it's first used for payment" ) + or BAIL_OUT($err); +$payment[1] = $fs->qsearchs('cust_pay', { custnum => $cust[1]->custnum, + paid => '3.00' }) + or BAIL_OUT("can't find payment record"); +ok( $payment[1]->tokenized, "payment is tokenized" ); +$payby[1] = $payby[1]->replace_old; +ok( $payby[1]->tokenized, "card is now tokenized" ); + +# test db doesn't have this +#foreach my $pg ($fs->qsearch('payment_gateway')) { +# unless ($pg->gateway_module eq 'CardFortress') { +# note('UPGRADING NON-CF PAYMENT GATEWAY'); +# my %pgopts = ( +# gateway => $pg->gateway_module, +# gateway_login => $pg->gateway_username, +# gateway_password => $pg->gateway_password, +# private_key => '/usr/local/etc/freeside/cardfortresstest.txt', +# ); +# $pg->gateway_module('CardFortress'); +# $pg->gateway_username('cardfortresstest'); +# $pg->gateway_password('(TEST54)'); +# $err = $pg->replace(\%pgopts); +# last if $err; +# } +#} +#ok( !$err, "remove non-CF payment gateways" ) or BAIL_OUT($err); + +# invoke the part of freeside-upgrade that tokenizes +FS::cust_main->queueable_upgrade( quiet => 1 ); +#$err = system('freeside-upgrade','admin'); +#ok( !$err, 'tokenizable upgrade' ) or BAIL_OUT('Error string: '.$!); + +$payby[0] = $payby[0]->replace_old; +ok( $payby[0]->tokenized, "old card was tokenized during upgrade" ); +$payment[0] = $payment[0]->replace_old; +ok( $payment[0]->tokenized, "old payment was tokenized during upgrade" ); +ok( ($payment[0]->cust_pay_pending)[0]->tokenized, "old cust_pay_pending was tokenized during upgrade" ); + +$pending_failed = $pending_failed->replace_old; +ok( $pending_failed->tokenized, "cust_pay_pending with no customer was tokenized" ); + +# add a new payment card to one customer +$payby[2] = FS::cust_payby->new({ + custnum => $cust[0]->custnum, + random_card(), +}); +$err = $payby[2]->insert; +ok( !$err, "new card was saved" ); +ok($payby[2]->tokenized, "new card is tokenized" ); + +sub random_card { + my $payinfo = '4111' . join('', map { int(rand(10)) } 1 .. 11); + $payinfo .= generate_last_digit($payinfo); + my $paydate = DateTime->now + ->add('years' => 1) + ->truncate(to => 'month') + ->strftime('%F'); + return ( 'payby' => 'CARD', + 'payinfo' => $payinfo, + 'paydate' => $paydate, + 'payname' => 'Tokenize Me', + ); } -ok( !$err, "remove non-CF payment gateways" ) or BAIL_OUT($err); -$err = system('freeside-upgrade','admin'); -ok( !$err, 'tokenizable upgrade' ) or BAIL_OUT('Error string: '.$!); 1; -- 2.11.0