首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对navision webservice的PHP SOAP请求

对navision webservice的PHP SOAP请求
EN

Stack Overflow用户
提问于 2015-06-19 10:16:55
回答 1查看 4.5K关注 0票数 2

几天来,我一直在努力通过NTLM身份验证在PHP webshop和navision服务器之间建立连接。现在连接和身份验证已经完成,我在执行正确的请求时遇到了问题。

在这个例子中,我尝试使用一个函数(ItemPriceDiscInventory)来检索价格信息。

我从客户那里得到的网址是:http://IP:PORT/MSIteminfoTest/WS/Saniceve%20BV/Codeunit/ItemPriceDiscInventory

我尝试了两种方法来提出请求:

使用原始XML发布的

原始XML是由客户提供的。这是测试程序(SOACleaner)在输入(本地) WSDL文件时给我的相同的XML。

代码语言:javascript
复制
$request = '
<InputItemPriceDiscInventory_PortGetPriceDiscInvInformation xmlns="http://xyrow.com">
<Body xmlns="">
<GetPriceDiscInvInformation xmlns="urn:microsoft-dynamics-schemas/codeunit/ItemPriceDiscInventory">
  <itemPriceDiscInventory>
    <Item xmlns="urn:microsoft-dynamics-nav/xmlports/x50005">
      <Klantnummer />
      <Artikelnr />
      <Aantal />
      <KortingsPercentage1 />
      <KortingsPercentage2 />
      <NettoPerEenheid />
      <BeschikbareVoorraad />
      <WebShopVoorraad />
    </Item>
  </itemPriceDiscInventory>
  <customerNo>1234</customerNo>
  <itemNo>5678</itemNo>
  <quantityVarDec>1</quantityVarDec>
</GetPriceDiscInvInformation>
</Body>
</InputItemPriceDiscInventory_PortGetPriceDiscInvInformation>';

我的请求:

代码语言:javascript
复制
$ch = curl_init(); 
$headers = array( 
      'Method: POST', 
        'Connection: Keep-Alive',       
        'Content-Type: text/xml; charset=utf-8',             
        "Host: {$ip}:{$port}",
        "Accept: */*"                       
    );      
curl_setopt($ch, CURLOPT_URL,            $url );        
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt($ch, CURLOPT_POST,           true );        
curl_setopt($ch, CURLOPT_POSTFIELDS,    $request); 
curl_setopt($ch, CURLOPT_USERPWD, 'usr:pass');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM );
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);          
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);     
curl_setopt($ch, CURLOPT_FAILONERROR, 0);

这将返回WSDL文件,无论我包含什么POST值。如果我包含头'SOAPAction: "ItemPriceDiscInventory"',它会给出错误:

代码语言:javascript
复制
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode xmlns:a="urn:microsoft-dynamics-schemas/error">a:System.Net.WebException</faultcode><faultstring xml:lang="nl-NL">Soap message is invalid!</faultstring><detail><string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Soap message is invalid!</string></detail></s:Fault></s:Body></s:Envelope> 

WSDL看起来像:

