mourningdove/cgi-bin/DW/Controller/Shop/Stripe.pm
2026-05-24 01:03:05 +00:00

76 lines
2.1 KiB
Perl

#!/usr/bin/perl
#
# DW::Controller::Shop::Stripe
#
# Controllers for the Stripe endpoints for the shop.
#
# Authors:
# Mark Smith <mark@dreamwidth.org>
#
# Copyright (c) 2019 by Dreamwidth Studios, LLC.
#
# This program is free software; you may redistribute it and/or modify it under
# the same terms as Perl itself. For a copy of the license, please reference
# 'perldoc perlartistic' or 'perldoc perlgpl'.
#
package DW::Controller::Shop::Stripe;
use strict;
use Carp qw/ confess /;
use Digest::SHA qw/ hmac_sha256_hex /;
use LJ::JSON;
use DW::Routing;
use DW::Controller;
use DW::Controller::Shop;
use DW::Shop::Engine::Stripe;
DW::Routing->register_string( '/shop/stripe-checkout', \&stripe_checkout_handler, app => 1 );
DW::Routing->register_string( '/shop/stripe-webhook', \&stripe_webhook_handler, format => 'json' );
sub _stripe_controller {
my ( $ok, $rv ) = DW::Controller::Shop::_shop_controller(@_);
if ($ok) {
$rv->{stripe_published_key} = $LJ::STRIPE{published_key} // '';
}
return ( $ok, $rv );
}
sub stripe_checkout_handler {
my ( $ok, $rv ) = _stripe_controller( anonymous => 1 );
return $rv unless $ok;
$rv->{stripe_session_id} = $rv->{cart}->paymentmethod_metadata('session_id');
return DW::Template->render_template( 'shop/stripe/checkout.tt', $rv );
}
sub stripe_webhook_handler {
my ( $ok, $rv ) = _stripe_controller( anonymous => 1 );
my $r = $rv->{r};
my $raw_json = $r->content;
my $event = from_json($raw_json);
# validate webhook signature
my $signature = $r->header_in('Stripe-Signature');
my %elems = map { split /=/, $_ } split( /,\s*/, $signature );
my $payload = $elems{t} . '.' . $raw_json;
my $hmac = hmac_sha256_hex( $payload, $LJ::STRIPE{webhook_key} );
if ( $hmac ne $elems{v1} ) {
$r->status(400);
$r->print('Invalid webhook signature.');
return $r->OK;
}
# Signature validated, process
my ( $status, $msg ) = DW::Shop::Engine::Stripe->process_webhook($event);
$r->status($status);
$r->print($msg);
return $r->OK;
}
1;