SOAP客户端复杂类型PHP请求

6

我有一个与以下链接相关的Web服务:link 我正在尝试使用SubmitRequestType访问函数名称,但似乎该函数不存在,而是submitAnsiSingle,这是正确的函数名称。到目前为止,我尝试过的是:

$wsdl = 'https://ww3.navicure.com:7000/webservices/NavicureSubmissionService?WSDL';

class SecurityHeaderType {
        private $submitterIdentifier;
        private $originatingIdentifier;
        private $submitterPassword;
        private $submissionId;
        function SecurityHeaderType() {
            $this->submitterIdentifier = '***';
            $this->originatingIdentifier = '****';
            $this->submitterPassword = '****';
            $this->submissionId = '';

        }           
}

class SubmitRequestType {

        private $submitterIdentifier;
        private $originatingIdentifier;
        private $submitterPassword;
        private $submissionId;
        private $timeout;
        private $transactionType;
        private $submittedAnsiVersion;
        private $resultAnsiVersion;
        private $submitterSubmissionId;
        private $processingOption;
        private $payload;
        private $exceptions;

        function SubmitRequestType() {

        $this->submitterIdentifier = '***';
        $this->originatingIdentifier = '***';
        $this->submitterPassword = '**';
        $this->submissionId = '**';
        $this->timeout = 60 ;
        $this->transactionType = "E";
        $this->submittedAnsiVersion = '5010';
        $this->resultAnsiVersion = '5010';
        $this->submitterSubmissionId = '**';
        $this->processingOption = 'R';
        $this->payload = 'EDI-270-Request';
        $this->exceptions = true;
        }
}

$soapheader = new SecurityHeaderType();


$submitrequest = new SubmitRequestType();



    $service = new \SoapClient($wsdl);
    $result= $service->SubmitAnsiSingle($submitrequest);
    echo "<pre/>";print_r($result);

    $types = $service->__getTypes ();
    $functions = $service->__getFunctions ();
    //echo "<pre/>";print_r($types);
    //echo "<pre/>";print_r($functions);

但是我收到的响应如下,似乎请求正在他们那边处理,但是SecurityHeaderType在他们那边没有解析。
stdClass Object
(
    [transactionTyp] => E
    [submitterSubmissionId] => ****
    [submittedAnsiVersion] => 5010
    [resultAnsiVersion] => 5010
    [statusHeader] => stdClass Object
        (
            [statusCode] => 1150
            [statusMessage] => com.navicure.webservices.core.WSCoreException: Account does not exist for ''
            [requestProcessed] => 
        )

)

任何提示都将不胜感激。
提前致谢。

我看到你创建了$soapheader,但没有使用它。 - Scuzzy
@Scuzzy 是的,但是我已经在 $submitrequest 中添加了这些参数,因为我没有找到一种同时调用安全头和请求的方法。当我打印函数 submitAnsiSingle(SubmitRequestType $parameters) 时。 - Jobin
$client->__setSoapHeaders($header); http://php.net/manual/zh/class.soapheader.php - Scuzzy
我也尝试过,但不确定这是否正确的方法:$header = new \SoapHeader('NAMESPACE','Auth',$soapheader,false); $service->__setSoapHeaders($header); 还有一个NAMESPACE的问题。 - Jobin
尝试了这个,但没有成功:$header = new \SoapHeader('http://www.navicure.com/2009/11/NavicureSubmissionService','SecurityHeaderType',$soapheader,false); - Jobin
2个回答

