简体   繁体   English

SOAP调用在SoapUI中工作但在PHP中使用soapclient失败 - 对象引用问题

[英]SOAP call works in SoapUI but fails in PHP using soapclient - Object reference issue

Trying to query a .NET webservice hosted on an IIS server using PHP 5.x 尝试使用PHP 5.x查询IIS服务器上托管的.NET Web服务

$wsdl_path = "http://192.168.1.1/TestSite/TestService.asmx?wsdl";
$soapClient = new SoapClient($wsdl_path, array('trace' => 1));
$dump=var_export($soapClient->__getFunctions(), true);
echo htmlentities($dump);

produces 产生

array (
  0 => 'ProcessTransactionResponse ProcessTransaction(ProcessTransaction $parameters)',
  1 => 'ProcessTransactionResponse ProcessTransaction(ProcessTransaction $parameters)',
)

which would indicate it is correctly accessing the wsdl file. 这表明它正在正确访问wsdl文件。

A correctly formatted query validated using SoapUI is as follows 使用SoapUI验证的格式正确的查询如下

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.mydomain.tld/">
   <soapenv:Header/>
   <soapenv:Body>
      <ws:ProcessTransaction>
        <!--Optional:-->
         <ws:request>
            <!--Optional:-->
            <ws:Header>
               <!--Optional:-->
               <ws:Token>hello</ws:Token>
            </ws:Header>
            <!--Optional:-->
            <ws:Parameters>
               <ws:DeviceID>12345</ws:DeviceID>
               <ws:SourceScreen>12345</ws:SourceScreen>
               <!--Optional:-->
               <ws:Language>E</ws:Language>
               <ws:LocalDateTime>2015-05-20T11:59:29.910Z</ws:LocalDateTime>
               <ws:TicketID>12345</ws:TicketID>
               <ws:PayScreenAttributeID>12345</ws:PayScreenAttributeID>
               <!--Optional:-->
               <ws:InputValue>1234556789</ws:InputValue>
               <ws:PaymentAmount>0</ws:PaymentAmount>
               <!--Optional:-->
               <ws:POSReceiptCustomer>?</ws:POSReceiptCustomer>
               <!--Optional:-->
               <ws:POSReceiptMerchant>?</ws:POSReceiptMerchant>
            </ws:Parameters>
         </ws:request>
      </ws:ProcessTransaction>
   </soapenv:Body>
</soapenv:Envelope>

So to replicate this with PHP and SoapClient I collect the data elements in an array 因此,要使用PHP和SoapClient复制它,我会收集数组中的数据元素

$inputParams=array(
    'Token' => 'hello',
    'DeviceID' => 12345,
    'SourceScreen' => 12345,
    'Language' => 'E',
    'LocalDateTime' => '2015-05-20T11:59:29.910Z',  
    'TicketID' => 12345,
    'PayScreenAttributeID' => 12345,
    'InputValue' => '123456789',
    'PaymentAmount' => 0,
    'POSReceiptCustomer' => '?',
    'POSReceiptMerchant' => '?',
);

and perform the query 并执行查询

try {
    $response = $soapClient->__soapCall('ProcessTransaction', array('parameters' => $inputParams));
    var_dump($response);
} catch (SoapFault $fault) {
    var_dump($fault);
    echo "SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})";
    echo "REQUEST:\n" . htmlentities($soapClient->__getLastRequest()) . "\n";
}

I get the dreaded Server was unable to process request. ---> Object reference not set to an instance of an object. 我得到了可怕的Server was unable to process request. ---> Object reference not set to an instance of an object. Server was unable to process request. ---> Object reference not set to an instance of an object. which isn't very useful. 这不是很有用。

When I look at the __getLastRequest() output, it appears to show the wrapper but none of the query elements 当我查看__getLastRequest()输出时,它似乎显示包装器但没有查询元素

