package MyRedland::Stripe; use v5.34.1; use strict; use warnings; use MyRedland::DB; use MyRedland::Lusers; use Mojo::UserAgent; use Moo; use Params::ValidationCompiler qw/validation_for/; use Types::Standard qw/Str InstanceOf HashRef Int Bool/; use MIME::Base64; use Data::Dumper; use Mojo::Util qw/url_escape/; my $ua = Mojo::UserAgent->new; has app => ( is => 'ro', isa => InstanceOf ['Mojolicious'], ); has _dbh => ( is => 'lazy', ); has _stripe_secret => ( is => 'lazy', ); has _users_dao => ( is => 'lazy', ); sub _build__dbh { my $self = shift; return MyRedland::DB->new( app => $self->app ); } sub _build__stripe_secret { my $self = shift; return $self->app->config->{stripe_secret}; } sub _build__users_dao { my $self = shift; return MyRedland::Lusers->new( app => $self->app ); } { my $validator = validation_for( params => { method => { type => Str }, url => { type => Str }, form => { type => HashRef, optional => 1 }, headers => { type => HashRef, optional => 1 }, } ); sub _make_request { my $self = shift; my %params = $validator->(@_); my $method = $params{method}; my $url = $params{url}; my $headers = $params{headers} // {}; $headers->{Authorization} = 'Basic ' . encode_base64( $self->_stripe_secret . ':', '' ); my $form = $params{form}; my $tx = $ua->build_tx( $method, $url, $headers, ( ( defined $form ) ? ( form => $form ) : () ) ); return $ua->start($tx); } } sub create_customer_for_user { my $self = shift; my $user = shift; if ( defined $user->stripe_customer_id ) { return $user; } my $response = $self->_make_request( method => 'POST', url => 'https://api.stripe.com/v1/customers' )->result->json; $user->stripe_customer_id( $response->{id} ); $user = $self->_users_dao->update( user => $user, fields => [qw/stripe_customer_id/] ); return $user; } { my $validator = validation_for( params => { user => { type => InstanceOf ['MyRedland::Luser'], }, price => { type => Int, }, off_session => { type => Bool }, } ); sub create_payment_intent { my $self = shift; my %params = $validator->(@_); my ( $user, $price, $off_session ) = @params{qw/user price off_session/}; my $response = $self->_make_request( method => 'POST', url => 'https://api.stripe.com/v1/payment_intents', form => { currency => 'eur', amount => $price, 'payment_method_types[]' => 'card', customer => $user->stripe_customer_id, ( ($off_session) ? ( off_session => $off_session ) : () ), } )->result->json; if ( defined $response->{error} ) { die Data::Dumper::Dumper $response->{error}; } return $response; } } { my $validator = validation_for( params => { payment_intent_id => { type => Str } } ); sub retrieve_payment_intent { my $self = shift; my %params = $validator->(@_); my ($payment_intent_id) = $params{'payment_intent_id'}; my $response = $self->_make_request( method => 'GET', url => 'https://api.stripe.com/v1/payment_intents/'.url_escape($payment_intent_id), )->result->json; if ( defined $response->{error} ) { die Data::Dumper::Dumper $response->{error}; } return $response; } } { my $validator = validation_for( params => { payment_intent_id => { type => Str }, updates => { type => HashRef } } ); sub update_payment_intent { my $self = shift; my %params = $validator->(@_); my ($payment_intent_id, $updates) = @params{qw/payment_intent_id updates/}; my $response = $self->_make_request( method => 'POST', url => 'https://api.stripe.com/v1/payment_intents/'.url_escape($payment_intent_id), form => $updates, )->result->json; print Data::Dumper::Dumper $response; if ( defined $response->{error} ) { die Data::Dumper::Dumper $response->{error}; } return $response; } } 1;