package Pear::LocalLoop::Controller::Api::Sendmessage; use Mojo::Base 'Mojolicious::Controller'; use LWP::UserAgent; use JSON; use JSON::Parse 'parse_json'; use Mojo::JWT; use Mojo::File; use Carp; has error_messages => sub { return { devicetoken => { required => { message => 'Device token is required', status => 400 }, in_resultset => { message => 'Device token not found', status => 400 }, }, sender => { required => { message => 'Sender name is required', status => 400 }, in_resultset => { message => 'Sender org not found', status => 400 }, }, messagetext => { required => { message => 'Message is required', status => 400 }, }, }; }; =begin comment Credit: Peter Scott/StackOverflow https://stackoverflow.com/a/53357961/4580273 Credit: jeffez/StackOverflow https://stackoverflow.com/q/56556438/4580273 =cut my $jwt = create_jwt_from_path_and_scopes('./localspend-47012.json', 'email https://www.googleapis.com/auth/cloud-platform'); my $ua = LWP::UserAgent->new(); my $response = $ua->post('https://www.googleapis.com/oauth2/v4/token', { 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt } ); my $bearer_token = parse_json($response->content); sub create_jwt_from_path_and_scopes { my ( $path, $scope ) = @_; croak("No path provided") if not defined $path; croak("$path not available") if not -f $path; my $json = decode_json( Mojo::File->new($path)->slurp ); croak("No Private key in $path") if not defined $json->{private_key}; croak("Not a service account") if $json->{type} ne 'service_account'; my $jwt = Mojo::JWT->new(); $jwt->algorithm('RS256'); $jwt->secret($json->{private_key}); $jwt->claims( { iss => $json->{client_email}, scope => $scope, aud => 'https://www.googleapis.com/oauth2/v4/token', iat => time(), exp => time()+3600 } ); $jwt->set_iat( 1 ); return $jwt->encode; } sub post_message { my $c = shift; my $validation = $c->validation; $validation->input( $c->stash->{api_json} ); $validation->required('devicetoken')->in_resultset('token', $c->schema->resultset('DeviceToken')); $validation->required('sender')->in_resultset('name', $c->schema->resultset('Organisation')); $validation->required('messagetext'); return $c->api_validation_error if $validation->has_error; my $end_point = "https://fcm.googleapis.com/v1/projects/localspend-47012/messages:send"; my $request = HTTP::Request->new('POST', $end_point); $request->header('Authorization' => "Bearer $bearer_token->{access_token}"); $request->header('Content-Type' => 'application/json'); $request->content(JSON::encode_json ({ message => { token => $validation->param('devicetoken'), notification => { title => $validation->param('sender'), body => $validation->param('messagetext') }, webpush => { headers => { urgency => 'very-low' }, notification => { title => $validation->param('sender'), body => $validation->param('messagetext'), } } } })); my $response = $ua->request($request); if ($response->is_success) { return $c->render( json => { success => Mojo::JSON->true, message => 'Your message has been sent successfully!', }); } elsif ($response->is_error) { return $c->render( json => { success => Mojo::JSON->false, message => [ $response->decoded_content, $jwt, $bearer_token ], error => 'message_error', }, status => $response->code, ); } } 1;