处理SOAP响应

5
我正在尝试处理来自First Data全球网关的SOAP响应。我以前使用过SoapClient,但是没有wsdl文件 - 公司表示他们不提供。我尝试了各种其他方法,例如基于此处和PHP手册中找到的示例的SimpleXMLElement,但我无法使任何内容正常工作。我怀疑命名空间是我的问题之一。是否有人可以建议一种方法或将我指向类似的示例 - 我的Google搜索至今无果。使用PHP 5。部分SOAP响应(去除所有HTML头信息)如下:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">

<SOAP-ENV:Header/>

<SOAP-ENV:Body>

<fdggwsapi:FDGGWSApiOrderResponse xmlns:fdggwsapi="http://secure.linkpt.net/fdggwsapi/schemas_us/fdggwsapi">

<fdggwsapi:CommercialServiceProvider/>

<fdggwsapi:TransactionTime>Thu Nov 29 17:03:18 2012</fdggwsapi:TransactionTime>

<fdggwsapi:TransactionID/>

<fdggwsapi:ProcessorReferenceNumber/>

<fdggwsapi:ProcessorResponseMessage/>

<fdggwsapi:ErrorMessage>SGS-005005: Duplicate transaction.</fdggwsapi:ErrorMessage>

<fdggwsapi:OrderId>A-e833606a-5197-45d6-b990-81e52df41274</fdggwsapi:OrderId>
...

<snip>

我需要确定是否有SOAP故障发生。相应的XML如下所示:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<SOAP-ENV:FaultX>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring xml:lang="en">MerchantException</faultstring>
<detail>
cvc-pattern-valid: Value '9999185.00' is not facet-valid with respect to pattern '([1-9]([0-9]{0,3}))?[0-9](\.[0-9]{1,2})?' for type '#AnonType_ChargeTotalAmount'.
cvc-type.3.1.3: The value '9999185.00' of element 'v1:ChargeTotal' is not valid.
</detail>
</SOAP-ENV:FaultX>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

使用Mr. Code的答案,我已经能够从非错误响应中检索数据。但是我需要确定我正在处理的数据包类型,并从两种类型中提取数据。如果他们提供了wsdl,那将会更容易!

1个回答

6

您可以使用SimpleXML解析响应,以下是一个示例。请注意,我将命名空间URL传递给children()以访问元素。

$obj = simplexml_load_string($xml);

$response = $obj->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('http://secure.linkpt.net/fdggwsapi/schemas_us/fdggwsapi')->FDGGWSApiOrderResponse;

echo $response->TransactionTime . "\n";
echo $response->ErrorMessage;

输出

2012年11月29日星期四17:03:18
SGS-005005:重复交易。

Codepad演示

编辑:SoapFault响应可以像下面这样解析。它输出故障字符串和详细信息,或“未发现故障”:

if($obj->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('http://schemas.xmlsoap.org/soap/envelope/') && isset($obj->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('http://schemas.xmlsoap.org/soap/envelope/')->children()->faultcode))
{
    $fault = $obj->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('http://schemas.xmlsoap.org/soap/envelope/')->children();

    // soap fault
    echo $fault->faultstring;
    echo $fault->detail;
}
else
{
    echo 'No fault found, do normal parsing...';
}

谢谢 - 这正是我所需要的 - 我之前没有看到过同时引用两个命名空间的示例。 - JonP
如果我得到一个有效的响应,这个例子运行得非常好,但是当出现SOAP故障时,我发现了一个额外的“问题”。在这种情况下,当然没有第二个命名空间,我无法找出一种简单的方法来确定是否存在故障元素及其内容。你有什么建议吗? - JonP
请在问题中附上一个SOAP故障响应的示例,我会查看一下。 - MrCode
完成 - 非常感谢您查看此内容。使用 Soap Client 一切似乎变得更加容易。 - JonP
好的 - 我现在明白了 - 我错过了“children”的三倍复数(这是一个词吗?)。 这似乎很奇怪。 非常感谢。 - JonP
让这个更清晰一些... $ns = $obj->getNamespaces(true); $fault = $obj->children($ns['SOAP-ENV'])->Body->children($ns['SOAP-ENV'])->children(); - strattonn

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