Revision 4ad6c50e
Von Jan Büren vor 10 Monaten hinzugefügt
SL/KIX18Client.pm | ||
---|---|---|
package SL::KIX18Client;
|
||
|
||
use strict;
|
||
|
||
use Data::Dumper;
|
||
use Encode qw(encode);
|
||
use Params::Validate qw(:all);
|
||
use REST::Client;
|
||
use Try::Tiny;
|
||
|
||
use SL::JSON;
|
||
use SL::Locale::String qw(t8);
|
||
|
||
use parent qw(Rose::Object);
|
||
|
||
use Rose::Object::MakeMethods::Generic (
|
||
'scalar --get_set_init' => [ qw(connector) ],
|
||
);
|
||
|
||
|
||
sub create_ticket_with_article {
|
||
my ($self) = shift;
|
||
validate(
|
||
@_, {
|
||
ticket => { type => HASHREF },
|
||
article => { type => HASHREF },
|
||
}
|
||
);
|
||
my %params = @_;
|
||
|
||
$params{article}{TicketID} = $self->create_ticket(%{ $params{ticket} });
|
||
$self->create_article(%{ $params{article} });
|
||
return $params{article}{TicketID};
|
||
}
|
||
|
||
sub create_ticket {
|
||
my ($self) = shift;
|
||
die "Invalid connection state" unless $self->connector->can('POST');
|
||
|
||
validate(
|
||
@_, {
|
||
Title => 1,
|
||
}
|
||
);
|
||
my %params = @_;
|
||
|
||
# create ticket with title
|
||
my %t_params = ();
|
||
foreach (keys %params) {
|
||
$t_params{Ticket}{$_} = _u8($params{$_});
|
||
}
|
||
my $ret = _decode_and_status_code($self->connector->POST('tickets', encode_json(\%t_params)));
|
||
|
||
return $ret->{TicketID};
|
||
}
|
||
|
||
sub create_article {
|
||
my ($self) = shift;
|
||
die "Invalid connection state" unless $self->connector->can('POST');
|
||
|
||
validate(
|
||
@_, {
|
||
Subject => 1,
|
||
Body => 1,
|
||
Channel => { type => SCALAR, default => 'note' },
|
||
Charset => { type => SCALAR, default => 'utf-8' },
|
||
MimeType => { type => SCALAR, default => 'text/plain', },
|
||
ContentType => { type => SCALAR, default => 'text/plain; charset=utf-8' },
|
||
|
||
TicketID => { callbacks => {
|
||
'is an integer' => sub {
|
||
return 1 if $_[0] =~ /^-?[1-9][0-9]*$/;
|
||
die "$_[0] is not a valid integer value";
|
||
},
|
||
}
|
||
},
|
||
}
|
||
);
|
||
my %params = @_;
|
||
|
||
# validate sets the params only if the caller passes them ...
|
||
# therefore the defaults need to be defined again:
|
||
$params{Channel} //= 'note';
|
||
$params{Charset} //= 'utf-8';
|
||
$params{MimeType} //= 'text/plain';
|
||
$params{ContentType} //= 'text/plain; charset=utf-8';
|
||
|
||
my %a_params = ();
|
||
foreach (keys %params) {
|
||
next if $_ eq 'TicketID'; # TicketID is set in POST URL
|
||
$a_params{Article}{$_} = $params{Charset} eq 'utf-8' ? _u8($params{$_}) : $params{$_};
|
||
}
|
||
|
||
my $ret = _decode_and_status_code($self->connector->POST("tickets/$params{TicketID}/articles", encode_json(\%a_params)));
|
||
return $ret->{ArticleID};
|
||
}
|
||
|
||
|
||
sub init_connector {
|
||
my ($self) = @_;
|
||
my $config = $::lx_office_conf{kix18};
|
||
|
||
foreach my $key (qw(kix_api_url kix_api_user kix_api_user_pw)) {
|
||
die ("missing parameter: $key") unless $config->{$key};
|
||
}
|
||
|
||
my $protocol = $config->{kix_api_url} =~ /(^https:\/\/|^http:\/\/)/ ? '' : $config->{protocol} . '://';
|
||
my $client = REST::Client->new(host => $config->{kix_api_url});
|
||
|
||
$client->getUseragent()->proxy([$config->{protocol}], $config->{proxy}) if $config->{proxy};
|
||
|
||
$client->addHeader('Content-Type', 'application/json');
|
||
$client->addHeader('charset', 'UTF-8' );
|
||
$client->addHeader('Accept', 'application/json');
|
||
|
||
my %auth_req = (
|
||
UserLogin => $config->{kix_api_user},
|
||
Password => $config->{kix_api_user_pw},
|
||
UserType => "Agent",
|
||
);
|
||
|
||
my $ret = $client->POST('auth', encode_json(\%auth_req));
|
||
die $ret->responseContent() unless (201 == $ret->responseCode());
|
||
|
||
my $token = decode_json($ret->responseContent())->{Token};
|
||
die "No Auth-Token received" unless $token;
|
||
|
||
# persist auth token
|
||
$client->addHeader('Authorization' => 'Token ' . $token);
|
||
|
||
return $client;
|
||
}
|
||
|
||
# internal methods
|
||
|
||
sub _decode_and_status_code {
|
||
my ($ret) = @_;
|
||
|
||
die t8("Unsuccessful HTTP return code: #1 Details: #2", $ret->responseCode(), $ret->responseContent())
|
||
unless $ret->responseCode() == 201;
|
||
|
||
try {
|
||
return decode_json($ret->responseContent());
|
||
} catch { t8("Invalid JSON format"); }
|
||
|
||
}
|
||
|
||
sub _u8 {
|
||
my ($value) = @_;
|
||
return encode('UTF-8', $value // '');
|
||
}
|
||
|
||
1;
|
||
|
||
__END__
|
||
|
||
=encoding utf-8
|
||
|
||
=head1 NAME
|
||
|
||
SL::KIX18Client a REST Client for the KIX18 restful API
|
||
|
||
=head1 SYNOPSIS
|
||
|
||
Needs at least three parameters in kivitendo.conf in
|
||
the section kix18:
|
||
|
||
C<kix_api_user>
|
||
C<kix_api_user_pw>
|
||
C<kix_api_url>
|
||
|
||
With these parameters the init_connector method will
|
||
try to authenticate against a given kix18 REST-Server.
|
||
If successfull the client is able to do RESTful calls to the server, i.e. create
|
||
tickets.
|
||
|
||
=head1 DESCRIPTION
|
||
|
||
For a general documentation of the RESTful API for KIX take a look here:
|
||
https://github.com/kix-service-software/kix-backend/blob/master/doc/API/V1/KIX.html
|
||
|
||
|
||
|
||
=head1 AVAILABLE METHODS
|
||
|
||
=over 4
|
||
|
||
=item C<create_ticket $Title>
|
||
|
||
Creates a Ticket with the named param Title. Returns the ID of the created Ticket.
|
||
No more parameters are accepted, if needed add optional params in the validation
|
||
|
||
=item C<create_article $TicketID $Subject $Body>
|
||
|
||
Creates an article for the given TicketID. Needs a Subject and a Body as
|
||
named Params. Defaults to Channel 'note' with encoding UTF8.
|
||
|
||
=item C<create_ticket_with_article \%ticket \%article>
|
||
|
||
Calls C<create_ticket> and C<create_article> Expects the mandantory params
|
||
for the calls in the hashref ticket and article.
|
||
|
||
=back
|
||
|
||
=head1 AUTHOR
|
||
|
||
Jan BürenE<lt>jan@kivitendo.deE<gt>
|
||
|
||
=cut
|
config/kivitendo.conf.default | ||
---|---|---|
international_dialing_prefix = 00
|
||
# Our own country code
|
||
our_country_code = 49
|
||
|
||
[kix18]
|
||
|
||
# mandantory auth
|
||
kix_api_user=
|
||
kix_api_user_pw=
|
||
kix_api_url=
|
||
|
||
# set proxy and protocol if needed
|
||
proxy =
|
||
protocol= # if url has no http(s) set https or http here
|
||
|
||
# optional for clickable links
|
||
# needs variable <%order_id%> as placeholder
|
||
kivi_order_url= # https://kivi.de/controller.pl?action=Order/edit&type=sales_order&id=<%order_id%>
|
||
# needs variable <%ticket_id%> as placeholder
|
||
kix_ticket_id_url= # https://kix.de/tickets/<%ticket_id%>
|
||
|
Auch abrufbar als: Unified diff
kix18: Client and configuration