4
我找到了解决方案!这似乎是PHP -> .NET Web服务兼容性问题。因此,从PHP中,复杂类型SOAP(这种格式)无法访问。我在这里找到了一些有用的帖子。所以我将SOAP切换为使用CURL的普通XML请求,并且似乎工作正常!此外,我们可以使用在线服务从WSDL链接中提取请求模板。因此,我的最终代码如下所示。
$xml_data = "<?xml version='1.0' encoding='UTF-8'?>
<s12:Envelope xmlns:s12='http://www.w3.org/2003/05/soap-envelope'>
  <s12:Header>
    <ns1:SecurityHeaderElement xmlns:ns1='http://www.navicure.com/2009/11/NavicureSubmissionService'>
      <ns1:originatingIdentifier>****</ns1:originatingIdentifier>
      <ns1:submitterIdentifier>****</ns1:submitterIdentifier>
      <ns1:submitterPassword>***</ns1:submitterPassword>
      <ns1:submissionId>?999?</ns1:submissionId>
    </ns1:SecurityHeaderElement>
  </s12:Header>
  <s12:Body>
    <ns1:SubmitAnsiSingleRequestElement xmlns:ns1='http://www.navicure.com/2009/11/NavicureSubmissionService'>
      <ns1:timeout>60</ns1:timeout>
      <ns1:transactionType>E</ns1:transactionType>
      <ns1:submittedAnsiVersion>5010</ns1:submittedAnsiVersion>
      <ns1:resultAnsiVersion>5010</ns1:resultAnsiVersion>
      <ns1:submitterSubmissionId></ns1:submitterSubmissionId>
      <ns1:processingOption>R</ns1:processingOption>
      <ns1:payload>EDI270Payload</ns1:payload>
    </ns1:SubmitAnsiSingleRequestElement>
  </s12:Body>
</s12:Envelope>";
$URL = "https://ww3.navicure.com:7000/webservices/NavicureSubmissionService";

$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch); 

print_r($output);

希望这能帮助其他人在未来解决问题。

1
你可能会遇到PHP的WSDL2实现不太兼容的问题。你可以尝试以下方法,但需要祈祷好运;
Headerbody需要按照XML中定义的深度实施,因为我在这里没有访问navicure的文档,这是示例代码:
$headerbody = array('Token' => $someToken, 
                    'Version' => $someVersion, 
                    'UserCredentials'=>array('UserID'=>$UserID, 
                                             'Password'=>$Pwd)); 

//Create Soap Header.        
$header = new SOAPHeader($namespace, 'RequestorCredentials', $headerbody);  

// 如果需要多个标题,请创建 $headers[] = $header,并在之后附加到 headers。

$options = array(
        'uri'=>'http://schemas.xmlsoap.org/soap/envelope/',
        'style'=>SOAP_RPC,
        'use'=>SOAP_ENCODED,
        'soap_version'=>SOAP_1_1,
        'cache_wsdl'=>WSDL_CACHE_NONE,
        'connection_timeout'=>15,
        'trace'=>true,
        'encoding'=>'UTF-8',
        'exceptions'=>true,
    );
try {
    $soap = new SoapClient($wsdl, $options);
    $soap->__setSoapHeaders($header);
    $data = $soap->SubmitAnsiSingle(array($submitrequest));
}
catch(Exception $e) {
    die($e->getMessage());
}

希望这对您有所帮助 - 如果实际使用WSDL2,则可以尝试使用nusoap,它可以在sourceforge上找到。虽然它已经很长时间没有更新了。


感谢您的回答,我之前尝试过类似这样的代码:$header = new \SoapHeader($namespace,'SecurityHeaderType',$soapheader,false);$service->__setSoapHeaders($header); 但仍然没有成功。发现一个疯狂的事实是从.NET平台可以正常工作,即使SubmitAnsiSingle()方法在.NET中有两个对象参数,分别是header和request type。深入搜索后发现一些.NET SOAP无法简单地从PHP访问,可能需要使用XML调用。 - Jobin
nusoap我检查过了,它也存在一些版本兼容性问题,我正在使用PHP7.0,因此我认为https://dev59.com/fHRB5IYBdhLWcg3w6LV3 Ivan Krechetov的建议很有道理,打算使用CURL代替他的方法。 - Jobin
正如所提到的,PHP在处理基于WSDL的API时存在一些问题,而且由于REST变得越来越流行,我怀疑PHP将永远不会解决这些问题。如果您不断遇到问题,一个稍微有点糟糕的解决方案是使用C#创建一个REST API,将您的PHP请求中继到WSDL服务。这可以解决很多麻烦 :) - DevionNL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接