2022-06-07 06:53:15 +02:00
|
|
|
package Mod::APIshareeio;
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
# Copyright (c) Rainer Gümpelein, TeilRad GmbH
|
|
|
|
#
|
2022-06-20 12:40:04 +02:00
|
|
|
#use lib qw(/var/www/copri-bike/shareeapp-sx/src);
|
|
|
|
#
|
2022-06-07 06:53:15 +02:00
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
use Exporter;
|
|
|
|
our @ISA = qw (Exporter);
|
|
|
|
|
|
|
|
use POSIX;
|
|
|
|
use CGI;
|
|
|
|
use Apache2::Const -compile => qw(OK );
|
|
|
|
use JSON;
|
|
|
|
use Scalar::Util qw(looks_like_number);
|
|
|
|
use Config::General;
|
|
|
|
|
|
|
|
use Lib::Config;
|
|
|
|
use Mod::DBtank;
|
|
|
|
use Mod::Basework;
|
|
|
|
use Mod::Shareework;
|
|
|
|
use Mod::APIfunc;
|
|
|
|
use Data::Dumper;
|
|
|
|
|
|
|
|
sub handler {
|
|
|
|
my ($r) = @_;
|
|
|
|
my $q = new CGI;
|
|
|
|
my $netloc = $q->url(-base=>1);
|
|
|
|
$q->import_names('R');
|
|
|
|
my $json = JSON->new->allow_nonref;
|
|
|
|
my $cf = new Config;
|
|
|
|
my $dbt = new DBtank;
|
|
|
|
my $bw = new Basework;
|
|
|
|
my $tk = new Shareework;
|
|
|
|
|
|
|
|
my %varenv = $cf->envonline();
|
|
|
|
my $oprefix = $dbt->{operator}->{$varenv{dbname}}->{oprefix};
|
|
|
|
my $now_dt = strftime "%Y-%m-%d %H:%M:%S", localtime;
|
|
|
|
my @keywords = $q->param;
|
|
|
|
my $user_agent = $q->user_agent();
|
|
|
|
my $aowner = 168;
|
2022-06-08 20:18:11 +02:00
|
|
|
my $debug=1;
|
2022-06-07 06:53:15 +02:00
|
|
|
my $api_file = "/var/www/copri4/shareeconf/apikeys.cfg";
|
|
|
|
my $aconf = Config::General->new($api_file);
|
|
|
|
my %apikeyconf = $aconf->getall;
|
|
|
|
|
|
|
|
my %headers = map { $_ => $q->http($_) } $q->http();
|
|
|
|
$bw->log("APIshareeio request:\n--> user-agent '$user_agent' ",$q,"");
|
|
|
|
$bw->log("headers:",\%headers,"");
|
|
|
|
|
|
|
|
#for my $header ( keys %headers ) {
|
|
|
|
# print "$header: $headers{$header}\n";
|
|
|
|
#}
|
|
|
|
|
|
|
|
print $q->header(-type => "application/json", -charset => "utf-8", -'Access-Control-Allow-Origin' => "*");
|
2022-06-08 20:18:11 +02:00
|
|
|
|
|
|
|
open(FILE,">>$varenv{logdir}/APIshareeio.log") if($debug);
|
|
|
|
print FILE "\n*** $now_dt user-agent: '$user_agent' to syshost: $varenv{syshost}\n" if($debug);
|
|
|
|
print FILE "<=== DUMP query\n " . Dumper($q) . "\n" if($debug);
|
|
|
|
print FILE "<=== DUMP postdata:\n " . Dumper($q->param('POSTDATA')) . "\n" if($debug);
|
|
|
|
|
|
|
|
|
2022-06-07 06:53:15 +02:00
|
|
|
my $response = {
|
2022-06-10 14:18:17 +02:00
|
|
|
event => "",
|
|
|
|
response_state => "Event doesn't match",
|
2022-06-07 06:53:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
my $http_sharee_api_key = $headers{HTTP_SHAREE_API_KEY} || $R::HTTP_SHAREE_API_KEY || "";
|
|
|
|
if(!$apikeyconf{shareeio}->{sharee_api_key} || !$http_sharee_api_key || $apikeyconf{shareeio}->{sharee_api_key} ne $http_sharee_api_key){
|
|
|
|
$response->{response_state} = "Failure: access denied, api-key doesn't match";
|
|
|
|
$bw->log("Failure: access denied, api-key doesn't match",$q,"");
|
|
|
|
my $jrout = $json->pretty->encode({shareeio => $response});
|
|
|
|
print $jrout;
|
|
|
|
return Apache2::Const::OK;
|
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach(@keywords){
|
2022-06-08 20:18:11 +02:00
|
|
|
if(length($_) > 40 || length($q->param($_)) > 400){
|
2022-06-07 06:53:15 +02:00
|
|
|
$response->{response_state} = "Failure 9000: amount of characters in $_ exceeds";
|
|
|
|
$bw->log("Failure 9000: amount of characters in $_ exceeds",$q,"");
|
|
|
|
my $jrout = $json->pretty->encode({shareeio => $response});
|
|
|
|
print $jrout;
|
|
|
|
return Apache2::Const::OK;
|
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-08 20:18:11 +02:00
|
|
|
|
|
|
|
#sig booking_update
|
2022-06-22 21:46:00 +02:00
|
|
|
my $response_out = {};
|
|
|
|
$response_out = sig_booking_update($q,\%varenv,$response,$aowner);# sig json post
|
2022-06-08 20:18:11 +02:00
|
|
|
|
|
|
|
#sig json api
|
|
|
|
sub sig_booking_update {
|
2022-06-20 12:40:04 +02:00
|
|
|
my $q = shift;
|
|
|
|
my $varenv = shift;
|
|
|
|
my $response = shift || {};
|
|
|
|
my $aowner = shift || "";
|
2022-06-08 20:18:11 +02:00
|
|
|
|
2022-06-20 12:40:04 +02:00
|
|
|
$q->import_names('R');
|
|
|
|
my $dbt = new DBtank;
|
|
|
|
my $apif = new APIfunc;
|
|
|
|
my $dbh = "";
|
|
|
|
my $debug=1;
|
2022-06-08 20:18:11 +02:00
|
|
|
my $jrout = "seems to be not valid";
|
|
|
|
|
|
|
|
#sig using POST JSON
|
|
|
|
my $POSTDATA = $q->param('POSTDATA');
|
|
|
|
|
|
|
|
#REST methode only used for easy testing
|
2022-06-07 06:53:15 +02:00
|
|
|
if($R::request && $R::request eq "booking_update"){
|
|
|
|
my $rentalId = $q->escapeHTML($R::rentalId) || "";
|
2022-06-08 20:18:11 +02:00
|
|
|
my %POSTDATA_hash = (
|
|
|
|
"event"=>"RENTAL_END",
|
|
|
|
"data"=>{
|
|
|
|
"bikeId"=>"test16b5-0522-43da-ab66-477744a731a3",
|
2022-06-29 17:34:51 +02:00
|
|
|
"lockStatus"=>"locked",
|
2022-06-08 20:18:11 +02:00
|
|
|
"rentalId"=>"$rentalId",
|
|
|
|
"reservationState"=>"",
|
|
|
|
"startTime"=>"2022-06-06T15:00:18.045Z",
|
|
|
|
"endTime"=>"2022-06-06T15:01:43.118Z",
|
|
|
|
"distance"=>1000
|
|
|
|
}
|
|
|
|
);
|
|
|
|
$POSTDATA = encode_json(\%POSTDATA_hash);
|
|
|
|
print FILE "<=== DUMP POSTDATA_hash:\n " . Dumper(\%POSTDATA_hash) . "\n" if($debug);
|
|
|
|
}
|
2022-06-22 21:46:00 +02:00
|
|
|
|
2022-06-08 20:18:11 +02:00
|
|
|
eval {
|
|
|
|
my $response_in = {};
|
|
|
|
$response_in = decode_json($POSTDATA) if($POSTDATA);
|
|
|
|
|
2022-06-10 14:18:17 +02:00
|
|
|
$response->{event} = "$response_in->{event}";
|
2022-06-20 12:40:04 +02:00
|
|
|
if($response_in->{event}){
|
2022-06-08 20:18:11 +02:00
|
|
|
|
2022-06-20 12:40:04 +02:00
|
|
|
my $bikeId = $q->escapeHTML($response_in->{data}->{bikeId}) || "";#on push, bikeId is bike_id
|
2022-06-08 20:18:11 +02:00
|
|
|
my $rentalId = $q->escapeHTML($response_in->{data}->{rentalId}) || "";
|
2022-06-23 14:22:35 +02:00
|
|
|
|
2022-06-07 06:53:15 +02:00
|
|
|
my $rows = 0;
|
|
|
|
my $booking_values = {};
|
|
|
|
|
2022-06-22 21:46:00 +02:00
|
|
|
print FILE "event: $response_in->{event}\n" if($debug);
|
|
|
|
|
2022-06-23 14:22:35 +02:00
|
|
|
if($response_in->{event} eq "BIKE_STATUS" || $response_in->{event} eq "BATTERY_CAPACITY"){
|
|
|
|
$response->{response_state} = "OK: $response_in->{event} methode not implemented, because we will get it just-in-time on requesting sig GET bikes";
|
|
|
|
}
|
2022-06-20 12:40:04 +02:00
|
|
|
if($response_in->{event} eq "RENTAL_START"){
|
2022-06-23 14:22:35 +02:00
|
|
|
$response->{response_state} = "OK: methode not implemented, because rental will be started by App and success returned by sig-connector";
|
2022-06-20 12:40:04 +02:00
|
|
|
}
|
2022-06-24 20:31:03 +02:00
|
|
|
elsif($response_in->{event} eq "RENTAL_END" || $response_in->{event} eq "RESERVATION_END" || ($response_in->{event} eq "SMARTLOCK" && $response_in->{data}->{lockStatus} eq "unlocked")){
|
2022-06-20 12:40:04 +02:00
|
|
|
if($rentalId){
|
2022-06-07 06:53:15 +02:00
|
|
|
|
|
|
|
my $ctpos = {};
|
|
|
|
my $booking_pos = {
|
|
|
|
table => "contenttranspos",
|
|
|
|
fetch => "one",
|
|
|
|
txt11 => "$rentalId",
|
|
|
|
int10 => "IN::('2','3')",
|
|
|
|
#ca_id => "$authraw->{c_id}",#sig doesn't know uid
|
|
|
|
};
|
2022-06-23 14:22:35 +02:00
|
|
|
|
|
|
|
#only reserved alias requested rentals can be canceled
|
|
|
|
$booking_pos->{int10} = 2 if($response_in->{event} eq "RESERVATION_END");
|
|
|
|
|
2022-06-07 06:53:15 +02:00
|
|
|
$ctpos = $dbt->fetch_tablerecord($dbh,$booking_pos);
|
2022-06-08 20:18:11 +02:00
|
|
|
|
|
|
|
my $distance = 0;
|
|
|
|
$distance = $response_in->{data}->{distance} / 1000 if(looks_like_number($response_in->{data}->{distance}) && $response_in->{data}->{distance} > 0);
|
|
|
|
$distance = sprintf('%.2f',$distance);
|
2022-06-07 06:53:15 +02:00
|
|
|
if(ref($ctpos) eq "HASH" && $ctpos->{txt22} && $ctpos->{txt11}){
|
|
|
|
my $sig_book = {
|
|
|
|
bikeId => $ctpos->{txt22},
|
|
|
|
rentalId => $ctpos->{txt11},
|
2022-06-08 20:18:11 +02:00
|
|
|
reservationId => "",
|
|
|
|
distance => $distance,
|
2022-06-07 06:53:15 +02:00
|
|
|
};
|
2022-06-08 20:18:11 +02:00
|
|
|
|
2022-06-07 06:53:15 +02:00
|
|
|
my $authraw = { c_id => "" };
|
|
|
|
$authraw->{c_id} = $ctpos->{ca_id} if($ctpos->{ca_id});
|
|
|
|
$q->param(-name=>'bike',-value=>"$ctpos->{ct_name}") if($ctpos->{ct_name});
|
2022-06-23 14:22:35 +02:00
|
|
|
$q->param(-name=>'state',-value=>"canceled") if($response_in->{event} eq "RESERVATION_END");
|
2022-06-24 20:31:03 +02:00
|
|
|
|
|
|
|
if($response_in->{event} eq "SMARTLOCK" && $response_in->{data}->{lockStatus} eq "unlocked"){
|
|
|
|
$q->param(-name=>'lock_state',-value=>"unlocked");
|
|
|
|
}
|
2022-06-23 14:22:35 +02:00
|
|
|
if($response_in->{event} eq "RENTAL_END"){
|
|
|
|
$q->param(-name=>'state',-value=>"available");
|
|
|
|
$q->param(-name=>'lock_state',-value=>"locked");
|
2022-06-24 20:31:03 +02:00
|
|
|
#addition state in context to get state=returned for miniquery
|
2022-06-29 17:34:51 +02:00
|
|
|
$sig_book->{station_lock_state} = "3";#set int28 to 3
|
2022-06-23 14:22:35 +02:00
|
|
|
}
|
|
|
|
|
2022-06-20 12:40:04 +02:00
|
|
|
($rows, $booking_values) = $apif->booking_update($q,$varenv,$authraw,$aowner,$sig_book) if($authraw->{c_id});
|
2022-06-09 15:31:31 +02:00
|
|
|
|
|
|
|
#response is for sig json after rental-end
|
|
|
|
$booking_values->{bikeId} = $sig_book->{bikeId};
|
|
|
|
$booking_values->{rentalId} = $sig_book->{rentalId};
|
2022-06-10 14:18:17 +02:00
|
|
|
delete $booking_values->{geo_distance};
|
|
|
|
delete $booking_values->{co2saving};
|
|
|
|
delete $booking_values->{bike};
|
|
|
|
delete $booking_values->{response_text};
|
2022-07-27 16:01:39 +02:00
|
|
|
delete $booking_values->{user_miniquery};
|
2022-06-23 14:22:35 +02:00
|
|
|
$response->{response_state} = "OK: event matched, but something seems to goes wrong on booking_update" if(!$booking_values->{response_state});
|
2022-06-07 06:53:15 +02:00
|
|
|
$response = {%$response, %$booking_values};
|
|
|
|
}else{
|
2022-06-23 14:22:35 +02:00
|
|
|
$response->{response_state} = "Failure: $response_in->{event} : there is no reservation OR rental with rentalID=$rentalId";
|
2022-06-07 06:53:15 +02:00
|
|
|
}
|
|
|
|
|
2022-06-20 12:40:04 +02:00
|
|
|
}else{
|
|
|
|
$response->{response_state} = "Failure: no rentalId defined";
|
|
|
|
}
|
|
|
|
}#end RENTAL_END
|
2022-06-08 20:18:11 +02:00
|
|
|
|
|
|
|
}#end event
|
2022-06-20 12:40:04 +02:00
|
|
|
|
2022-06-08 20:18:11 +02:00
|
|
|
};#end eval
|
|
|
|
if ($@){
|
|
|
|
print FILE "failure! can not decode POST json, POSTDATA:\n" . Dumper($q->param('POSTDATA')) . "\n" if($debug);
|
|
|
|
#warn $@;
|
|
|
|
print FILE "warn:" . $@ . "\n" if($debug);
|
2022-06-10 14:18:17 +02:00
|
|
|
$response->{response_state} = "Failure: can not decode POST json";
|
2022-06-08 20:18:11 +02:00
|
|
|
}
|
2022-06-22 21:46:00 +02:00
|
|
|
return $response;
|
2022-06-08 20:18:11 +02:00
|
|
|
}#end sig json booking_update
|
|
|
|
|
2022-06-07 06:53:15 +02:00
|
|
|
|
|
|
|
#end RESTful ------------------------------------------------------------
|
|
|
|
#FINAL JSON response OUTPUT ----------------------------------------------------------
|
2022-06-22 21:46:00 +02:00
|
|
|
my $jrout = $json->pretty->encode({shareeio => $response_out});
|
2022-06-07 06:53:15 +02:00
|
|
|
print $jrout;
|
|
|
|
|
2022-06-22 18:29:46 +02:00
|
|
|
print FILE "APIshareeio jrout:\n" . Dumper($jrout) . "\n" if($debug);
|
|
|
|
$bw->log("APIshareeio response by $user_agent mapped aowner:$aowner",$jrout,"");
|
2022-06-07 06:53:15 +02:00
|
|
|
#end JSON ----------------------------------------------------------------------------
|
|
|
|
|
2022-06-08 20:18:11 +02:00
|
|
|
close(FILE) if($debug);
|
2022-06-07 06:53:15 +02:00
|
|
|
return Apache2::Const::OK;
|
|
|
|
}#end handler
|
|
|
|
1;
|
|
|
|
|