WebService-Braintree
view release on metacpan or search on metacpan
lib/WebService/Braintree/WebhookNotificationGateway.pm view on Meta::CPAN
# vim: sw=4 ts=4 ft=perl
package # hide from pause
WebService::Braintree::WebhookNotificationGateway;
use 5.010_001;
use strictures 1;
use Moo;
use Carp qw(confess);
use MIME::Base64;
use WebService::Braintree::Digest qw(hexdigest);
use WebService::Braintree::Xml qw(xml_to_hash);
use WebService::Braintree::_::WebhookNotification;
# This does not use Role::MakeRequest which provides the gateway attribute.
has 'gateway' => (is => 'ro');
sub parse {
my ($self, $signature, $payload) = @_;
$self->_validate_signature($signature, $payload);
my $xml_payload = decode_base64($payload);
my $attributes = xml_to_hash($xml_payload);
WebService::Braintree::_::WebhookNotification->new($attributes->{notification});
}
sub _matching_signature {
my ($self, $signature, $payload) = @_;
foreach my $signature_pair (split("&", $signature)) {
my @components = split("\\|", $signature_pair);
if ($components[0] eq $self->gateway->config->public_key) {
return $components[1];
}
}
# Definitively return undef if nothing is found.
return;
}
sub _validate_signature {
my ($self, $signature, $payload) = @_;
my $matching_signature = $self->_matching_signature($signature, $payload);
if (!defined($matching_signature) || $matching_signature ne hexdigest($self->gateway->config->private_key, $payload)) {
confess "InvalidSignature";
}
return 1;
}
sub verify {
my ($self, $challenge) = @_;
if ($challenge !~ /^[a-f0-9]{20,32}$/) {
confess "InvalidChallenge";
}
return $self->gateway->config->public_key . "|" . hexdigest($self->gateway->config->private_key, $challenge);
}
__PACKAGE__->meta->make_immutable;
1;
__END__
( run in 1.025 second using v1.01-cache-2.11-cpan-39bf76dae61 )