Business-Giropay/lib/Business/Giropay/Role/Response.pm
package Business::Giropay::Role::Response;
=head1 NAME
Business::Giropay::Role::Response - Moo::Role consumed by all Response classes
=cut
use Carp;
use Digest::HMAC_MD5 'hmac_md5_hex';
use Business::Giropay::Types qw/Bool HashRef Int Maybe Str/;
use JSON::MaybeXS;
use Moo::Role;
with 'Business::Giropay::Role::Network';
=head1 ATTRIBUTES
=head2 json
The json message data returned from giropay. Required.
=cut
has json => (
is => 'ro',
isa => Str,
required => 1,
);
=head2 data
L</json> data converted to a hash reference.
=cut
has data => (
is => 'lazy',
isa => HashRef,
init_arg => undef,
);
sub _build_data {
return decode_json( shift->json );
}
=head2 rc
Response code / error number.
=cut
has rc => (
is => 'lazy',
isa => Int,
init_arg => undef,
);
sub _build_rc {
shift->data->{rc};
}
=head2 msg
Additional information on error (possibly empty).
=cut
has msg => (
is => 'lazy',
isa => Maybe [Str],
init_arg => undef,
);
sub _build_msg {
shift->data->{msg};
}
=head2 hash
The HMAC hash of the returned message. Required.
=cut
has hash => (
is => 'ro',
isa => Str,
required => 1,
);
=head2 secret
The Giropay shared secret for current C</merchantId> and C</projectId>,
=cut
has secret => (
is => 'ro',
isa => Str,
required => 1,
);
=head2 success
Boolean response indicating whether L</rc> indicates success.
=cut
has success => (
is => 'lazy',
isa => Bool,
init_arg => undef,
);
sub _build_success {
return shift->rc == 0 ? 1 : 0;
}
=head1 METHODS
=head2 BUILD
Check that the hash matches what we expect. Die on mismatch
=cut
sub BUILD {
my $self = shift;
my $verify = hmac_md5_hex( $self->json, $self->secret );
croak(
"Returned HMAC hash ", $self->hash,
" does not match expected hash ", $verify, " for json ", $self->json
) unless $verify eq $self->hash;
}
1;