Business-Tax-Avalara

 view release on metacpan or  search on metacpan

lib/Business/Tax/Avalara.pm  view on Meta::CPAN

package Business::Tax::Avalara;

use 5.010;

use strict;
use warnings;

use Try::Tiny;
use Carp;
use LWP;
use HTTP::Request::Common;
use Encode qw();
use Data::Dump;
use JSON::PP;


=head1 NAME

Business::Tax::Avalara - An interface to Avalara's REST webservice

=head1 SYNOPSYS

	use Business::Tax::Avalara;
	my $avalara_gateway = Business::Tax::Avalara->new(
		customer_code  => $customer_code,
		company_code   => $company_code,
		user_name      => $user_name,
		password       => $password,
		origin_address =>
		{
			line_1      => '1313 Mockingbird Lane',
			postal_code => '98765',
		},
	);
	
	my $tax_results = $avalara_gateway->get_tax(
		destination_address =>
		{
			line_1      => '42 Evergreen Terrace',
			city        => 'Springfield',
			postal_code => '12345',
		},
		cart_lines =>
		[
			{
				sku      => '42ACE',
				quantity => 1,
				amount   => '8.99',
			},
			{
				sku      => '9FCE2',
				quantity => 2,
				amount   => '38.98',
			}
		],
		
	);
	

=head1 DESCRIPTION

Business::Tax::Avalara is a simple interface to Avalara's REST-based sales tax webservice.
It takes in a perl hash of data to send to Avalara, generates the JSON, fetches a response,
and converts that back into a perl hash structure.

This module only supports the 'get_tax' method at the moment.

=head1 VERSION

Version 1.2.0

lib/Business/Tax/Avalara.pm  view on Meta::CPAN

		'tax_included'        => 'TaxIncluded', # Boolean
		'ref_1'               => 'Ref1',
		'ref_2'               => 'Ref2',
	);

	foreach my $node ( keys %nodes )
	{
		if ( defined $cart_line->{ $node } )
		{
			$cart_line_request->{ $nodes{ $node } } = $cart_line->{ $node };
		}
	}

	my %tax_override_nodes =
	(
		'reason'              => 'Reason', # Typical reasons include: 'Return', 'Layaway', 'Imported'.
		'tax_override_type'   => 'TaxOverrideType', # None, TaxAmount, Exemption, or TaxDate.
		'tax_date'            => 'TaxDate', # Date the tax was calculated (if type is TaxDate).
		'tax_amount'          => 'TaxAmount', # The amount of tax to apply (if type is TaxAmount).
	);

	# Fill in the TaxOverride values.
	if ( defined $cart_line->{'tax_override'} )
	{
		foreach my $node ( keys %tax_override_nodes )
		{
			if ( defined $cart_line->{'tax_override'}{ $node } )
			{
				$cart_line_request->{'TaxOverride'}{ $tax_override_nodes{ $node } } = $cart_line->{'tax_override'}{ $node };
			}
		}
	}
	
	return $cart_line_request;
}


=head2 _make_request_json()

Makes the https request to Avalara, and returns the response json.

=cut

sub _make_request_json
{
	my ( $self, $request_json, $resource ) = @_;
		
	$resource //= 'get';
	
	my $request_server = $self->{'is_development'}
		? $AVALARA_DEVELOPMENT_REQUEST_SERVER
		: $AVALARA_REQUEST_SERVER;
	my $request_url = 'https://' . $request_server . '/1.0/tax/' . $resource;
	
	# Create a user agent object
	my $user_agent = LWP::UserAgent->new();
	$user_agent->agent( "perl/Business-Tax-Avalara/$VERSION" );
	$user_agent->timeout( $self->{'request_timeout'} );
	
	# Create a request
	my $request = HTTP::Request::Common::POST(
		$request_url,
	);
	
	$request->authorization_basic(
		$self->{'user_name'},
		$self->{'password'},
	);
	
	$request->header( content_type => 'text/json' );
	$request->content( $request_json );
	$request->header( content_length => length( $request_json ) );
	
	if ( $self->{'debug'} )
	{
		carp( 'Request to Avalara: ', Data::Dump::dump( $request->content() ) );
	}
	
	# Pass request to the user agent and get a response back
	my $response = $user_agent->request( $request );
	
	if ( $self->{'debug'} )
	{
		carp( 'Response from Avalara: ', Data::Dump::dump( $response->content() ) );
	}

	# Check the outcome of the response
	if ( $response->is_success() )
	{
		return $response->content();
	}
	else
	{
		carp $response->status_line();
		carp $request->as_string();
		carp $response->as_string();
		carp "Failed to fetch JSON response: " . $response->status_line() . "\n";
		return $response->content();
	}
	
	return;
}


=head2 _parse_response_json()

Converts the returned JSON into a perl hash.

=cut

sub _parse_response_json
{
	my ( $self, $response_json ) = @_;
	
	my $json = JSON::PP->new()->ascii()->pretty()->allow_nonref();
	my $perl = $json->decode( $response_json );
	
	my $lines = delete $perl->{'TaxLines'};
	foreach my $line ( @$lines )
	{
		$perl->{'TaxLines'}->{ $line->{'LineNo'} } = $line;



( run in 1.090 second using v1.01-cache-2.11-cpan-8dfa8b56332 )