【问题标题】:Creating a SOAP call using PHP with an XML body使用带有 XML 主体的 PHP 创建 SOAP 调用
【发布时间】:2013-03-08 18:30:08
【问题描述】:

我正在尝试使用 PHP 调用 SOAP 方法。

这是我得到的代码:

$data = array('Acquirer' =>
  array(
    'Id' => 'MyId',
    'UserId' => 'MyUserId',
    'Password' => 'MyPassword'
  ));
$method = 'Echo';
$client = new SoapClient(NULL,
           array('location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler', 
           'uri' => 'http://example.com/wsdl', 'trace' => 1));
$result = $client->$method($data);

这是它创建的请求:

  <?xml version="1.0" encoding="UTF-8"?>
  <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SOAP-ENV:Body>
      <ns1:Echo>
        <param0 xsi:type="ns2:Map">
          <item>
            <key xsi:type="xsd:string">Acquirer</key>
            <value xsi:type="ns2:Map">
              <item>
                <key xsi:type="xsd:string">Id</key>
                <value xsi:type="xsd:string">mcp</value>
              </item>
              <item>
                <key xsi:type="xsd:string">UserId</key>
                <value xsi:type="xsd:string">tst001</value>
              </item>
              <item>
                <key xsi:type="xsd:string">Password</key>
                <value xsi:type="xsd:string">test</value>
              </item>
            </value>
          </item>
        </param0>
      </ns1:Echo>
    </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>

这就是我想要请求的样子:

  <?xml version="1.0" encoding="UTF-8"?>
  <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SOAP-ENV:Body>
      <Echo>
        <Acquirer>
          <Id>MyId</Id>
          <UserId>MyUserId</UserId>
          <Password>MyPassword</Password>
        </Acquirer>
      </Echo>
    </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>

【问题讨论】:

  • 如果没有完整的 WSDL 信息,这个问题就无法解决。 PHP SoapClient 主动解析并使用 WSDL 将函数参数放入正确的位置。如果没有加载 WSDL,几乎不可能创建有效的东西。
  • @Sven - 这很有帮助,尽管它并没有完全解决我的问题。您可以将其发布为答案吗?如果没有其他人回应,我至少会接受,因为它在一定程度上帮助了我前进。
  • 不用了,谢谢,你得到了一个更好的答案,应该得到赏金。
  • @Sven - 好吧,即使它没有直接回答我的问题,您的回答也让我找到了解决方案;)感谢 Sven 和 Matthijs van den Bos 的帮助!

标签: php soap


【解决方案1】:

有几种方法可以解决这个问题。最少的hackiest,几乎是您想要的:

$client = new SoapClient(
    null,
    array(
        'location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler',
        'uri' => 'http://example.com/wsdl',
        'trace' => 1,
        'use' => SOAP_LITERAL,
    )
);
$params = new \SoapVar("<Acquirer><Id>MyId</Id><UserId>MyUserId</UserId><Password>MyPassword</Password></Acquirer>", XSD_ANYXML);
$result = $client->Echo($params);

这将为您提供以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl">
    <SOAP-ENV:Body>
        <ns1:Echo>
            <Acquirer>
                <Id>MyId</Id>
                <UserId>MyUserId</UserId>
                <Password>MyPassword</Password>
            </Acquirer>
        </ns1:Echo>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这几乎正是您想要的,除了方法名称上的命名空间。我不知道这是否有问题。如果是这样,您可以进一步破解它。您可以手动将 &lt;Echo&gt; 标记放入 XML 字符串中,并通过将 'style' =&gt; SOAP_DOCUMENT, 添加到 options 数组中让 SoapClient 不设置方法,如下所示:

$client = new SoapClient(
    null,
    array(
        'location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler',
        'uri' => 'http://example.com/wsdl',
        'trace' => 1,
        'use' => SOAP_LITERAL,
        'style' => SOAP_DOCUMENT,
    )
);
$params = new \SoapVar("<Echo><Acquirer><Id>MyId</Id><UserId>MyUserId</UserId><Password>MyPassword</Password></Acquirer></Echo>", XSD_ANYXML);
$result = $client->MethodNameIsIgnored($params);

这会产生以下请求 XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <Echo>
            <Acquirer>
                <Id>MyId</Id>
                <UserId>MyUserId</UserId>
                <Password>MyPassword</Password>
            </Acquirer>
        </Echo>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

最后,如果您想使用 SoapVar 和 SoapParam 对象,可以在 PHP 手册中的以下注释中找到一个很好的参考:http://www.php.net/manual/en/soapvar.soapvar.php#104065。如果你让它工作,请告诉我,我失败得很惨。

【讨论】:

    【解决方案2】:

    首先,您必须指定您希望使用 Document Literal 样式:

    $client = new SoapClient(NULL, array(
        'location' => 'https://example.com/path/to/service',
        'uri' => 'http://example.com/wsdl',
        'trace' => 1,
        'use' => SOAP_LITERAL)
    );
    

    然后,您需要将数据转换为 SoapVar;我写了一个简单的变换函数:

    function soapify(array $data)
    {
            foreach ($data as &$value) {
                    if (is_array($value)) {
                            $value = soapify($value);
                    }
            }
    
            return new SoapVar($data, SOAP_ENC_OBJECT);
    }
    

    然后,您将此转换函数应用于您的数据:

    $data = soapify(array(
        'Acquirer' => array(
            'Id' => 'MyId',
            'UserId' => 'MyUserId',
            'Password' => 'MyPassword',
        ),
    ));
    

    最后,调用传递 Data 参数的服务:

    $method = 'Echo';
    
    $result = $client->$method(new SoapParam($data, 'Data'));
    

    【讨论】:

    • 这实际上是stackoverlow上第一篇提到“Data”参数的帖子
    猜你喜欢
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    相关资源
    最近更新 更多