代码语言:javascript
复制
<definitions targetNamespace="urn:microsoft-dynamics-schemas/codeunit/ItemPriceDiscInventory" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="urn:microsoft-dynamics-schemas/codeunit/ItemPriceDiscInventory">
<types>
    <schema elementFormDefault="qualified" targetNamespace="urn:microsoft-dynamics-nav/xmlports/x50005" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="urn:microsoft-dynamics-nav/xmlports/x50005">
        <complexType name="Item">
            <sequence>
                <element minOccurs="1" maxOccurs="1" name="Klantnummer" type="string"/>
                <element minOccurs="1" maxOccurs="1" name="Artikelnr" type="string"/>
                <element minOccurs="1" maxOccurs="1" name="Aantal" type="string"/>
                <element minOccurs="1" maxOccurs="1" name="KortingsPercentage1" type="string"/>
                <element minOccurs="1" maxOccurs="1" name="KortingsPercentage2" type="string"/>
                <element minOccurs="1" maxOccurs="1" name="NettoPerEenheid" type="string"/>
                <element minOccurs="1" maxOccurs="1" name="BeschikbareVoorraad" type="string"/>
                <element minOccurs="1" maxOccurs="1" name="WebShopVoorraad" type="string"/>
            </sequence>
        </complexType>
        <complexType name="ItemPriceDiscInvInfo" mixed="true">
            <sequence>
                <element minOccurs="1" maxOccurs="1" name="Item" type="tns:Item"/>
            </sequence>
        </complexType>
        <element name="ItemPriceDiscInvInfo" type="tns:ItemPriceDiscInvInfo"/>
    </schema>
    <schema elementFormDefault="qualified" targetNamespace="urn:microsoft-dynamics-schemas/codeunit/ItemPriceDiscInventory" xmlns="http://www.w3.org/2001/XMLSchema">
        <element name="GetPriceDiscInvInformation">
            <complexType>
                <sequence>
                    <element minOccurs="1" maxOccurs="1" name="itemPriceDiscInventory" type="q1:ItemPriceDiscInvInfo" xmlns:q1="urn:microsoft-dynamics-nav/xmlports/x50005"/>
                    <element minOccurs="1" maxOccurs="1" name="customerNo" type="string"/>
                    <element minOccurs="1" maxOccurs="1" name="itemNo" type="string"/>
                    <element minOccurs="1" maxOccurs="1" name="quantityVarDec" type="decimal"/>
                </sequence>
            </complexType>
        </element>
        <element name="GetPriceDiscInvInformation_Result">
            <complexType>
                <sequence>
                    <element minOccurs="1" maxOccurs="1" name="itemPriceDiscInventory" type="q2:ItemPriceDiscInvInfo" xmlns:q2="urn:microsoft-dynamics-nav/xmlports/x50005"/>
                </sequence>
            </complexType>
        </element>
    </schema>
</types>
<message name="GetPriceDiscInvInformation">
    <part name="parameters" element="tns:GetPriceDiscInvInformation"/>
</message>
<message name="GetPriceDiscInvInformation_Result">
    <part name="parameters" element="tns:GetPriceDiscInvInformation_Result"/>
</message>
<portType name="ItemPriceDiscInventory_Port">
    <operation name="GetPriceDiscInvInformation">
        <input name="GetPriceDiscInvInformation" message="tns:GetPriceDiscInvInformation"/>
        <output name="GetPriceDiscInvInformation_Result" message="tns:GetPriceDiscInvInformation_Result"/>
    </operation>
</portType>
<binding name="ItemPriceDiscInventory_Binding" type="tns:ItemPriceDiscInventory_Port">
    <binding transport="http://schemas.xmlsoap.org/soap/http" xmlns="http://schemas.xmlsoap.org/wsdl/soap/"/>
    <operation name="GetPriceDiscInvInformation">
        <operation soapAction="urn:microsoft-dynamics-schemas/codeunit/ItemPriceDiscInventory:GetPriceDiscInvInformation" style="document" xmlns="http://schemas.xmlsoap.org/wsdl/soap/"/>
        <input name="GetPriceDiscInvInformation">
            <body use="literal" xmlns="http://schemas.xmlsoap.org/wsdl/soap/"/>
        </input>
        <output name="GetPriceDiscInvInformation_Result">
            <body use="literal" xmlns="http://schemas.xmlsoap.org/wsdl/soap/"/>
        </output>
    </operation>
</binding>
<service name="ItemPriceDiscInventory">
    <port name="ItemPriceDiscInventory_Port" binding="tns:ItemPriceDiscInventory_Binding">
        <address location="http://IP:PORT/MSIteminfoTest/WS/Saniceve%20BV/Codeunit/ItemPriceDiscInventory" xmlns="http://schemas.xmlsoap.org/wsdl/soap/"/>
    </port>
</service>
</definitions>

SoapClient请求

好的,我想,试试PHP的SOAP功能。我使用了一个NTLMSoapClient类进行身份验证,这似乎还可以。如果我在WSDL模式下构造客户机,并且提供了上面的URL,它就不能解析WSDL:

