ultranerds has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm trying to get PayPal's Adaptive API working (so I can create multiple payments going out to multiple sellers, from one buyer). I'm still struggling to get my head around how you are mean't to pass in the request though. There seems to be 0% documentation on Perl. So far I'm just trying to get the basic connection going, I have:

#!/usr/bin/perl use warnings; use strict; use HTTP::Request::Common; use LWP::UserAgent; use XML::Simple; my $user = 'andy.business_api1.123.co.uk'; my $password = 'some password'; my $signature = 'my key'; my $application_id = 'APP-xxxxx'; my $url = 'https://svcs.sandbox.paypal.com/AdaptivePayments +/Pay'; use SOAP::Lite; eval "use SOAP::Lite +trace => 'debug';"; # create header for requests my $authHeader = SOAP::Header->name("xsd:authHeader" => \SOAP::Header- +>value( SOAP::Header->name('X-PAYPAL-SECURITY-USERID')->value($user)->type +(''), SOAP::Header->name('X-PAYPAL-SECURITY-PASSWORD')->value($password) +->type(''), SOAP::Header->name('X-PAYPAL-SECURITY-SIGNATURE')->value($signatur +e)->type(''), SOAP::Header->name('X-PAYPAL-APPLICATION-ID')->value($application_ +id)->type(''), SOAP::Header->name('X-PAYPAL-DEVICE-IPADDRESS')->value($ENV{REMOTE +_ADDR})->type(''), SOAP::Header->name('X-PAYPAL-MESSAGE-PROTOCOL'1)->value('SOAP11')- +>type(''), )); my $soap = SOAP::Lite->new( proxy => $url); $soap->on_debug(sub { print @_ }); $soap->default_ns('urn:HelloWorld'); my $som = $soap->call('sayHello', SOAP::Data->name('name')->value('Kutter'), SOAP::Data->name('givenName')->value('Martin'), $authHeader ); die $som->faultstring if ($som->fault); print $som->result, "\n";
However, it always dies:

Authentication failed. API credentials are incorrect. at test.cgi line 44.

I managed to kinda get it working using LWP::UserAgent/ HTTP::Headers, like so:
my $ua = LWP::UserAgent->new(); my $headers = HTTP::Headers->new( 'X-PAYPAL-SECURITY-USERID' => $user, 'X-PAYPAL-SECURITY-PASSWORD' => $password, 'X-PAYPAL-SECURITY-SIGNATURE' => $signature, 'X-PAYPAL-APPLICATION-ID' => $application_id, 'X-PAYPAL-DEVICE-IPADDRESS' => $ENV{REMOTE_ADDR}, 'X-PAYPAL-MESSAGE-PROTOCOL' => 'SOAP11'); my $format = '%s' x 8; my $content = qq|<?xml version="1.1" encoding="utf-8"?> <Envelope xmlns=""> <PayRequest xmlns="http://svcs.paypal.com/types/ap"> <detailLevel>ReturnAll</detailLevel> <errorLanguage >en_US</errorLanguage> <actionType xmlns="">PAY</actionType> <currencyCode xmlns="">USD</currencyCode> <receiverList xmlns=""> <receiver> <amount>5</amount> <email>andy.newby\@gmail.com</email> </receiver> </receiverList> <sender> <useCredentials xmlns=""></useCredentials> </sender> <account xmlns=""> <phone xmlns=""></phone> </account> <returnUrl xmlns="">http://paypal.site.com/paypal/class/1.2/Pa +y_Return.html</returnUrl> <cancelUrl xmlns="">http://paypal.site.com/paypal/class/1.2/Pa +y_Cancel.html</cancelUrl> <payKey>AP-xxxxxxxxxxxxx</payKey> </PayRequest> </Envelope> |; my $request = HTTP::Request->new( 'POST', $url, $headers, $content ); my $response = $ua->request( $request ); print $response->decoded_content; use Data::Dumper; print Dumper(XMLin($response->decoded_content));
..but it always gives me this error:
'soapenv:Text' => {
 'content' => 'Only SOAP 1.1 or SOAP 1.2 messages are supported in the system',
 'xml:lang' => 'en-US'
}
I'm at a bit of a loss as to what else to try! (this is my first SOAP script, so please be nice ;))

