WebService-NetSuite
view release on metacpan or search on metacpan
lib/WebService/NetSuite.pm view on Meta::CPAN
package WebService::NetSuite;
use strict;
use warnings;
use Moose;
use Carp;
use LWP;
use LWP::UserAgent;
use LWP::Debug;
use SOAP::Lite;
use Data::Dumper;
use JSON;
use XML::Parser;
use XML::Parser::EasyTree;
$XML::Parser::EasyTree::Noempty = 1;
use Storable qw(dclone);
use Crypt::OpenSSL::RSA;
use Encode;
use WebService::NetSuite::Config;
our $ME = 'WebService::NetSuite';
our $VERSION = '0.05';
our $nsversion = "2013_2";
our $soap_href = "https://webservices.%s/services/NetSuitePort_$nsversion";
our $sso_href = 'https://checkout.%s/app/site/backend/sitesso.nl';
our $cart_href = 'http://shopping.%s/app/site/backend/additemtocart.nl';
our $debug = 0; # global setting for deb(), trigger on pkg variable
our $debugFile = 'NetSuite.dbg';
# defined as globals so these don't appear when printing Dumper($self):
our $record_namespaces = &WebService::NetSuite::Config::RecordNamespaces;
our $search_namespaces = &WebService::NetSuite::Config::SearchNamespaces;
our $record_types = &WebService::NetSuite::Config::RecordTypes;
our $search_types = &WebService::NetSuite::Config::SearchTypes;
our $record_fields = &WebService::NetSuite::Config::RecordFields;
has 'debug' => ( is => 'rw', trigger => \&setDebug );
has 'debugfile' => ( is => 'rw', trigger => \&setDebugFile,
default => 'NetSuite.dbg' );
has 'time' => ( is => 'rw' );
has 'company' => ( is => 'ro' );
has 'rsa_private_key' => ( is => 'ro' );
has 'nsemail' => ( is => 'ro', required => 1 );
has 'nspassword' => ( is => 'ro', required => 1 );
has 'nsrole' => ( is => 'ro', writer => '_set_nsrole' );
has 'nsaccount' => ( is => 'ro', writer => '_set_nsaccount' );
has 'nsroleName' => ( is => 'ro', writer => '_set_nsroleName' );
has 'nsaccountName' => ( is => 'ro', writer => '_set_nsaccountName' );
has 'nsdomain' => ( is => 'ro',
writer => '_set_nsdomain',
default => 'netsuite.com' );
has 'sandbox' => ( is => 'ro',
default => 0,
writer => '_set_sandbox',
trigger => \&setSandbox );
has 'site_id' => ( is => 'ro',
default => 1 );
has 'sso_href' => (is => 'ro',
required => 1,
lazy => 1,
default => sub {
my $self = shift;
my $href = sprintf( $sso_href, $self->nsdomain);
return $href;
}
);
has 'cart_href' => (is => 'ro',
required => 1,
lazy => 1,
default => sub {
my $self = shift;
my $href = sprintf($cart_href, self->nsdomain);
return $href;
}
);
has 'soap' => (is => 'ro', writer => '_set_soap');
sub setDebug {
my $self = shift;
$debug = $self->debug;
}
sub setDebugfile {
my $self = shift;
$debugFile = $self->debugfile;
}
sub setSandbox {
my $self = shift;
my $domain = $self->nsdomain;
$domain =~ s/sandbox\.//;
if ($self->sandbox) {
$domain = 'sandbox.' . $domain;
}
$self->_set_nsdomain($domain);
}
sub nvl {
my ($v1,$v2) = @_;
lib/WebService/NetSuite.pm view on Meta::CPAN
}
}
}
sub sso_url {
my ( $self, $args ) = @_;
my $user_id = $args->{user_id} || die 'no user_id';
my $return_url = $args->{return_url};
my $landing_url = $args->{landing_url};
my $hide_login_page = $args->{hide_login_page};
die "custom domain unsupported, Netsuite sandbox does not work with it"
if $args->{d};
my %args = (
a => $self->_generate_auth_token($user_id),
pid => $self->nsaccount,
c => $self->nsaccount,
n => $self->site_id,
);
$args{returnurl} = $return_url if $return_url;
$args{landingurl} = $landing_url if $landing_url;
$args{hideloginpage} = $hide_login_page if $hide_login_page;
my $url = URI->new( $self->sso_href );
$url->query_form( \%args );
return $url->as_string;
}
sub cart_url {
my ( $self, $args ) = @_;
my $buy_id = $args->{buy_id} || die 'no buy_id';
my $show_cart = $args->{show_cart};
my $quantity = $args->{quantity} || 1;
my $c = $args->{c} || die 'no company id';
my %args = (
buyid => $buy_id,
qty => $quantity,
c => $c,
);
$args{showcart} = $show_cart if $show_cart;
my $url = URI->new( $self->cart_href );
$url->query_form( \%args );
return $url->as_string;
}
sub _generate_auth_token {
my ( $self, $user_id ) = @_;
#$DB::single = 1;
my $rsa_priv =
Crypt::OpenSSL::RSA->new_private_key( $self->rsa_private_key );
$rsa_priv->use_pkcs1_padding;
# number of milliseconds since the epoch
my $super_epoch = time() * 1000;
my $authentication_token = $rsa_priv->private_encrypt(
Encode::encode(
'UTF8', join( ' ', $self->company, $user_id, $super_epoch )
)
);
# convert encrypted token to hex
my $token = uc( unpack( 'H*', $authentication_token ) );
return $token;
}
sub add {
my ( $self, $recordType, $recordRef, $recordAttrs ) = @_;
my $ns = $record_namespaces->{$recordType};
if (!defined($ns)) {
my $i = index($recordType, ':');
if ($i < 0) {
fatal "Invalid recordType: $recordType!";
} else {
$ns = substr($recordType, 0, $i);
$recordType = substr($recordType, $i+1);
}
}
deb "namespace for $recordType is " . $ns . "\n";
my %recAttrs = (
'xsi:type' => $ns . ':' . ucfirst($recordType)
);
# Add recordAttrs to recAttrs. This supports cases like where
# ExpenseReport supports adding externalId attr on the <record>
# element. recordAttrs argument is optional and passed only when
# needed.
if ($recordAttrs) {
foreach my $x ( keys %{$recordAttrs} ){
$recAttrs{ $x } = $recordAttrs->{ $x };
}
}
$self->soap->on_action( sub { return 'add'; } );
my $som = $self->soap->add(
$self->_passport,
SOAP::Data->name(
'record' => \SOAP::Data->value(
$self->_parseRequest( ucfirst($recordType), $recordRef )
)
)->attr(\%recAttrs)
);
if ( $som->fault ) {
$self->error;
} else {
if ( $som->dataof("//addResponse/writeResponse/status")
->attr->{'isSuccess'} eq 'true' ) {
return $som->dataof("//addResponse/writeResponse/baseRef")
( run in 1.456 second using v1.01-cache-2.11-cpan-39bf76dae61 )