Business-GoCardless/lib/Business/GoCardless/Webhook.pm
package Business::GoCardless::Webhook;
=head1 NAME
Business::GoCardless::Webhook
=head1 DESCRIPTION
A class for gocardless webhooks, extends L<Business::GoCardless::Resource>.
For more details see the gocardless API documentation specific to webhooks:
https://developer.gocardless.com/#webhook-overview
=cut
use strict;
use warnings;
use Moo;
extends 'Business::GoCardless::Resource';
with 'Business::GoCardless::Utils';
use JSON ();
use Business::GoCardless::Exception;
=head1 ATTRIBUTES
resource_type
action
=cut
has [ qw/
resource_type
action
_payload
/ ] => (
is => 'rw',
clearer => 1,
);
=head1 Operations on a webhook
=head2 json
Allows you to set the json data sent to you in the webhook:
$Webhook->json( $json_data )
Will throw a L<Business::GoCardless::Exception> exception if the json fails to
parse or if the signature does not match the payload data.
=cut
has json => (
is => 'rw',
required => 1,
trigger => sub {
my ( $self,$json ) = @_;
# defensive decoding
my $params;
eval { $params = JSON->new->decode( $json ) };
$@ && do {
$self->_clear_payload;
$self->clear_resource_type;
$self->clear_action;
Business::GoCardless::Exception->throw({
message => "Failed to parse json: $@",
});
};
$self->resource_type( $params->{payload}{resource_type} );
$self->action( $params->{payload}{action} );
$self->_payload( $params->{payload} );
if ( ! $self->signature_valid(
$params->{payload},$self->client->app_secret )
) {
$self->_clear_payload;
$self->clear_resource_type;
$self->clear_action;
Business::GoCardless::Exception->throw({
message => "Invalid signature for webhook",
});
}
return $json;
}
);
=head2 resources
Returns an array of resource objects (Bill, Subscription, etc) that are present
in webhook allowing you to do things with them or update your own data:
if ( $Webhook->is_bill ) {
foreach my $Bill ( $Webhook->resources ) {
...
}
} elsif ( $Webhook->is_subscription ) {
...
=cut
sub resources {
my ( $self ) = @_;
my @resources;
return if ! $self->resource_type;
my $key = {
bill => 'bills',
pre_authorization => 'pre_authorizations',
subscription => 'subscriptions',
}->{ $self->resource_type };
my $class_suffix = ucfirst( $self->resource_type );
$class_suffix =~ s/_([A-z])/uc($1)/ge;
my $class = "Business::GoCardless::$class_suffix";
foreach my $hash ( @{ $self->_payload->{ $key } } ) {
my $obj = $class->new(
client => $self->client,
%{ $hash },
);
push( @resources,$obj );
}
return @resources;
}
=head2 is_bill
=head2 is_pre_authorization
=head2 is_subscription
Shortcut methods to get the type of data in the webhook, and thus the type of
objects that will be returned by the call to ->resources
=cut
sub is_bill { return shift->resource_type eq 'bill' }
sub is_pre_authorization { return shift->resource_type eq 'pre_authorization' }
sub is_subscription { return shift->resource_type eq 'subscription' }
=head2 is_legacy
See if the webhook is a legacy (Basic API) webhook
if ( $Webhook->is_legacy ) {
...
}
=cut
sub is_legacy { 1 }
=head1 CONFIRMING WEBHOOKS
According to the gocardless API docs you should respond once the signature of the
webhook has been checked. The response is a HTTP status 200 code:
HTTP/1.1 200 OK
You should handle this in your own code, the library will not do it for you. See
https://developer.gocardless.com/#response for more information
=head1 AUTHOR
Lee Johnson - C<leejo@cpan.org>
This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself. If you would like to contribute documentation,
features, bug fixes, or anything else then please raise an issue / pull request:
https://github.com/Humanstate/business-gocardless
=cut
1;
# vim: ts=4:sw=4:et