package Business::CyberSource::Factory::Response; use 5.010; use strict; use warnings; use namespace::autoclean; our $VERSION = '0.006014'; # VERSION use Moose; extends 'Business::CyberSource::Factory'; use Class::Load qw( load_class ); use Exception::Base ( 'Business::CyberSource::Exception' => { has => [ qw( answer ) ], }, 'Business::CyberSource::Response::Exception' => { isa => 'Business::CyberSource::Exception', has => [ qw(decision reason_text reason_code request_id request_token trace) ], string_attributes => [ qw( message decision reason_text ) ], }, verbosity => 4, ignore_package => [ __PACKAGE__, 'Business::CyberSource::Client' ], ); sub create { my ( $self, $dto, $answer ) = @_; my $result = $answer->{result}; my $decision = $self->_get_decision( $result ); # the reply is a subsection of result named after the specic request, e.g # ccAuthReply my $reply = $self->_get_reply( $result ); my @traits; my $e = { }; # response constructor args my $prefix = 'Business::CyberSource::'; my $req_prefix = $prefix . 'Request::'; my $res_prefix = $prefix . 'Response::'; my $role_prefix = $res_prefix . 'Role::'; if ( $result->{decision} eq 'ACCEPT' ) { push( @traits, $role_prefix .'Accept' ); my $ptotals = $result->{purchaseTotals}; $e->{currency} = $ptotals->{currency}; $e->{reference_code} = $result->{merchantReferenceCode}; $e->{amount} = $reply->{amount} if $reply->{amount}; $e->{request_specific_reason_code} = "$reply->{reasonCode}"; my $datetime = $self->_get_datetime( $reply ); $e->{datetime} = $datetime if $datetime; if( $reply->{reconciliationID} ) { push( @traits, $role_prefix . 'ReconciliationID'); $e->{reconciliation_id} = $reply->{reconciliationID}; } if ( $dto->isa( $req_prefix . 'DCC') ) { push ( @traits, $role_prefix . 'DCC' ); $e->{exchange_rate } = $ptotals->{exchangeRate}; $e->{foreign_currency} = $ptotals->{foreignCurrency}; $e->{foreign_amount } = $ptotals->{foreignAmount}; $e->{valid_hours } = $reply->{validHours}; $e->{dcc_supported} =$reply->{dccSupported} eq 'TRUE' ? 1 : 0 ; $e->{exchange_rate_timestamp} = $ptotals->{exchangeRateTimeStamp} ; $e->{margin_rate_percentage} = $reply->{marginRatePercentage}; } } if ( defined $reply->{processorResponse} ) { push ( @traits, $role_prefix . 'ProcessorResponse' ); $e->{processor_response} = $reply->{processorResponse}; } if ( $dto->isa( $req_prefix . 'Authorization') ) { if ( $result->{ccAuthReply} ) { push( @traits, $role_prefix . 'Authorization' ); $e->{auth_code} = $reply->{authorizationCode} if $reply->{authorizationCode} ; if ( $reply->{cvCode} && $reply->{cvCodeRaw}) { $e->{cv_code} = $reply->{cvCode}; $e->{cv_code_raw} = $reply->{cvCodeRaw}; } if ( $reply->{avsCode} && $reply->{avsCodeRaw}) { $e->{avs_code} = $reply->{avsCode}; $e->{avs_code_raw} = $reply->{avsCodeRaw}; } $e->{auth_record} = $reply->{authRecord} if $reply->{authRecord}; } } my $response = load_class('Business::CyberSource::Response') ->with_traits( @traits ) ->new({ request_id => $result->{requestID}, decision => $decision, # quote reason_code to stringify from BigInt reason_code => "$result->{reasonCode}", request_token => $result->{requestToken}, %{$e}, }); $response->_trace( $dto->trace ) if $dto->has_trace; if ( $decision eq 'ERROR' ) { my %exception = ( message => 'message from CyberSource\'s API', decision => $response->decision, reason_text => $response->reason_text, reason_code => $response->reason_code, value => $response->reason_code, request_id => $response->request_id, request_token => $response->request_token, ); $exception{trace} = $response->trace if $response->has_trace; Business::CyberSource::Response::Exception->throw( %exception ); } return $response; } sub _get_datetime { my ( $self, $reply ) = @_; my $datetime = $reply->{requestDateTime} ? $reply->{requestDateTime} : $reply->{authorizedDateTime} ; return $datetime; } sub _get_reply { my ( $self, $result ) = @_; my $_; my $reply; foreach ( sort keys %{ $result } ) { if ( $_ =~ m/Reply/x ) { unless ( defined $reply ) { $reply = $result->{$_} } else { # sale's have 2 Reply sections, this merges them require Hash::Merge; $reply = Hash::Merge::merge( $result->{$_}, $reply ); } } } return $reply; } sub _get_decision { my ( $self, $result ) = @_; my $_; my ( $decision ) = grep { $_ eq $result->{decision} } qw( ERROR ACCEPT REJECT ) or Business::CyberSource::Exception->throw( message => 'decision not defined or not handled', answer => $result, ) ; return $decision; } 1; # ABSTRACT: A Response Factory __END__ =pod =head1 NAME Business::CyberSource::Factory::Response - A Response Factory =head1 VERSION version 0.006014 =head1 METHODS =head2 create Pass the C from L and the original Request Data Transfer Object. =head1 BUGS Please report any bugs or feature requests on the bugtracker website https://github.com/xenoterracide/Business-CyberSource/issues When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. =head1 AUTHOR Caleb Cushing =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2012 by HostGator.com. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut