Dealing with a STRANGE API

I

Ignoramus7272

I am using PayPal API class

Business::payPal::API::TransactionSearch

It uses some very weird code

my %response = ();
unless( $self->getBasic($som, $path, \%response) ) {
$self->getErrors($som, $path, \%response);
return %response;
}

return $self->getFieldsList( $som, $path . '/PaymentTransactions',
{ Timestamp => 'Timestamp',
Timezone => 'Timezone',
Type => 'Type',
Payer => 'Payer',
PayerDisplayName => 'PayerDisplayName',
TransactionID => 'TransactionID',
Status => 'Status',
GrossAmount => 'GrossAmount',
FeeAmount => 'FeeAmount',
NetAmount => 'NetAmount',
} );

that is, it returns a hash when there is error, and a list reference when there is not.

I am bewildered, just how can I get this result into one variable and
then figure out if I am dealing with success (so that I can print
results from the list reference), or failure (so that I can print a
hash element error message).

Any idea? I tried obvious things like setting a scalar to the result
of this function, and could not.

The man pages gloss over this issue. I did read them in their entirety.

i
 
A

anno4000

Ignoramus7272 said:
I am using PayPal API class

Business::payPal::API::TransactionSearch

It uses some very weird code

Indeed. Snipped.
that is, it returns a hash when there is error, and a list reference
when there is not.

I am bewildered, just how can I get this result into one variable and
then figure out if I am dealing with success (so that I can print
results from the list reference), or failure (so that I can print a
hash element error message).

Any idea? I tried obvious things like setting a scalar to the result
of this function, and could not.

Untested:

my @mystery = $obj->meth_from_hell( ...);

if ( @mystery == 1 ) {
my @array = @{ $mystery[ 0] };
# normal processing
} else {
my %hash = @mystery;
# error
}

The distinction is reliable because the hash returns an even number of
scalars.

You shouldn't have to do this.

Anno
 
B

Ben Morrow

Quoth Ignoramus7272 said:
[snipped]

OK, thanks. I used your code to write this:

sub run_weird_method {
my ($sub, @args) = @_;
my @mystery = &$sub( @args );

I don't know if you realise, but this will not call $sub as a method.
(Even if you pass in an object as the first argument manually, you will
not get any inheritance). You would have to call this function as

my %results = run_weird_method
sub { $PayPal->TransactionSearch(@_) },
qw/foo bar baz/;

which is a little odd, to say the least. For my part, if I really wanted
a general-purpose sub like this (AFAICT, this is the only sub in
Business::payPal that behaves like this, so I'd probably just wrap
that), I would either prototype it to accept a coderef and call that:

sub call_weird (&) {
my ($sub) = @_;
my @mystery = $sub->();
...
}

my $results = call_weird {
$PayPay->TransactionSearch(qw/foo bar baz/);
};

or simply accept and translate a list:

sub remove_weirdness {
my @mystery = @_;
...
}

my $results = remove_weirdness
$PayPal->TransactionSearch(qw/foo bar baz/);

If you really want to pass a method and an arglist you would need to
accept an object argument as well:

sub run_weird_method {
my ($obj, $meth, @args) = @_;
my @mystery = $obj->$meth(@args);
...
}

my $results = run_weird_method
$PayPal, TransactionSearch => qw/foo bar baz/;

A quick scan of the docs for B::pP::A::TS suggests that this behaviour is
a bug. Indeed, both the initial example and the "ERROR HANDLING" section
state that a succesful return *also* returns a hash, with a true 'Ack'
member and the result somewhere else (unspecified) in the hash. The 0.11
version says the module is still in alpha: Be Very Careful. Alpha
modules playing with your money is not something I would like. Depending
on how much work you want to do, you may be better off calling the
PayPal API yourself with SOAP::Lite.
if ( @mystery == 1 ) {
# normal processing
return { success => 1, result => $mystery[0] };
}

# Failure
my %hash = @mystery;
return { success => 0, result => \%hash };

Here I would instead emulate the rest of the B::pP::A interface, that is

if (@mystery == 1) {
# success
return ( Ack => 'Success', Results => $mystery[0] );
}
else {
# failure

# the hash should already have an Ack => 'Failure' member
return @mystery;

# if for some reason it doesn't:
# return ( Ack => 'Failure', @mystery );
}

Not that I like that interface one bit, but consistency is always a good
thing :).

I would also consider overwriting &B::pP::A::TS::TransactionSearch with
a sub that behaves correctly (perhaps with Hook::LexWrap); and
submitting a patch to the author.

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top