3

Could I get a simple example of using PHP's SoapClient class to make an empty call to Paypal with nothing but the version number? I have the correct WSDL url and server url, so that's not what I need help with. This is what I have:

public function SOAPcall($function, $args=array()) {
    $args['Version'] = '63.0';
    $args = new SoapVar($args, SOAP_ENC_ARRAY, $function.'_Request');
    $args = array(new SoapVar($args, SOAP_ENC_ARRAY, $function.'_Req', 'urn:ebay:api:PayPalAPI'));
    $results = $this->soapClient->__soapCall($function, $args, array('location' => $this->activeKeys['certificate']), $this->soapOptions);
}

I hope it's okay I am not showing everything. The body of the request comes out completely wrong, as you can see below:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:ebay:api:PayPalAPI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="urn:ebay:apis:eBLBaseComponents">
      <SOAP-ENV:Header>
            <ns1:RequesterCredentials>
                  <ns2:Credentials>
                        <ns2:Username>xxx</ns2:Username>
                        <ns2:Password>xxx</ns2:Password>
                        <ns2:Signature>xxx</ns2:Signature>
                  </ns2:Credentials>
            </ns1:RequesterCredentials>
      </SOAP-ENV:Header>
      <SOAP-ENV:Body>
            <ns1:GetBalanceReq xsi:type="ns1:GetBalance_Req">
                  <xsd:string>63.0</xsd:string>
            </ns1:GetBalanceReq>
      </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

It should look like this:

<?xml version=”1.0” encoding=”UTF-8”?>
<SOAP-ENV:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:SOAP-ENC=”http://schemas.xmlsoap.org/soap/encoding/”
xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”
><SOAP-ENV:Header>
<RequesterCredentials xmlns=”urn:ebay:api:PayPalAPI”>
<Credentials xmlns=”urn:ebay:apis:eBLBaseComponents”>
<Username>api_username</Username>
<Password>api_password</Password>
<Signature/>
<Subject/>
</Credentials>
</RequesterCredentials>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<specific_api_name_Req xmlns=”urn:ebay:api:PayPalAPI”>
<specific_api_name_Request>
<Version xmlns=urn:ebay:apis:eBLBaseComponents”>service_version
</Version>
<required_or_optional_fields xsi:type=”some_type_here”> data
</required_or_optional_fields>
</specific_api_name_Request>
</specific_api_name_Req>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Of course, Paypal throws a "Version is not supported" error.

hakre
  • 193,403
  • 52
  • 435
  • 836
Jonah
  • 2,040
  • 7
  • 29
  • 32

3 Answers3

6

This is the cleanest solution I could come up with:

$client = new SoapClient( 'https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl',
                           array( 'soap_version' => SOAP_1_1 ));

$cred = array( 'Username' => $username,
               'Password' => $password,
               'Signature' => $signature );

$Credentials = new stdClass();
$Credentials->Credentials = new SoapVar( $cred, SOAP_ENC_OBJECT, 'Credentials' );

$headers = new SoapVar( $Credentials,
                        SOAP_ENC_OBJECT,
                        'CustomSecurityHeaderType',
                        'urn:ebay:apis:eBLBaseComponents' );

$client->__setSoapHeaders( new SoapHeader( 'urn:ebay:api:PayPalAPI',
                                           'RequesterCredentials',
                                           $headers ));

$args = array( 'Version' => '71.0',
               'ReturnAllCurrencies' => '1' );

$GetBalanceRequest = new stdClass();
$GetBalanceRequest->GetBalanceRequest = new SoapVar( $args,
                                                     SOAP_ENC_OBJECT,
                                                     'GetBalanceRequestType',
                                                     'urn:ebay:api:PayPalAPI' );

$params = new SoapVar( $GetBalanceRequest, SOAP_ENC_OBJECT, 'GetBalanceRequest' );

$result = $client->GetBalance( $params );

echo 'Balance is: ', $result->Balance->_, $result->Balance->currencyID;

This produces the following XML request document, which, at the time of writing, was being successfully accepted and processed by PayPal:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:ns1="urn:ebay:apis:eBLBaseComponents" xmlns:ns2="urn:ebay:api:PayPalAPI"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <SOAP-ENV:Header>
  <ns2:RequesterCredentials>
   <ns1:Credentials xsi:type="Credentials">
    <Username>***</Username>
    <Password>***</Password>
    <Signature>***</Signature>
   </ns1:Credentials>
  </ns2:RequesterCredentials>
 </SOAP-ENV:Header>
 <SOAP-ENV:Body>
  <ns2:GetBalanceReq xsi:type="GetBalanceRequest">
   <GetBalanceRequest xsi:type="ns2:GetBalanceRequestType">
    <ns1:Version>71.0</ns1:Version>
    <ns2:ReturnAllCurrencies>1</ns2:ReturnAllCurrencies>
   </GetBalanceRequest>
  </ns2:GetBalanceReq>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

In response to some of the other comments on this page:

  • I'm fairly certain the OP has read the API doc, because that's where the example XML came from that he is trying to reproduce using PHP SOAP library.
  • The PayPal PHP API has some shortcomings, the biggest one being that it fails to work with E_STRICT warnings turned on. It also requires PEAR, so if you are not currently using PEAR in your project it means dragging in quite a lot of new code, which means more complexity and potentially more risk, in order to achieve what should be two or three fairly simple XML exchanges for a basic implementation.
  • The NVP API looks pretty good too, but I'm a glutten for punishment, so I chose the hard path. :-)
JamesG
  • 4,288
  • 2
  • 31
  • 36
  • I ended up doing something like this. NVP may be simple to implement, but it's not as beautiful as SOAP, and thus in the long run tends to get more complicated than SOAP – Jonah Apr 12 '11 at 04:40
  • Could you explain to me the reasoning for using the SoapVar class, the methods seem to work the same if you just pass in straight arrays. – Steven Mar 04 '12 at 14:56
  • According to the notes I left in my code, it was necessary to include type and namespace details in order to add the type info to this element in the request. Presumably if you pass in straight arrays then the type info doesn't get added (?). At the time I posted the original answer, if type information wasn't included the server would get confused and report an "Unknown version" error. Maybe Paypal have changed something on their end to make the server a little less strict in this regard, particularly if this was catching out a lot of developers... – JamesG Mar 04 '12 at 22:38
5

Did you check out the API's provided by PayPal here? And a direct link to the PHP SOAP API download.

And here is a link to the NVP API which PayPal recommends you use.

  • +1 for the NVP. Why would you mess with complex SOAP when you can use simplicity to get the job done without all this headache :) – jamesmortensen Jan 30 '11 at 02:59
  • NVP: "This interface is better for those who prefer more lightweight, script-based development." SOAP: "This interface is better for those who prefer object-oriented development.". OOP always wins in the end. I was able to get SOAP working and I am more than happy with it. – Jonah Apr 12 '11 at 04:42
-1

PHP has a very easy to use soapClass. Which can be found here.

http://www.php.net/manual/en/class.soapclient.php