package Net::Artera;
use 5.005;
use strict;
use Data::Dumper;
use LWP::UserAgent;
use XML::Simple;
use Locale::Country;
#require Exporter;
use vars qw($VERSION @ISA $DEBUG @login_opt); #$WARN );
# @EXPORT @EXPORT_OK %EXPORT_TAGS);
#@ISA = qw(Exporter);
# This allows declaration use Net-Artera ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
#%EXPORT_TAGS = ( 'all' => [ qw(
#
#) ] );
#@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
#@EXPORT = qw();
$VERSION = '0.01';
#$WARN = 0;
$DEBUG = 0;
=head1 NAME
Net::Artera - Perl extension for Artera XML API.
=head1 SYNOPSIS
use Net::Artera;
my $connection = new Net::Artera (
'rid' => 'reseller_id',
'username' => 'reseller_username',
'password' => 'reseller_password',
'production' => 0,
);
my $result = $artera->newOrder(
'email' => $email,
'cname' => $name,
'ref' => $refnum,,
'aid' => $affiliatenum,
'add1' => $address1,
'add2' => $address2,
'add3' => $city,
'add4' => $state,
'zip' => $zip,
'cid' => $country,
'phone' => $phone,
'fax' => $fax,
);
if ( $result->{'id'} == 1 ) {
#Success!
$serialnum = $result->{'ASN'};
$keycode = $result->{'AKC'};
} else {
#Failure
die $result->{'message'};
}
# etc...
=head1 DESCRIPTION
This is a Perl module which speaks the Artera XML API.
See <http://www.arteraturbo.com>. Artera Resellers can use this module
to access some features of the API.
=head1 METHODS
=over 4
=item new [ OPTIONS_HASHREF | OPTION => VALUE ... ]
Constructor. Options can be passed as a hash reference or a list. Options are
case-insensitive.
Available options are:
=over 4
=item username - Reseller username
=item password - Reseller password
=item rid - Reseller ID (RID)
=item pid - Product ID (PID).
=item production - if set true, uses the production server instead of the staging server.
=back
=cut
@login_opt = qw( RID Username Password );
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless ($self, $class);
my $opt = $self->_lc_hash_or_hashref(@_);
$self->{$_} = $opt->{$_} for map lc($_), @login_opt;
if ( defined($opt->{'production'}) && $opt->{'production'} ) {
$self->{'url'} = 'https://secure.arteragroup.com/';
} else {
$self->{'url'} = 'http://staging.arteragroup.com/';
}
$self->{'url'} .= 'Wizards/wsapi/31/APIService.asmx';
$self->{'ua'} = LWP::UserAgent->new;
warn "\n$self created: ". Dumper($self) if $DEBUG;
$self;
}
sub _lc_hash_or_hashref {
my $self = shift;
my $opt = ref($_[0]) ? shift : {@_};
my $gratuitous = { map { lc($_) => $opt->{$_} } keys %$opt };
$gratuitous;
}
=item newTrial [ OPTIONS_HASHREF | OPTION => VALUE ... ]
Options can be passed as a hash reference or a list. Options are
case-insensitive.
Available options are:
=over 4
=item email (required)
=item cname (required) - Customer's name
=item ref (required) - Reseller's own order reference
=item pid (required) - Artera Product ID
=item priceid (required) - Artera Price ID
=item aid - Affiliate ID number used when the Reseller wants to track some type of sales channel beneath them.
=item add1*
=item add2
=item add3* - City
=item add4* - State
=item zip*
=item cid* - Country ID. Defaults to 2 (USA). Can be specified as a numeric CID or as an ISO 3166 two-letter country code or full name.
=item phone
=item fax
=back
*These fields are optional, but must be supplied as a set.
Returns a hash reference with the following keys (these keys B<are>
case-sensitive):
=over 4
=item id - This is the Result ID to indicate success or failure: 1 for success, anything else for failure
=item message - Some descriptive text regarding the success or failure
=item ASN - The Artera Serial Number
=item AKC - The Artera Key Code
=item TrialID - The Artera Trial Number
=item Ref - The Reseller Reference
=item CustomerID - Artera's CustomerID
=item TrialLength - Trial Length
=cut
sub newTrial {
my $self = shift;
my $opt = $self->_lc_hash_or_hashref(@_);
$self->_newX('Trial', $opt);
}
=item newOrder [ OPTIONS_HASHREF | OPTION => VALUE ... ]
Available options are the same as B<newTrial>. Additionally the I<asn> and
I<akc> fields may be specified to convert a trial to an order.
=cut
sub newOrder {
my $self = shift;
my $opt = $self->_lc_hash_or_hashref(@_);
push @{$opt->{'optional_params'}}, qw( ASN AKC );
$self->_newX('Order', $opt);
}
sub _newX {
my( $self, $x, $opt ) = @_;
if ( defined($opt->{'cid'}) ) {
$opt->{'cid'} = $self->_country2cid($opt->{'cid'});
} else {
$opt->{'cid'} = 2 if grep defined($_), qw(Add1 Add3 Add4 Zip);
}
push @{$opt->{'required_params'}},
qw( Email CName Ref PID PriceID );
push @{$opt->{'optional_params'}},
qw( AID Add1 Add2 Add3 Add4 Zip CID Phone Fax );
$self->_submit( "new$x", $opt );
}
my %country2cid = (
'uk' => 1,
'gb' => 1,
'us' => 2,
'in' => 3,
'jp' => 4,
'ru' => 5,
'fr' => 6,
'pl' => 7,
'gr' => 8,
'ug' => 9,
'lk' => 10,
'sa' => 11,
'nl' => 12,
'pe' => 13,
'ca' => 14,
'nz' => 15,
'kr' => 16,
'it' => 17,
'es' => 18,
'il' => 19,
'se' => 20,
'de' => 21,
'ie' => 22,
'mx' => 23,
'au' => 24,
'to' => 25,
'eg' => 26,
'tr' => 27,
'am' => 28,
'az' => 29,
'by' => 30,
'ee' => 31,
'ge' => 32,
'kz' => 33,
'kg' => 34,
'lt' => 35,
'md' => 36,
'tj' => 38,
'tm' => 39,
'ua' => 40,
'uz' => 41,
'' => 42, #BOSNIA
'' => 43, #HERZEGOVINA
'hr' => 44,
'mk' => 45,
'' => 46, #SERBIA
'' => 47, #MONTENEGRO
'si' => 48,
'er' => 49,
'mh' => 51,
'pw' => 52,
'fm' => 53,
'na' => 54,
'lv' => 56,
'za' => 57,
'jm' => 58,
);
sub _country2cid {
my( $self, $country ) = @_;
if ( $country =~ /^\s*(\d+)\s*$/ ) {
$1;
} elsif ( $country =~ /^\s*(\w\w)\s*$/ ) {
$country2cid{$1};
} elsif ( $country !~ /^\s*$/ ) {
$country2cid{country2code($country)};
} else {
'';
}
}
=item statusChange [ OPTIONS_HASHREF | OPTION => VALUE ... ]
Options can be passed as a hash reference or a list. Options are
case-insensitive.
Available options are:
=over 4
=item ASN (required) - Artera Serial Number
=item AKC (required) - Artera Key Code
=item StatusID (required) - Possible StatusID values are as follows:
=over 4
=item 15 - Normal Unrestricted: re-enable a disabled Serial Number (e.g. a payment dispute has been resolved so the Serial Number needs to be re-enabled).
=item 16 - Disable: temporarily prohibit an end-user's serial number from working (e.g. there is a payment dispute, so you want to turn off the Serial Number until the dispute is resolved).
=item 17 - Terminate: permanently prohibit an end-user's Serial Number from working (e.g. subscription cancellation)
=back
=item Reason - Reason for terminating
=back
Returns a hash reference with the following keys (these keys B<are>
case-sensitive):
=over 4
=item id - This is the Result ID to indicate success or failure: 1 for success, anything else for failure
=item message - Some descriptive text regarding the success or failure
=back
=cut
sub statusChange {
my $self = shift;
my $opt = $self->_lc_hash_or_hashref(@_);
push @{$opt->{'required_params'}},
qw( ASN AKC StatusID );
push @{$opt->{'optional_params'}}, 'Reason';
$self->_submit('statusChange', $opt );
}
=item getProductStatus [ OPTIONS_HASHREF | OPTION => VALUE ... ]
Options can be passed as a hash reference or a list. Options are
case-insensitive.
Available options are:
=over 4
=item ASN (required) - Artera Serial Number
=item AKC (required) - Artera Key Code
=back
Returns a hash reference with the following keys (these keys B<are>
case-sensitive):
=over 4
=item id - This is the Result ID to indicate success or failure: 1 for success, anything else for failure
=item message - On failure, descriptive text regarding the failure
=item StatusID (required) - Possible StatusID values are as follows:
=over 4
=item 15 - Normal Unrestricted: re-enable a disabled Serial Number (e.g. a payment dispute has been resolved so the Serial Number needs to be re-enabled).
=item 16 - Disable: temporarily prohibit an end-user's serial number from working (e.g. there is a payment dispute, so you want to turn off the Serial Number until the dispute is resolved).
=item 17 - Terminate: permanently prohibit an end-user's Serial Number from working (e.g. subscription cancellation)
=back
=item Description - Status description
=back
=cut
sub getProductStatus {
my $self = shift;
my $opt = $self->_lc_hash_or_hashref(@_);
push @{$opt->{'required_params'}}, qw( ASN AKC );
my $result = $self->_submit('getProductStatus', $opt );
# munch results, present as flat list
$result->{$_} = $result->{'Status'}->{$_} foreach (qw(StatusID Description));
delete $result->{'Status'};
$result;
}
=item updateContentControl [ OPTIONS_HASHREF | OPTION => VALUE ... ]
Options can be passed as a hash reference or a list. Options are
case-insensitive.
Available options are:
=over 4
=item ASN (required) - Artera Serial Number
=item AKC (required) - Artera Key Code
=item UseContentControl (required) - 0 for off, 1 for on
=back
Returns a hash reference with the following keys (these keys B<are>
case-sensitive):
=over 4
=item id - This is the Result ID to indicate success or failure: 1 for success, anything else for failure
=item message - Some descriptive text regarding the success or failure
=back
=cut
sub updateContentControl {
my $self = shift;
my $opt = $self->_lc_hash_or_hashref(@_);
push @{$opt->{'required_params'}}, qw( ASN AKC UseContentControl );
$self->_submit('updateContentControl', $opt );
}
=item orderListByDate [ OPTIONS_HASHREF | OPTION => VALUE ... ]
Unimplemented.
=cut
#--
sub _submit {
my( $self, $method, $opt ) = @_;
my $ua = $self->{'ua'};
my $param = {
( map { $_ => $self->{lc($_)} }
@login_opt,
),
( map { $_ => $opt->{lc($_)} }
@{$opt->{'required_params'}}
),
( map { $_ => ( exists $opt->{lc($_)} ? $opt->{lc($_)} : '' ) }
@{$opt->{'optional_params'}}
),
};
warn "$self url $self->{url}/$method\n" if $DEBUG;
warn "$self request parameters: ". Dumper($param). "\n" if $DEBUG;
#POST
my $response = $ua->post( "$self->{'url'}/$method", $param );
warn "$self raw response: ". $response->content. "\n" if $DEBUG;
#unless ( $response->is_success ) {
# die $response->content;
#}
my $xml = XMLin( $response->content );
warn "$self parsed response: ". Dumper($xml) if $DEBUG;
#warn "\n".$xml->{'message'}."\n" unless $xml->{'id'} == 1 or not $WARN;
$xml;
}
=back
=head1 BUGS
orderListByDate is unimplemented.
=head1 SEE ALSO
<http://www.arteraturbo.com>
=head1 AUTHOR
Ivan Kohler, E<lt>ivan-net-artera@420.amE<gt>
Freeside, open-source billing for ISPs: <http://www.sisd.com/freeside>
Not affiliated with Artera Group, Inc.
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2004 Ivan Kohler
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
1;