#################### main pod documentation begin ################### =head1 NAME Zymonic::PaymentGateway::Test - Zymonic Workflow System PaymentGateway module =head1 SYNOPSIS A test payment gateway. =head1 DESCRIPTION For testing purposes only. Response will be based on incoming card number. The following rules are used to determine the response from the card number: Card Number = 4444AAXXXXXXXXXX 4444 is 4444 AA is the response code to return (00=sucess, 02=referral, else=fail), X is any digit =head1 USAGE Add following action to a transition: ... ... ... And set a merchant on the transaction to one with payment gateway name of 'Test'. The following SystemOptions may be set in zz_system_options to customize this Test Payment Gateway: * TestPaymentGatewayMinDelay and TestPaymentGatewayMaxDelay: A random value between these two will be taken and used as a delay when processing. * TestPaymentGatewayConnectionsLimit: Integer limit of the number of simultaneous connections to allow. Any more than this will cause a TooManyConnections error. The retry times and waits are determined by payment_gateway_retries and payment_gateway_wait Config Options. If not set then will not limit connections. =head1 BUGS NONE =head1 SUPPORT As in the license, Zymonic is provided without warranty or support unless purchased separately, however... If you email zymonic-support@zednax.com your issue will be noted and may receive a response. For security issues, please contact zymonic-security@zednax.com and someone will respond within 8 working hours. =head1 AUTHOR Alex Masidlover et al.a CPAN ID: MODAUTHOR Zednax Limited alex.masidlover@zednax.com http://www.zednax.com =head1 COPYRIGHT This program is free software licensed under the... Zymonic Public License 1.0 The full text of the license can be found in the LICENSE file included with this module. Other licenses may be acceptable if including parts of Zymonic in larger projects, please contact Zednax for details. =head1 SEE ALSO Zymonic::PaymentGateway::Message::PaymentGateway Zymonic::Action::PaymentGateway Zymonic::PaymentGateway Zymonic perl(1). =cut #################### main pod documentation end ################### package Zymonic::PaymentGateway::Test; use strict; BEGIN { use Exporter (); use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = '0.01'; @ISA = qw(Exporter); #Give a hoot don't pollute, do not export more than needed by default @EXPORT = qw(); @EXPORT_OK = qw(); %EXPORT_TAGS = (); } use base 'Zymonic::PaymentGateway'; use Time::HiRes qw(usleep); use Zymonic::Utils qw(debug); use Zymonic; use Exception::Class ( 'Zymonic::Exception::PaymentGateway::Parameter' => { isa => 'Zymonic::Exception::PaymentGateway', fields => ['param'], description => 'card_number needs to be set on incoming transaction.', }, ); #################### subroutine header begin #################### =head2 authorise Usage : $pg->authorise($trans) Purpose : Authorises the incoming transaction. Returns : The result of the authorisation. Argument : A hashref containg transaction details Throws : Zymonic::Exception::PaymentGateway::Parameter Zymonic::Exception::PaymentGateway::TooManyExceptions Comment : Authorisation is based on incoming card number. See Also : =cut #################### subroutine header end #################### sub authorise { my $self = shift; my $trans = shift; my $max_connections = $self->{config}->sys_opt( 'TestPaymentGatewayConnectionsLimit', undef, 'no_cache' ); if ( defined $max_connections ) { my $connections = $self->{config}->sys_opt('TestPaymentGatewayConnections') || 0; Zymonic::Exception::PaymentGateway::TooManyConnections->throw( type => 'Test', catchable => 'false' ) if $connections >= $max_connections; # add this connection $self->{config}->sys_opt( 'TestPaymentGatewayConnections', $connections + 1 ); } my $min_delay = $self->{config}->sys_opt( 'TestPaymentGatewayMinDelay', undef, 'no_cache' ); my $max_delay = $self->{config}->sys_opt( 'TestPaymentGatewayMaxDelay', undef, 'no_cache' ); if ( defined $min_delay && $max_delay && $min_delay <= $max_delay ) { my $delay = rand( $max_delay - $min_delay ) + $min_delay; debug("Sleeping for $delay seconds."); usleep( $delay * 1000 ); } if ( $trans->{csc} ) { debug( 'Incoming CSC: ' . ( 'X' x length( $trans->{csc} ) ) ); } else { debug('No incoming CSC'); } Zymonic::Exception::PaymentGateway::Parameter->throw( zname => $self->{zname}, param => 'card_number', catchable => 'false' ) unless $trans->{card_number}; my $response = $self->build_response( $trans->{card_number}, $trans->{csc} ); if ( defined $max_connections ) { # remove this connection my $connections = $self->{config}->sys_opt('TestPaymentGatewayConnections') || 0; $self->{config}->sys_opt( 'TestPaymentGatewayConnections', $connections - 1 ); } return $response; } #################### subroutine header begin #################### =head2 build_response Usage : $pg->build_response($card_number, $csc) Purpose : Generates the test response for the given card_number and CSC. Returns : A hashref authorisation result. Argument : A card_number and a csc Throws : nothing Comment : See Also : =cut #################### subroutine header end #################### sub build_response { my $self = shift; my $card_number = shift; my $csc = shift || ''; my $response = { response_code => 11, auth_code => 'AUTH', auth_message => 'Invalid Card Number', referral_phone => '', csc_message => '', csc_response => '' }; if ( $card_number =~ /4444(\d{2})\d{10}/ ) { $response->{response_code} = $1; if ( $response->{response_code} eq '00' ) { $response->{auth_message} = 'Success'; } elsif ( $response->{response_code} eq '02' ) { $response->{auth_message} = 'Referral'; } else { $response->{auth_code} = ''; $response->{auth_message} = 'Failure'; } } if ($csc) { $response->{csc_response} = substr( $csc, 0, 3 ) . '800'; $response->{csc_message} = "Test Response - $response->{csc_response}"; } return $response; } 1;