FWIW, someone on the paypal dev forums (doesn't know about Perl, but seems to know how the SOAP should be formatted), said this should work:
<?xml version="1.0" encoding="utf-8"?> <PayRequest xmlns="http://svcs.paypal.com/types/ap"> <requestEnvelope xmlns=""> <detailLevel>ReturnAll</detailLevel> <errorLanguage>en_US</errorLanguage> </requestEnvelope> <actionType xmlns="">PAY</actionType> <cancelUrl xmlns="">http://paypal.angelleye.com/paypal/class/1.2/Pay +_Cancel.php</cancelUrl> <clientDetails xmlns=""> <applicationId xmlns="">APP-80W284485P519543T</applicationId> <ipAddress xmlns="">37.187.79.225</ipAddress> <partnerName xmlns="">Always Give Back</partnerName> </clientDetails> <currencyCode xmlns="">USD</currencyCode> <receiverList xmlns=""> <receiver xmlns=""> <amount xmlns="">10.00</amount> <email xmlns="">sandbo_1204199080_biz@angelleye.com</email> </receiver> <receiver xmlns=""> <amount xmlns="">5.00</amount> <email xmlns="">usb_1329725429_biz@angelleye.com</email> <invoiceId xmlns="">123-ABCDEF</invoiceId> </receiver> </receiverList> <sender> <useCredentials xmlns=""></useCredentials> </sender> <account xmlns=""> <phone xmlns=""></phone> </account> <returnUrl xmlns="">http://paypal.angelleye.com/paypal/class/1.2/Pay +_Return.php</returnUrl> </PayRequest>

Replies are listed 'Best First'.
Re: PayPal Adaptive SOAP request? (JSON)
by Anonymous Monk on Apr 01, 2014 at 09:24 UTC
      Thanks for the reply. I have actually tried that module already, but it doesn't work with the parallel payments AFAIK.

      For the JSON - thanks, I'll take a look into that. I would also prefer that method, as its much easier to make a hashref, then convert it using JSON.pm into a JSON string.

      Thanks!
      Thanks, its getting there :)

      my $user = 'xxxx'; my $password = 'xxx'; my $signature = 'xxx'; my $application_id = 'APP-80W284485P519543T'; my $url = 'https://svcs.sandbox.paypal.com/AdaptivePayments +/Pay'; my $ua = LWP::UserAgent->new(); my $headers = HTTP::Headers->new( 'X-PAYPAL-SECURITY-USERID' => $user, 'X-PAYPAL-SECURITY-PASSWORD' => $password, 'X-PAYPAL-SECURITY-SIGNATURE' => $signature, 'X-PAYPAL-APPLICATION-ID' => $application_id, 'X-PAYPAL-DEVICE-IPADDRESS' => $ENV{REMOTE_ADDR}, 'X-PAYPAL-REQUEST-DATA-FORMAT' => 'JSON', 'X-PAYPAL-RESPONSE-DATA-FORMAT' => 'JSON' ); my $json_var = { requestEnvelope => { detailLevel => "ReturnAll", errorLanguage => "en_US", }, actionType => "PAY", currencyCode => "USD", receiverList => { receiver => [ { amount => 5, email => 'andy.newby@gmail.com', totalShipping => 10 }, { amount => 15, email => 'foobar@gmail.com' } ], }, returnUrl => 'http://paypal.angelleye.com/paypal/class/1.2/Pay +_Return.php', cancelUrl => 'http://paypal.angelleye.com/paypal/class/1.2/Pay +_Cancel.php' }; use JSON; my $new_json = JSON::to_json($json_var); # print "FOO: $new_json \n\n"; my $request = HTTP::Request->new( 'POST', $url, $headers, $new_json ) +; my $response = $ua->request( $request ); #print $response->status_line, "\n"; my $json_returned = decode_json($response->decoded_content); print qq|Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_ +ap-payment&paykey=$json_returned->{payKey} \n\n|;
      The only thing I can't figure out now, is how to get a shipping price in per person. I guess I could just add it into the total cost, but I think people would prefer to see it as a separate field.

      Any ideas on that one? (not sure how familiar you are with this payment system)