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 )