代码语言:javascript
复制
[WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'URL' : Start tag expected, '<' 

但是如果我在非WSDL模式下这样做,并给出参数中的位置,我就会得到一些结果.

代码语言:javascript
复制
    stream_wrapper_unregister('http'); 
stream_wrapper_register('http', 'MyServiceProviderNTLMStream') or die("Failed to register protocol");

$client = new MyServiceNTLMSoapClient(null,array(   'location' => $url,
                                                    'uri'      => "http://schemas.xmlsoap.org/wsdl/soap/",
                                                    'trace'    => 1));  

$itemPriceDiscInventory = array(
                "Item" => array(
                    "Klantnummer" => null,
                    "Artikelnr" => null,
                    "Aantal" => null,
                    "KortingsPercentage" => null,
                    "NettoPerEenheid" => null,
                    "Voorraad" => null
                )
            );

$params = array(
            "itemPriceDiscInventory" => $itemPriceDiscInventory,
            "customerNo" => '0000265',
            "itemNo" => 'SAN483539',
            "quantityVarDec" => '1.0'
);


echo $client->GetPriceDiscInvInformation($params);  

stream_wrapper_restore('http');

这将导致一个错误。如果我得到最后的请求和回应,它会给我:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
    <ns1:GetPriceDiscInvInformation>
        <param0 xsi:type="ns2:Map">
            <item>
                <key xsi:type="xsd:string">itemPriceDiscInventory</key>
                <value xsi:type="ns2:Map">
                    <item>
                        <key xsi:type="xsd:string">Item</key>
                        <value xsi:type="ns2:Map">
                            <item>
                                <key xsi:type="xsd:string">Klantnummer</key>
                                <value xsi:nil="true"/>
                            </item>
                            <item>
                                <key xsi:type="xsd:string">Artikelnr</key>
                                <value xsi:nil="true"/>
                            </item>
                            <item>
                                <key xsi:type="xsd:string">Aantal</key>
                                <value xsi:nil="true"/>
                            </item>
                            <item>
                                <key xsi:type="xsd:string">KortingsPercentage</key>
                                <value xsi:nil="true"/>
                            </item>
                            <item>
                                <key xsi:type="xsd:string">NettoPerEenheid</key>
                                <value xsi:nil="true"/>
                            </item>
                            <item>
                                <key xsi:type="xsd:string">Voorraad</key>
                                <value xsi:nil="true"/>
                            </item>
                        </value>
                    </item>
                </value>
            </item>
            <item>
                <key xsi:type="xsd:string">customerNo</key>
                <value xsi:type="xsd:string">0000265</value>
            </item>
            <item>
                <key xsi:type="xsd:string">itemNo</key>
                <value xsi:type="xsd:string">SAN483539</value>
            </item>
            <item>
                <key xsi:type="xsd:string">quantityVarDec</key>
                <value xsi:type="xsd:string">1.0</value>
            </item>
        </param0>
    </ns1:GetPriceDiscInvInformation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

响应:

代码语言:javascript
复制
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
    <s:Fault>
        <faultcode xmlns:a="urn:microsoft-dynamics-schemas/error">a:Microsoft.Dynamics.Nav.Service.WebServices.ServiceBrokerException</faultcode>
        <faultstring xml:lang="nl-NL">Parameter itemPriceDiscInventory in method GetPriceDiscInvInformation in service ItemPriceDiscInventory is null!</faultstring>
        <detail>
            <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Parameter itemPriceDiscInventory in method GetPriceDiscInvInformation in service ItemPriceDiscInventory is null!</string>
        </detail>
    </s:Fault>
</s:Body>

因此,他似乎试图解析它,但请求的格式不正确。注意:我不知道uri参数必须是什么。这是我可以从WSDL中读到的东西吗?

如果我看一下客户给我的请求和SOAP请求,它会有很大的不同(第一个看起来根本不像SOAP ),但是对于SOAP请求,我似乎离得更近了。

对此有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-22 07:32:09

我终于想出来了。首先,我认为我的请求中的命名空间有问题。

我将WSDL文件保存在自己的服务器上,并将其用于WSDL模式下的soapclient,并以navision服务器为位置。这起作用了!

我不知道为什么不能在WSDL模式中使用直接URL,但这是一个可以接受的解决办法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30935645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档