【问题标题】:Soap Response into JSON Array肥皂响应到 JSON 数组
【发布时间】:2015-07-07 21:37:36
【问题描述】:

我已经启动并运行了这个 API,但是在一个完整的回合中我觉得不舒服.. 我的问题是他们的响应有 soap: 前缀在一些索引上,我无法让它们正常工作注册这些前缀。所以我解决问题的方法是减去肥皂:字符串开头和结尾的字符,然后变成 JSON .. 是不是很乱??

也许我没有为soap和pur正确定义前缀,但我根本无法让它工作,一直说前缀未定义。

这是我的代码

<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);


//variables from quoting system
    $quote_client_id = $_GET['quote_client_id'];
    $quote_billterms = $_GET['quote_billterms'];
    $quote_ship_date = $_GET['quote_ship_date'];

    //convert time to ISO 8601 format
        $quote_ship_date = (new DateTime($quote_ship_date))->format('c');

    //shipper variables
        $quote_shipper_postalcode = $_GET['quote_shipper_postalcode'];
        $quote_shipper_country = $_GET['quote_shipper_country'];
        $quote_shipper_state = $_GET['quote_shipper_state'];
        $quote_shipper_city = $_GET['quote_shipper_city'];

    //consignee variables
        $quote_consignee_postalcode = $_GET['quote_consignee_postalcode'];
        $quote_consignee_country = $_GET['quote_consignee_country'];
        $quote_consignee_state = $_GET['quote_consignee_state'];
        $quote_consignee_city = $_GET['quote_consignee_city'];

    //package info
        $quote_weight = $_GET['quote_weight'];
        $quote_l = $_GET['quote_l'];
        $quote_w = $_GET['quote_w'];
        $quote_h = $_GET['quote_h'];
        $quote_quantity = $_GET['quote_quantity'];


//XML Request
    $xml = "<?xml version='1.0' encoding='utf-8'?>
        <soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:pur='http://PurolatorServices.com/'>
          <soap:Body>
            <pur:GetRates>
              <pur:request>
                <pur:Credentials>
                  <pur:UserName>username</pur:UserName>
                  <pur:Password>pw</pur:Password>
                  <pur:ClientID>clientid</pur:ClientID>
                </pur:Credentials>
                <pur:OrderNumber>TEST</pur:OrderNumber>
                <pur:ShipDate>" . $quote_ship_date . "</pur:ShipDate>
                <pur:BillingOption>" . $quote_billterms . "</pur:BillingOption>
                <pur:ShipFromAddress>
                  <pur:City>" . $quote_shipper_city . "</pur:City>
                  <pur:StateProv>" . $quote_shipper_state . "</pur:StateProv>
                  <pur:PostalCode>" . $quote_shipper_postalcode . "</pur:PostalCode>
                  <pur:Country>" . $quote_shipper_country . "</pur:Country>
                </pur:ShipFromAddress>
                <pur:ShipToAddress>
                  <pur:City>" . $quote_consignee_city . "</pur:City>
                  <pur:StateProv>" . $quote_consignee_state . "</pur:StateProv>
                  <pur:PostalCode>" . $quote_consignee_postalcode . "</pur:PostalCode>
                  <pur:Country>" . $quote_consignee_country . "</pur:Country>
                </pur:ShipToAddress>
                <pur:Currency>USD</pur:Currency>
                <pur:Packages>
                  <pur:RequestPackageV3>
                    <pur:WeightUOM>LB</pur:WeightUOM>
                    <pur:Weight>" . $quote_weight . "</pur:Weight>
                    <pur:DimL>" . $quote_l . "</pur:DimL>
                    <pur:DimW>" . $quote_w . "</pur:DimW>
                    <pur:DimH>" . $quote_h . "</pur:DimH>
                  </pur:RequestPackageV3>
                </pur:Packages>
              </pur:request>
            </pur:GetRates>
          </soap:Body>
        </soap:Envelope>
    ";


//XML Request Headers for POST
    $headers = array(
        "POST /WebServices/ShippingServicesv3.asmx HTTP/1.1",
        "Host: sandbox.purolatorshipping.com",
        "Content-Type: text/xml; charset=utf-8",
        "Content-Length: " . strlen($xml) . "",
        "SOAPAction: http://PurolatorServices.com/GetRates"
    ); 

//SOAP URL
    $url = "http://sandbox.purolatorshipping.com/WebServices/ShippingServicesV3.asmx";

//Initialize cURL and pull together Request and Headers
    $ch = curl_init();

    //pass curl options
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, false);

    //Execute the cURL
        $response = curl_exec($ch);     
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $header = substr($response, 0, $header_size);

        //had to subtract the header, and the soap footers since I couldn't get the soap name spaces working correctly ( FIND A FIX FOR THIS  )
            $body = substr($response, $header_size+18, -47);

//Close cURL connection
    curl_close($ch);