REQUEST:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://ws.mydomain.tld/"><SOAP-ENV:Body><ns1:ProcessTransaction/></SOAP-ENV:Body></SOAP-ENV:Envelope>

I have tried both with and without the Token element to no avail, as well as initially leaving out optional fields (which work fine in the SoapUI interface) but no joy there either. 我已经尝试过使用和不使用Token元素都无济于事,以及最初省略了可选字段(在SoapUI接口中工作正常),但也没有任何乐趣。

I suspect that it is related to the additional header container with the Token element as our other soap implementations have not included this element. 我怀疑它与带有Token元素的附加头容器有关,因为我们的其他soap实现没有包含这个元素。

You're probably right about the header being the cause, or at least part of it. 你可能是正确的标题是正确的,或者至少是它的一部分。 I am not currently within easy reach of a soap server, but I hope the below can at least give some pointers. 我目前不是肥皂服务器的容易接触,但我希望下面至少可以给出一些指示。

There are two possibilities here: either the header should be included as a SoapHeader object, or you need to build your parameters array differently. 这里有两种可能:标题应作为SoapHeader对象包含,或者您需要以不同方式构建参数数组。 I'll list both versions. 我将列出两个版本。

Either way, you can probably skip the __soapCall() method and use the magic method instead, since you appear to be using wsdl. 无论哪种方式,您都可以跳过__soapCall()方法并使用魔术方法,因为您似乎正在使用wsdl。

Parameters version (try this first) 参数版本(先试试)

If you're lucky, you just need to reformat the body in order to suit the given schema. 如果你很幸运,你只需要重新格式化身体以适应给定的模式。 It honestly kinda looks like that. 老实说它看起来像那样。 Something like this: 像这样的东西:

$params = array(
    'request' => array(
        'Header' => array(
            'Token' => 'hello'
        ),
        'Parameters' => array(
            'DeviceID' => 12345,
            'SourceScreen' => 12345,
            'Language' => 'E',
            'LocalDateTime' => '2015-05-20T11:59:29.910Z',  
            'TicketID' => 12345,
            'PayScreenAttributeID' => 12345,
            'InputValue' => '123456789',
            'PaymentAmount' => 0,
            'POSReceiptCustomer' => '?',
            'POSReceiptMerchant' => '?'
        )
    )
);

$wsdl_path = "http://192.168.1.1/TestSite/TestService.asmx?wsdl";
$soapClient = new SoapClient($wsdl_path, array('trace' => 1));
$response = $soapClient->ProcessTransaction($params);

SoapHeader version SoapHeader版本

What you need to do if you actually do need a proper header is to create an header object and attach it to the client you've instantiated. 如果您确实需要合适的标头,则需要做的是创建一个标头对象并将其附加到您已实例化的客户端。 Then, you can call the endpoint. 然后,您可以调用端点。

In order to do so you need to know the namespace, which should be called targetNameSpace in your schema. 为此,您需要知道命名空间,该命名空间应该在模式中称为targetNameSpace You'll also need to know the name, which you can see in eg SoapUI. 您还需要知道名称,您可以在SoapUI中看到。

Finally, it should be enough to just supply the parameters straight away - no need to put them in a single-element array. 最后,它应该足以直接提供参数 - 无需将它们放在单元素阵列中。 So you end up with something like the below. 所以你最终会得到类似下面的东西。 With any luck, that may at least put you in the right direction. 运气好的话,至少可以让你朝着正确的方向前进。 :) :)

// instantiate soap client
$wsdl_path = "http://192.168.1.1/TestSite/TestService.asmx?wsdl";
$soapClient = new SoapClient($wsdl_path, array('trace' => 1));

// create and attach a header
$header = new SoapHeader($namespace, $name, array('Token' => 'hello'));
$soapClient->__setSoapHeaders($header);

// call the endpoint
$response = $soapClient->ProcessTransaction($inputParams);
var_dump($response); // hopefully you get something back...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM