Business-TrueLayer

 view release on metacpan or  search on metacpan

lib/Business/TrueLayer/Request.pm  view on Meta::CPAN


no warnings qw/ experimental::signatures experimental::postderef /;

use Business::TrueLayer::Types;
use Business::TrueLayer::Authenticator;
use Business::TrueLayer::Signer;

use Try::Tiny::SmartCatch;
use Mojo::UserAgent;
use Carp qw/ croak /;
use JSON;
use Data::GUID;

my $MAX_REDIRECTS = 5;

has [ qw/ client_id client_secret kid / ] => (
    is        => 'ro',
    isa       => 'Str',
    required  => 0,
);

has 'host' => (
    is        => 'ro',
    isa       => 'Str',
    required  => 0,
    default   => sub ( $self ) {
        'truelayer.com',
    }
);

has api_host => (
    is        => 'ro',
    isa       => 'Str',
    required  => 0,
    lazy      => 1,
    default   => sub ( $self ) {
        return join( '.','api',$self->host );
    }
);

has auth_host => (
    is        => 'ro',
    isa       => 'Str',
    required  => 0,
    lazy      => 1,
    default   => sub ( $self ) {
        return join( '.','auth',$self->host );
    }
);

has payment_host => (
    is        => 'ro',
    isa       => 'Str',
    required  => 0,
    lazy      => 1,
    default   => sub ( $self ) {
        return join( '.','payment',$self->host );
    }
);

has 'private_key' => (
    is       => 'ro',
    isa      => 'EC512:PrivateKey',
    coerce   => 1,
    required => 0,
);

has '_ua' => (
    is        => 'ro',
    isa       => 'UserAgent',
    required  => 0,
    default   => sub {
        return Mojo::UserAgent->new
            ->max_redirects( $MAX_REDIRECTS )
            ->connect_timeout( 5 )
            ->inactivity_timeout( 5 )
            ->request_timeout( 30 )
        ;
    },
);

has 'authenticator' => (
    is        => 'ro',
    isa       => 'Authenticator',
    lazy      => 1,
    default   => sub ( $self ) {

        Business::TrueLayer::Authenticator->new(
            client_id     => $self->client_id,
            client_secret => $self->client_secret,
            host          => $self->auth_host,
            _ua           => $self->_ua,
        );
    },
);

has 'signer' => (
    is        => 'ro',
    isa       => 'Signer',
    lazy      => 1,
    default   => sub ( $self ) {

        Business::TrueLayer::Signer->new(
            kid         => $self->kid,
            private_key => $self->private_key,
        );
    },
);

sub idempotency_key ( $self ) {
    return Data::GUID->new->as_string;
}

sub api_post (
    $self,
    $absolute_path,
    $http_request_body = undef,
    $expect_json = 1,
) {
    # sign the request
    my $idempotency_key = $self->idempotency_key;

    my $json = $http_request_body
        ? JSON->new->utf8->canonical->encode( $http_request_body )
        : undef;

    my ( $jws ) = $self->signer->sign_request(
        'POST',
        $absolute_path,
        $idempotency_key,
        $json,
    );

    return $self->_ua_request(
        "https://" . $self->api_host . $absolute_path,
        $json,
        [
            'Authorization' => "Bearer " . $self->authenticator->access_token,
            'Tl-Signature'  => $jws,
            'Idempotency-Key' => $idempotency_key,
        ],
        'POST',
        $expect_json
    );
}

sub _ua_request (
    $self,
    $url,
    $body,
    $headers = undef,
    $method = 'POST',
    $expect_json = 1
) {

    my $ua = $self->_ua;
    my $res = $ua->start($ua->build_tx(
        $method,
        $url,
        {
            'Accept'        => 'application/json; charset=UTF-8',
            'Content-Type'  => 'application/json; charset=UTF-8',
            @{ $headers // [] },
        },
        # Mojo::UserAgent::Transactor::tx calls $self->generators and then the



( run in 0.503 second using v1.01-cache-2.11-cpan-ceb78f64989 )