//activity::add("Purolator API Get Rate", "Purolator API Get Rate", "user", "1", "fa-ticket");

//load response into xml and json
    $xml_load =simplexml_load_string($body);
    $array  = json_decode(json_encode($xml_load) , 1);

//Loop through the different services
    foreach ($array['Rates']['RateV3'] as $obj_key =>$row) {

    //Shipment Method
        echo "Ship Method " . $row['ShipMethod'] . "<br>";

    // Delivery Date
        echo "Estimated Delivery Date " . $row['EstimatedDeliveryDate'] . "<br>";

    // Estimated Rate
        echo "Rate " . $row['EstimatedRate'] . "<br>";

    // Accessorials
        echo "Fuel " . $row['RateDetails']['KeyValueDecimal'][4]['Value'] . "<br>";

        echo "<br>";
    }

var_dump($xml_load);

这是我得到的回复

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetRatesResponse xmlns="http://PurolatorServices.com/"><GetRatesResult><Status>0</Status><Packages /><TotalShipping>0</TotalShipping><Rates><RateV3><ShipMethod>Ground</ShipMethod><EstimatedDeliveryDate>2015-07-13T05:00:00+00:00</EstimatedDeliveryDate><EstimatedRate>23.46000</EstimatedRate><IsAvailable>true</IsAvailable><RateDetails><KeyValueDecimal><Key>Total</Key><Value>23.46000</Value></KeyValueDecimal><KeyValueDecimal><Key>Tariff</Key><Value>19.80000</Value></KeyValueDecimal><KeyValueDecimal><Key>Beyond</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Rural</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Fuel</Key><Value>3.66000</Value></KeyValueDecimal><KeyValueDecimal><Key>Surcharges</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Insurance</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Taxes</Key><Value>0</Value></KeyValueDecimal></RateDetails></RateV3><RateV3><ShipMethod>Express</ShipMethod><EstimatedDeliveryDate>2015-07-08T05:00:00+00:00</EstimatedDeliveryDate><EstimatedRate>49.41000</EstimatedRate><IsAvailable>true</IsAvailable><RateDetails><KeyValueDecimal><Key>Total</Key><Value>49.41000</Value></KeyValueDecimal><KeyValueDecimal><Key>Tariff</Key><Value>41.70000</Value></KeyValueDecimal><KeyValueDecimal><Key>Beyond</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Rural</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Fuel</Key><Value>7.71000</Value></KeyValueDecimal><KeyValueDecimal><Key>Surcharges</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Insurance</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Taxes</Key><Value>0</Value></KeyValueDecimal></RateDetails></RateV3></Rates></GetRatesResult></GetRatesResponse></soap:Body></soap:Envelope>

那么我该如何接收该响应并将其转换为 JSON?

感谢您的帮助,请轻松编写我的代码:D

【问题讨论】:

  • 我觉得这是不恰当的,但我得到了它的工作,以获取 cURL 响应并替换任何肥皂实例:用空白 $test = str_replace("soap:","",$response);
  • 为什么要手动构建 SOAP 信封并解析响应,而不是使用适当的 SOAP 客户端?使用合适的 SOAP 客户端,整个问题就迎刃而解了,因为您不需要进行所有这些 XML 转换。
  • 我从他们的示例代码构建了这个,我尝试使用soap客户端来获取前缀以适当地定义,但无法让它工作。
  • 好吧。我的建议是放弃那些糟糕的示例代码并使用实际的 SOAP 客户端,例如 PHP 内置的 SoapClient 类。

标签: php json xml web-services soap


【解决方案1】:

那么我该如何接收该响应并将其转换为 JSON?

响应包含多个命名空间。命名空间是 JSON 根本不支持的概念。因此,将响应转换为 JSON 听起来是一个非常糟糕的主意,因为它 - 在很大程度上 - 不兼容

为了明确这一点:XML 中表示的数据已经没有与 JSON 不兼容的命名空间。存在使用 XML 进行 JSON 序列化的某些形式(JsonDOM、JsonML、Badgerfish、JSONx - all supported for PHP's DOMDocument via Fluent DOM),但需要您自己决定使用哪种工具以及处理哪些数据。

例如,对于您的 SOAP 响应,您很可能对响应主体感兴趣,而不是整个 SOAP XML。为此,您需要一个 XML 解析器 first:

但仅靠解析器是不行的。您还需要解析 SOAP 结果。上面已经列出了一个参考问题。或许命名空间XML命名空间这个词可能会帮助你找到更多。


对于您的 SOAP 请求,我建议将其包装起来。例如,为它使用像 SoapClient 这样的预制组件。特别是如果有 WSDL。并不是说你重新发明了轮子。如果有 WSDL,请查看是否可以使用替代 API 访问,例如与 SOAP API 保持一致的基于 XML 或 JSON 的 rest API。

【讨论】:

    猜你喜欢
    • 2019-10-21
    • 2014-09-05
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多