Business-iDEAL-Adyen

 view release on metacpan or  search on metacpan

lib/Business/iDEAL/Adyen.pm  view on Meta::CPAN

sub _carp {
    my $self = shift;
    Carp::carp(@_);
}

sub _init {
    my ($self, $args) = @_;

    # test for mandatory fields
    for(qw/shared_secret skinCode merchantAccount/) {
       $self->_croak("$_ not set") unless $args->{$_};
    }

    # set some defaults and let user override if needed
    my %options = (
        ua            => LWP::UserAgent->new(
                             agent => __PACKAGE__." v. ".$VERSION,
			     requests_redirectable => '',
                         ),
        xso           => XML::Simple->new(),
	hmac          => Digest::HMAC_SHA1->new(delete $args->{shared_secret}),
        prod_base_url => 'https://live.adyen.com',
        test_base_url => 'https://test.adyen.com',
        banklist_path => '/hpp/idealbanklist.shtml',
        redirect_path => '/hpp/redirectIdeal.shtml',
        %{ $args }
    );

    # map all keys to $self->{_$key} for easy access
    $self->{"_$_"} = $options{$_} for (keys %options);
}

sub _url {
    my ($self, $type) = @_;

    # determine what path we need and whether that exists or not
    my $path = $self->{"_".$type."_path"} or 
        $self->_croak("Unknown type '$type'");

    # return the test or production url based on $type input
    return ($self->{_test} ? $self->{_test_base_url} 
                           : $self->{_prod_base_url}).
            $path;
}

sub _parse_xml {
    my ($self, $input) = @_;
    return unless($input);

    return $self->{_xso}->XMLin($input);    
}

sub _sign_req {
    my ($self, $args) = @_;

    my $plaintext = '';
    if($args->{paymentAmount}) {
        # Initial signature (the one we _send_)
        for(qw/paymentAmount currencyCode shipBeforeDate merchantReference 
               skinCode merchantAccount sessionValidity shopperEmail 
               shopperReference allowedMethods blockedMethods/) {
            $plaintext .= ( defined $self->{"_$_"} ) 
                       ? $self->{"_$_"} : ( $args->{$_} || "" );
        }
    } else {
        # Second signature (the one we _receive_)
        for(qw/authResult pspReference merchantReference skinCode/) {
            $plaintext .= ( defined $self->{"_$_"} ) 
                       ? $self->{"_$_"} : ( $args->{$_} || "" );
        }
    }

    $self->{_hmac}->add($plaintext);
    my $b64_digest = $self->{_hmac}->b64digest;
       $b64_digest .= '=' while (length($b64_digest) % 4);

    return $b64_digest; 
}

=pod

=head3 banklist

In order to offer all iDEAL banks, you will have to fetch a list
with their names and codes. This list is subject to change, so check
this often (Adyen recommends "regularly (e.g. once a day)").
I'd suggest to always check this before a payment.

This method will return an arrayref with the bank_ids and bank_names,
or undef in case an error occured (see L<"error">)

=cut

sub banklist {
    my $self = shift;

    my $res = $self->{_ua}->get($self->_url('banklist'));
    if ($res->is_success) {
        return $self->_parse_xml($res->decoded_content)->{'bank'};
    } else {
        $self->{_error} = $res->status_line;
        return undef;
    }
}

=pod

=head3 fetch

After you've retrieved the L<"banklist">, your users may choose the preferred
bank. Now you can feed that 'bank_id', together with the other mandatory
options to this method.

C<fetch> will return an URL to the bank's iDEAL page that the user should
be directed to.

Some fields are mandatory, while others have somewhat sane defaults and
may be skipped.

=head4 options



( run in 3.452 seconds using v1.01-cache-2.11-cpan-8dfa8b56332 )