php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #31727 SOAPClient incorrectly encoding parameters
Submitted: 2005-01-27 19:55 UTC Modified: 2005-01-31 19:00 UTC
From: adam at trachtenberg dot com Assigned: dmitry (profile)
Status: Not a bug Package: SOAP related
PHP Version: 5CVS-2005-01-27 (dev) OS: n/a
Private report: No CVE-ID: None
 [2005-01-27 19:55 UTC] adam at trachtenberg dot com
Description:
------------
The SOAPClient class is incorrectly encoding parameters. It is not placing them inside their own named elements.

I believe this to be a bug, but it's quite hard to confirm because the SOAP spec is so theoretical. I can't find any real examples. Also, even after this bug is fixed, the "working" code won't make a successful request, as the WSDL endpoint is wrong and there are no headers. This is just a stripped down version to reproduce the bug.

Reproduce code:
---------------
$wsdl_url = 'http://developer.ebay.com/webservices/393/eBaySvc.wsdl';

$client = new SOAPClient($wsdl_url, array('trace' => 1, 'exceptions' => 0, )); 

$DetailLevel = new SOAPParam(new SOAPVar('ReturnAll', XSD_STRING,  NULL, NULL, NULL, 'urn:ebay:apis:eBLBaseCo\
mponents'), 'DetailLevel');
$Version     = new SOAPParam(new SOAPVar(393,         XSD_DOUBLE, NULL, NULL, NULL, 'urn:ebay:apis:eBLBaseCom\
ponents'), 'Version');

$user = $client->GetUser($Version, $DetailLevel);
print "GetUser(): \n".$client->__getLastRequest() ."\n";

$user = $client->__call('GetUser', array($Version, $DetailLevel));
print "__call(GetUser): \n".$client->__getLastRequest() ."\n";

Expected result:
----------------
GetUser(): 
<?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"><SOAP-ENV:Body><ns1:GetUserRequest><ns1:Version>393</ns1:Version><ns1:DetailLevel>ReturnAll</ns1:DetailLevel></ns1:GetUserRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>

__call(GetUser): 
<?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"><SOAP-ENV:Body><ns1:GetUserRequest><ns1:Version>393</ns1:Version><ns1:DetailLevel>ReturnAll</ns1:DetailLevel></ns1:GetUserRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>

Actual result:
--------------
GetUser(): 
<?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"><SOAP-ENV:Body><ns1:GetUserRequest>393</ns1:GetUserRequest><ns1:DetailLevel>ReturnAll</ns1:DetailLevel></SOAP-ENV:Body></SOAP-ENV:Envelope>

__call(GetUser): 
<?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"><SOAP-ENV:Body><ns1:GetUserRequest>393</ns1:GetUserRequest><ns1:DetailLevel>ReturnAll</ns1:DetailLevel></SOAP-ENV:Body></SOAP-ENV:Envelope>

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-01-28 11:38 UTC] dmitry@php.net
ext/soap is more simple in use then you think, but it requre some understanding of SOAP encoding.

The following code should work fine.

<?php

$wsdl_url = 'http://developer.ebay.com/webservices/393/eBaySvc.wsdl';

$client = new SOAPClient($wsdl_url, 
                         array('trace' => 1, 'exceptions' => 0)); 

$user = $client->GetUser(array('Version'=>393, 
                               'DetailLevel'=>'ReturnAll', 
                               'UserID'=>'?'));
print "GetUser(): \n".$client->__getLastRequest() ."\n";
print "GetUser(): \n".$client->__getLastResponse() ."\n";

?>


 [2005-01-28 18:29 UTC] adam at trachtenberg dot com
Unfortunately, eBay's SOAP is more complex than this. I actually need to send SOAP headers, so I cannot use the simplified call format. Here what I actually need to do:

$token = 'TTT';
$devId = 'DDD';
$appId = 'AAA';
$certId = 'CCC';

$wsdl_url = 'http://developer.ebay.com/webservices/393/eBaySvc.wsdl';
$client = new SOAPClient($wsdl_url, array('trace' => 1, 'exceptions'
=> 0, ));

class eBayAuth {
        function __construct($token, $dev, $app, $cert) {
                $credentials = new eBayCredentials($dev, $app, $cert);
                $this->eBayAuthToken = new SoapVar($token, XSD_STRING, NULL, NULL, NULL, 'urn:ebay:apis:eBLBaseComponents');
                $this->Credentials = new SoapVar($credentials, SOAP_ENC_OBJECT, NULL, NULL, NULL, 'urn:ebay:apis:eBLBaseComponents');
        }
}

class eBayCredentials {
        function __construct($dev, $app, $cert) {
                $this->AppId   = $app;
                $this->DevID   = $dev;
                $this->AuthCert  = $cert;
        }
}

$eBayAuth = new eBayAuth($token, $devId, $appId, $certId);
$header_body = new SoapVar($eBayAuth, SOAP_ENC_OBJECT);

$header = array(new SOAPHeader('urn:ebay:api:eBLBaseComponents', 'RequesterCredentials', $header_body));

$params = array('Version' => 393, 'DetailLevel' => 'ReturnAll');

$user = $client->__call('GetUser', $params, NULL, $header);

This generates:

<?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:eBLBaseComponents"><SOAP-ENV:Header><ns2:RequesterCredentials><ns1:eBayAuthToken>TTT</ns1:eBayAuthToken><ns1:Credentials><AppId>AAA</AppId><DevID>DDD</DevID><AuthCert>CCC</AuthCert></ns1:Credentials></ns2:RequesterCredentials></SOAP-ENV:Header><SOAP-ENV:Body><ns1:GetUserRequest/><param1>ReturnAll</param1></SOAP-ENV:Body></SOAP-ENV:Envelope>

As you can see, now the parameters are totally incorrect. One is missing. The other is called "param1".

My header construction may be overly complex; however, our SOAP service recently switched from 3 namespaces to 1 namespace. When there were 3 namespaces, I found I needed to manually set the values because otherwise they would not be inside the correct namespace. (Actually, looking at this, I may still need to place additional fields inside the namespace.)

This problem would go away if ext/soap supported the instantiation of the complexTypes defined in the WSDL, the ability to set their values, and then pass those objects into the SOAPClient, but I realize that's a non-trivial job.
 [2005-01-31 09:01 UTC] dmitry@php.net
As I understand this Web Service uses document encoding and the 'GetUser' method uses one argument of complexType.
So you should call it in the following way.

$params = array('Version' => 393, 'DetailLevel' => 'ReturnAll');

$user = $client->__soapCall('GetUser', array($params), NULL, $header);

 [2005-01-31 19:00 UTC] amt@php.net
Yup. That seems to work. Sorry for the noise.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 14:01:32 2024 UTC